]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/cifsd/pack.c
separate MSCHAP(v2) and NTLM(v2) authentication
[plan9front.git] / sys / src / cmd / ip / cifsd / pack.c
1 #include <u.h>
2 #include <libc.h>
3 #include "dat.h"
4 #include "fns.h"
5
6 int
7 unpack(uchar *b, uchar *p, uchar *e, char *f, ...)
8 {
9         va_list a;
10         int r;
11
12         va_start(a, f);
13         r = vunpack(b, p, e, f, a);
14         va_end(a);
15         return r;
16 }
17
18 int
19 pack(uchar *b, uchar *p, uchar *e, char *f, ...)
20 {
21         va_list a;
22         int r;
23
24         va_start(a, f);
25         r = vpack(b, p, e, f, a);
26         va_end(a);
27         return r;
28 }
29
30 int
31 vunpack(uchar *b, uchar *p, uchar *e, char *f, va_list a)
32 {
33         struct {
34                 void *prev;
35                 int o, c, i;
36                 uchar *e;
37                 uchar **ap, **ae;
38         } sub[8], *sp, *sa;
39         int (*funpack)(uchar *, uchar *, uchar *, void *);
40         char c, ff[2];
41         int i, x, n;
42         uchar *t;
43
44         memset(sub, 0, sizeof(sub));
45         for(sp = sub; sp < sub+nelem(sub); sp++){
46                 sp->o = -1;
47                 sp->c = -1;
48                 sp->i = 1;
49         }
50
51         t = p;
52         sp = nil;
53         sa = sub;
54         while(c = *f++){
55                 switch(c){
56                 case '_':
57                 case 'b':
58                         if(p >= e)
59                                 return 0;
60                         if(c == 'b')
61                                 *va_arg(a, int*) = *p;
62                         p++;
63                         break;
64                 case 'w':
65                         if(p+1 >= e)
66                                 return 0;
67                         *va_arg(a, int*) = (int)p[1]<<8 | (int)p[0];
68                         p+=2;
69                         break;
70                 case 'l':
71                         if(p+3 >= e)
72                                 return 0;
73                         *va_arg(a, int*) = (int)p[3]<<24 | (int)p[2]<<16 | (int)p[1]<<8 | (int)p[0];
74                         p+=4;
75                         break;
76                 case 'v':
77                         if(p+7 >= e)
78                                 return 0;
79                         *va_arg(a, vlong*) =
80                                         (vlong)p[7]<<56 |
81                                         (vlong)p[6]<<48 |
82                                         (vlong)p[5]<<40 |
83                                         (vlong)p[4]<<32 |
84                                         (vlong)p[3]<<24 |
85                                         (vlong)p[2]<<16 |
86                                         (vlong)p[1]<<8 |
87                                         (vlong)p[0];
88                         p += 8;
89                         break;
90                 case '%':
91                         x = *f++ - '0';
92                         while((p - b) % x)
93                                 p++;
94                         break;
95                 case 'f':
96                         funpack = va_arg(a, void*);
97                         if((n = funpack(b, p, e, va_arg(a, void*))) == 0)
98                                 return 0;
99                         p += n;
100                         break;
101                 case '#':
102                 case '@':
103                         x = *f++ - '0';
104                         ff[0] = *f++;
105                         ff[1] = 0;
106                         if((n = unpack(b, p, e, ff, &i)) == 0)
107                                 return 0;
108                         p += n;
109                         if(c == '#'){
110                                 sub[x].c = i;
111                         } else {
112                                 sub[x].o = i;
113                         }
114                         break;
115                 case '{':
116                 case '[':
117                         sa->prev = sp;
118                         sp = sa++;
119                         if(*f == '*'){
120                                 sp->i = f[1]-'0';
121                                 f += 2;
122                         }
123                         if(sp->o >= 0 && b + sp->o > p)
124                                 if(b + sp->o <= e || *f != '?')
125                                         p = b + sp->o;
126                         if(*f == '?')
127                                 f++;
128                         sp->o = p - b;
129                         sp->e = e;
130                         if(sp->c >= 0){
131                                 e = p + sp->c * sp->i;
132                                 if(e > sp->e)
133                                         return 0;
134                         }
135                         if(c == '['){
136                                 sp->ap = va_arg(a, uchar**);
137                                 sp->ae = va_arg(a, uchar**);
138                         }
139                         break;
140                 case '}':
141                 case ']':
142                         e = sp->e;
143                         if(sp->c < 0)
144                                 sp->c = ((p - (b + sp->o))+sp->i-1)/sp->i;
145                         p = b + sp->o + sp->c * sp->i;
146                         if(p > e)
147                                 return 0;
148                         if(sp->ap)
149                                 *sp->ap = b + sp->o;
150                         if(sp->ae)
151                                 *sp->ae = p;
152                         sp = sp->prev;
153                         break;
154                 case '.':
155                         *va_arg(a, uchar**) = p;
156                         break;
157                 }
158                 if(p > e)
159                         return 0;
160         }
161         return p - t;
162 }
163
164 vpack(uchar *b, uchar *p, uchar *e, char *f, va_list a)
165 {
166         struct {
167                 void *prev;
168                 int o, i;
169                 uchar *wc, *wo, wcf, wof;
170         } sub[8], *sp, *sa;
171         int (*fpack)(uchar *, uchar *, uchar *, void *);
172         char c, ff[2];
173         int i, x, n;
174         vlong v;
175         uchar *t;
176
177         memset(sub, 0, sizeof(sub));
178         for(sp = sub; sp < sub+nelem(sub); sp++){
179                 sp->o = -1;
180                 sp->i = 1;
181         }
182
183         t = p;
184         sp = nil;
185         sa = sub;
186         while(c = *f++){
187                 switch(c){      
188                 case '_':
189                 case 'b':
190                         if(p >= e)
191                                 return 0;
192                         if(c == 'b')
193                                 *p++ = va_arg(a, int);
194                         else
195                                 *p++ = 0;
196                         break;
197                 case 'w':
198                         if(p+1 >= e)
199                                 return 0;
200                         i = va_arg(a, int);
201                         *p++ = i & 0xFF;
202                         *p++ = i>>8 & 0xFF;
203                         break;
204                 case 'l':
205                         if(p+3 >= e)
206                                 return 0;
207                         i = va_arg(a, int);
208                         *p++ = i & 0xFF;
209                         *p++ = i>>8 & 0xFF;
210                         *p++ = i>>16 & 0xFF;
211                         *p++ = i>>24 & 0xFF;
212                         break;
213                 case 'v':
214                         if(p+7 >= e)
215                                 return 0;
216                         v = va_arg(a, vlong);
217                         *p++ = v & 0xFF;
218                         *p++ = v>>8 & 0xFF;
219                         *p++ = v>>16 & 0xFF;
220                         *p++ = v>>24 & 0xFF;
221                         *p++ = v>>32 & 0xFF;
222                         *p++ = v>>40 & 0xFF;
223                         *p++ = v>>48 & 0xFF;
224                         *p++ = v>>56 & 0xFF;
225                         break;
226                 case '%':
227                         x = *f++ - '0';
228                         while((p - b) % x){
229                                 if(p >= e)
230                                         return 0;
231                                 *p++ = 0;
232                         }
233                         break;
234                 case 'f':
235                         fpack = va_arg(a, void*);
236                         if((n = fpack(b, p, e, va_arg(a, void*))) == 0)
237                                 return 0;
238                         p += n;
239                         break;
240                 case '#':
241                 case '@':
242                         x = *f++ - '0';
243                         ff[0] = *f++;
244                         ff[1] = 0;
245                         if((n = pack(b, p, e, ff, 0)) == 0)
246                                 return 0;
247                         if(c == '#'){
248                                 sub[x].wc = p;
249                                 sub[x].wcf = ff[0];
250                         } else {
251                                 sub[x].wo = p;
252                                 sub[x].wof = ff[0];
253                         }
254                         p += n;
255                         break;
256                 case '{':
257                 case '[':
258                         sa->prev = sp;
259                         sp = sa++;
260                         if(*f == '*'){
261                                 sp->i = f[1]-'0';
262                                 f += 2;
263                         }
264                         if(*f == '?')
265                                 f++;
266                         sp->o = p - b;
267                         if(c == '['){
268                                 uchar *s, *se;
269
270                                 s = va_arg(a, uchar*);
271                                 se = va_arg(a, uchar*);
272                                 n = se - s;
273                                 if(n < 0 || p + n > e)
274                                         return 0;
275                                 if(p != s)
276                                         memmove(p, s, n);
277                                 p += n;
278                         }
279                         break;
280                 case '}':
281                 case ']':
282                         n = ((p - (b + sp->o))+sp->i-1)/sp->i;
283                         p = b + sp->o + n * sp->i;
284                         if(sp->wc){
285                                 ff[0] = sp->wcf;
286                                 ff[1] = 0;
287                                 pack(b, sp->wc, e, ff, n);
288                         }
289                         if(sp->wo){
290                                 ff[0] = sp->wof;
291                                 ff[1] = 0;
292                                 pack(b, sp->wo, e, ff, sp->o);
293                         }
294                         sp = sp->prev;
295                         break;
296                 case '.':
297                         *va_arg(a, uchar**) = p;
298                         break;
299                 }
300                 if(p > e)
301                         return 0;
302         }
303         return p - t;
304 }
305