1 #include "headers.h"
2
3 #define BUFFER 1
4 #define STRUCT 2
5 #define PUSHED 4
6
7 struct SmbBuffer {
8 uchar *buf;
9 ulong realmaxlen;
10 ulong maxlen;
11 ulong rn;
12 ulong wn;
13 ulong savewn;
14 int flags;
15 };
16
17 void
smbbufferreset(SmbBuffer * s)18 smbbufferreset(SmbBuffer *s)
19 {
20 if (s == nil)
21 return;
22 s->rn = 0;
23 s->wn = 0;
24 s->flags &= ~PUSHED;
25 }
26
27 void
smbbuffersetbuf(SmbBuffer * s,void * p,ulong maxlen)28 smbbuffersetbuf(SmbBuffer *s, void *p, ulong maxlen)
29 {
30 s->realmaxlen = s->maxlen = maxlen;
31 if (s->buf) {
32 if (s->flags & BUFFER)
33 free(s->buf);
34 s->buf = nil;
35 }
36 s->flags &= ~BUFFER;
37 if (p)
38 s->buf = p;
39 else {
40 s->buf = smbemalloc(maxlen);
41 s->flags |= BUFFER;
42 }
43 smbbufferreset(s);
44 }
45
46 SmbBuffer *
smbbufferinit(void * base,void * bdata,ulong blen)47 smbbufferinit(void *base, void *bdata, ulong blen)
48 {
49 SmbBuffer *b;
50 b = smbemalloc(sizeof(*b));
51 b->buf = base;
52 b->flags = STRUCT;
53 b->rn = (uchar *)bdata - (uchar *)base;
54 b->wn = b->rn + blen;
55 b->realmaxlen = b->maxlen = b->wn;
56 return b;
57 }
58
59 int
smbbufferalignl2(SmbBuffer * s,int al2)60 smbbufferalignl2(SmbBuffer *s, int al2)
61 {
62 ulong mask, newn;
63 mask = (1 << al2) - 1;
64 newn = (s->wn + mask) & ~mask;
65 if (newn != s->wn) {
66 if (newn > s->maxlen)
67 return 0;
68 s->wn = newn;
69 }
70 return 1;
71 }
72
73 int
smbbufferputb(SmbBuffer * s,uchar b)74 smbbufferputb(SmbBuffer *s, uchar b)
75 {
76 if (s->wn >= s->maxlen)
77 return 0;
78 s->buf[s->wn++] = b;
79 return 1;
80 }
81
82 ulong
smbbufferspace(SmbBuffer * sess)83 smbbufferspace(SmbBuffer *sess)
84 {
85 return sess->maxlen - sess->wn;
86 }
87
88 int
smbbufferoffsetputs(SmbBuffer * sess,ulong offset,ushort s)89 smbbufferoffsetputs(SmbBuffer *sess, ulong offset, ushort s)
90 {
91 if (offset + 2 > sess->wn)
92 return 0;
93 smbhnputs(sess->buf + offset, s);
94 return 1;
95 }
96
97 int
smbbufferputs(SmbBuffer * sess,ushort s)98 smbbufferputs(SmbBuffer *sess, ushort s)
99 {
100 if (sess->wn + sizeof(ushort) > sess->maxlen)
101 return 0;
102 smbhnputs(sess->buf + sess->wn, s);
103 sess->wn += sizeof(ushort);
104 return 1;
105 }
106
107 int
smbbufferputl(SmbBuffer * s,ulong l)108 smbbufferputl(SmbBuffer *s, ulong l)
109 {
110 if (s->wn + sizeof(ulong) > s->maxlen)
111 return 0;
112 smbhnputl(s->buf + s->wn, l);
113 s->wn += sizeof(ulong);
114 return 1;
115 }
116
117 int
smbbufferputv(SmbBuffer * s,vlong v)118 smbbufferputv(SmbBuffer *s, vlong v)
119 {
120 if (s->wn + sizeof(vlong) > s->maxlen)
121 return 0;
122 smbhnputv(s->buf + s->wn, v);
123 s->wn += sizeof(vlong);
124 return 1;
125 }
126
127 int
smbbufferputbytes(SmbBuffer * s,void * data,ulong datalen)128 smbbufferputbytes(SmbBuffer *s, void *data, ulong datalen)
129 {
130 if (s->wn + datalen > s->maxlen)
131 return 0;
132 if (data)
133 memcpy(s->buf + s->wn, data, datalen);
134 s->wn += datalen;
135 return 1;
136 }
137
138 int
smbbufferputstring(SmbBuffer * b,SmbPeerInfo * p,ulong flags,char * string)139 smbbufferputstring(SmbBuffer *b, SmbPeerInfo *p, ulong flags, char *string)
140 {
141 int n = smbstringput(p, flags, b->buf, b->wn, b->maxlen, string);
142 if (n <= 0)
143 return 0;
144 b->wn += n;
145 return 1;
146 }
147
148 int
smbbufferputstrn(SmbBuffer * s,char * string,int size,int upcase)149 smbbufferputstrn(SmbBuffer *s, char *string, int size, int upcase)
150 {
151 int n = smbstrnput(s->buf, s->wn, s->maxlen, string, size, upcase);
152 if (n <= 0)
153 return 0;
154 s->wn += n;
155 return 1;
156 }
157
158 ulong
smbbufferwriteoffset(SmbBuffer * s)159 smbbufferwriteoffset(SmbBuffer *s)
160 {
161 return s->wn;
162 }
163
164 ulong
smbbufferwritemaxoffset(SmbBuffer * s)165 smbbufferwritemaxoffset(SmbBuffer *s)
166 {
167 return s->maxlen;
168 }
169
170 ulong
smbbufferreadoffset(SmbBuffer * s)171 smbbufferreadoffset(SmbBuffer *s)
172 {
173 return s->rn;
174 }
175
176 void *
smbbufferreadpointer(SmbBuffer * s)177 smbbufferreadpointer(SmbBuffer *s)
178 {
179 return s->buf + s->rn;
180 }
181
182 void *
smbbufferwritepointer(SmbBuffer * s)183 smbbufferwritepointer(SmbBuffer *s)
184 {
185 return s->buf + s->wn;
186 }
187
188 ulong
smbbufferwritespace(SmbBuffer * b)189 smbbufferwritespace(SmbBuffer *b)
190 {
191 return b->maxlen - b->wn;
192 }
193
194 SmbBuffer *
smbbuffernew(ulong maxlen)195 smbbuffernew(ulong maxlen)
196 {
197 SmbBuffer *b;
198 b = smbemalloc(sizeof(SmbBuffer));
199 b->buf = smbemalloc(maxlen);
200 b->realmaxlen = b->maxlen = maxlen;
201 b->rn = 0;
202 b->wn = 0;
203 b->flags = STRUCT | BUFFER;
204 return b;
205 }
206
207 void
smbbufferfree(SmbBuffer ** bp)208 smbbufferfree(SmbBuffer **bp)
209 {
210 SmbBuffer *b = *bp;
211 if (b) {
212 if (b->flags & BUFFER) {
213 free(b->buf);
214 b->buf = nil;
215 b->flags &= ~BUFFER;
216 }
217 if (b->flags & STRUCT)
218 free(b);
219 *bp = nil;
220 }
221 }
222
223 uchar *
smbbufferbase(SmbBuffer * b)224 smbbufferbase(SmbBuffer *b)
225 {
226 return b->buf;
227 }
228
229 int
smbbuffergetbytes(SmbBuffer * b,void * buf,ulong len)230 smbbuffergetbytes(SmbBuffer *b, void *buf, ulong len)
231 {
232 if (b->rn + len > b->wn)
233 return 0;
234 if (buf)
235 memcpy(buf, b->buf + b->rn, len);
236 b->rn += len;
237 return 1;
238 }
239
240 void
smbbuffersetreadlen(SmbBuffer * b,ulong len)241 smbbuffersetreadlen(SmbBuffer *b, ulong len)
242 {
243 b->wn = b->rn + len;
244 }
245
246 int
smbbuffertrimreadlen(SmbBuffer * b,ulong len)247 smbbuffertrimreadlen(SmbBuffer *b, ulong len)
248 {
249 if (b->rn + len > b->wn)
250 return 0;
251 else if (b->rn + len < b->wn)
252 b->wn = b->rn + len;
253 return 1;
254 }
255
256 int
smbbuffergets(SmbBuffer * b,ushort * sp)257 smbbuffergets(SmbBuffer *b, ushort *sp)
258 {
259 if (b->rn + 2 > b->wn)
260 return 0;
261 *sp = smbnhgets(b->buf + b->rn);
262 b->rn += 2;
263 return 1;
264 }
265
266 int
smbbuffergetstrn(SmbBuffer * b,ushort size,char ** sp)267 smbbuffergetstrn(SmbBuffer *b, ushort size, char **sp)
268 {
269 uchar *np;
270 if (size > b->wn - b->rn)
271 return 0;
272 np = memchr(b->buf + b->rn, 0, size);
273 if (np == nil)
274 return 0;
275 *sp = strdup((char *)b->buf + b->rn);
276 b->rn += size;
277 return 1;
278 }
279
280 int
smbbuffergetstr(SmbBuffer * b,ulong flags,char ** sp)281 smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp)
282 {
283 int c;
284 char *p;
285 uchar *np;
286
287 np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
288 if (np == nil)
289 return 0;
290 *sp = strdup((char *)b->buf + b->rn);
291 for (p = *sp; *p != 0; p++) {
292 c = *p;
293 if (c >= 'a' && c <= 'z' && (flags & SMB_STRING_UPCASE))
294 *p = toupper(c);
295 else if (c == '/' && (flags & SMB_STRING_REVPATH))
296 *p = '\\';
297 else if (c == '\\' && (flags & SMB_STRING_PATH))
298 *p = '/';
299 else if (smbglobals.convertspace){
300 if (c == 0xa0 && (flags & SMB_STRING_REVPATH))
301 *p = ' ';
302 else if (c == ' ' && (flags & SMB_STRING_PATH))
303 *p = 0xa0;
304 }
305 }
306 b->rn = np - b->buf + 1;
307 return 1;
308 }
309
310 int
smbbuffergetstrinline(SmbBuffer * b,char ** sp)311 smbbuffergetstrinline(SmbBuffer *b, char **sp)
312 {
313 uchar *np;
314 np = memchr(b->buf + b->rn, 0, b->wn - b->rn);
315 if (np == nil)
316 return 0;
317 *sp = (char *)b->buf + b->rn;
318 b->rn = np - b->buf + 1;
319 return 1;
320 }
321
322 int
smbbuffergetucs2(SmbBuffer * b,ulong flags,char ** sp)323 smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp)
324 {
325 uchar *bdata = b->buf + b->rn;
326 uchar *edata = b->buf + b->wn;
327 Rune r;
328 int l;
329 char *p, *q;
330 uchar *savebdata;
331 int first;
332
333 l = 0;
334 if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1)
335 bdata++;
336 savebdata = bdata;
337 first = 1;
338 do {
339 if (bdata + 2 > edata) {
340 l++;
341 break;
342 }
343 r = smbnhgets(bdata); bdata += 2;
344 if (first && (flags & SMB_STRING_PATH) && r != '\\')
345 l++;
346 first = 0;
347 if (flags & SMB_STRING_CONVERT_MASK)
348 r = smbruneconvert(r, flags);
349 l += runelen(r);
350 } while (r != 0);
351 p = smbemalloc(l);
352 bdata = savebdata;
353 q = p;
354 first = 1;
355 do {
356 if (bdata + 2 > edata) {
357 *q = 0;
358 break;
359 }
360 r = smbnhgets(bdata); bdata += 2;
361 if (first && (flags & SMB_STRING_PATH) && r != '\\')
362 *q++ = '/';
363 first = 0;
364 if (flags & SMB_STRING_CONVERT_MASK)
365 r = smbruneconvert(r, flags);
366 q += runetochar(q, &r);
367 } while (r != 0);
368 b->rn = bdata - b->buf;
369 *sp = p;
370 return 1;
371 }
372
373 int
smbbuffergetstring(SmbBuffer * b,SmbHeader * h,ulong flags,char ** sp)374 smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp)
375 {
376 if (flags & SMB_STRING_UNICODE)
377 return smbbuffergetucs2(b, flags, sp);
378 else if (flags & SMB_STRING_ASCII)
379 return smbbuffergetstr(b, flags, sp);
380 else if (h->flags2 & SMB_FLAGS2_UNICODE)
381 return smbbuffergetucs2(b, flags, sp);
382 else
383 return smbbuffergetstr(b, flags, sp);
384 }
385
386 void *
smbbufferpointer(SmbBuffer * b,ulong offset)387 smbbufferpointer(SmbBuffer *b, ulong offset)
388 {
389 return b->buf + offset;
390 }
391
392 int
smbbuffergetb(SmbBuffer * b,uchar * bp)393 smbbuffergetb(SmbBuffer *b, uchar *bp)
394 {
395 if (b->rn < b->wn) {
396 *bp = b->buf[b->rn++];
397 return 1;
398 }
399 return 0;
400 }
401
402 int
smbbuffergetl(SmbBuffer * b,ulong * lp)403 smbbuffergetl(SmbBuffer *b, ulong *lp)
404 {
405 if (b->rn + 4 <= b->wn) {
406 *lp = smbnhgetl(b->buf + b->rn);
407 b->rn += 4;
408 return 1;
409 }
410 return 0;
411 }
412
413 int
smbbuffergetv(SmbBuffer * b,vlong * vp)414 smbbuffergetv(SmbBuffer *b, vlong *vp)
415 {
416 if (b->rn + 8 <= b->wn) {
417 *vp = smbnhgetv(b->buf + b->rn);
418 b->rn += 8;
419 return 1;
420 }
421 return 0;
422 }
423
424 ulong
smbbufferreadspace(SmbBuffer * b)425 smbbufferreadspace(SmbBuffer *b)
426 {
427 return b->wn - b->rn;
428 }
429
430 void
smbbufferwritelimit(SmbBuffer * b,ulong limit)431 smbbufferwritelimit(SmbBuffer *b, ulong limit)
432 {
433 if (b->rn + limit < b->maxlen)
434 b->maxlen = b->rn + limit;
435 }
436
437 int
smbbufferreadskipto(SmbBuffer * b,ulong offset)438 smbbufferreadskipto(SmbBuffer *b, ulong offset)
439 {
440 if (offset < b->rn || offset >= b->wn)
441 return 0;
442 b->rn = offset;
443 return 1;
444 }
445
446 int
smbbufferpushreadlimit(SmbBuffer * b,ulong limit)447 smbbufferpushreadlimit(SmbBuffer *b, ulong limit)
448 {
449 if (b->flags & PUSHED)
450 return 0;
451 if (limit > b->wn || limit < b->rn)
452 return 0;
453 b->savewn = b->wn;
454 b->wn = limit;
455 b->flags |= PUSHED;
456 return 1;
457 }
458
459 int
smbbufferpopreadlimit(SmbBuffer * b)460 smbbufferpopreadlimit(SmbBuffer *b)
461 {
462 if ((b->flags & PUSHED) == 0)
463 return 0;
464 b->wn = b->savewn;
465 b->flags &= ~PUSHED;
466 return 1;
467 }
468
469 int
smbbufferwritebackup(SmbBuffer * b,ulong offset)470 smbbufferwritebackup(SmbBuffer *b, ulong offset)
471 {
472 if (offset >= b->rn && offset <= b->wn) {
473 b->wn = offset;
474 return 1;
475 }
476 return 0;
477 }
478
479 int
smbbufferreadbackup(SmbBuffer * b,ulong offset)480 smbbufferreadbackup(SmbBuffer *b, ulong offset)
481 {
482 if (offset <= b->rn) {
483 b->rn = offset;
484 return 1;
485 }
486 return 0;
487 }
488
489 int
smbbufferfixuprelatives(SmbBuffer * b,ulong fixupoffset)490 smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset)
491 {
492 ulong fixval;
493 if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
494 return 0;
495 fixval = b->wn - fixupoffset - 2;
496 if (fixval > 65535)
497 return 0;
498 smbhnputs(b->buf + fixupoffset, fixval);
499 return 1;
500 }
501
502 int
smbbufferfixuprelativel(SmbBuffer * b,ulong fixupoffset)503 smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset)
504 {
505 ulong fixval;
506 if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
507 return 0;
508 fixval = b->wn - fixupoffset - 4;
509 smbhnputl(b->buf + fixupoffset, fixval);
510 return 1;
511 }
512
513 int
smbbufferfixupabsolutes(SmbBuffer * b,ulong fixupoffset)514 smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset)
515 {
516 if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
517 return 0;
518 if (b->wn > 65535)
519 return 0;
520 smbhnputs(b->buf + fixupoffset, b->wn);
521 return 1;
522 }
523
524 int
smbbufferfixupl(SmbBuffer * b,ulong fixupoffset,ulong fixupval)525 smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong fixupval)
526 {
527 if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
528 return 0;
529 smbhnputl(b->buf + fixupoffset, fixupval);
530 return 1;
531 }
532
533 int
smbbufferfixupabsolutel(SmbBuffer * b,ulong fixupoffset)534 smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset)
535 {
536 if (fixupoffset < b->rn || fixupoffset > b->wn - 2)
537 return 0;
538 smbhnputl(b->buf + fixupoffset, b->wn);
539 return 1;
540 }
541
542 int
smbbufferfixuprelativeinclusivel(SmbBuffer * b,ulong fixupoffset)543 smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset)
544 {
545 if (fixupoffset < b->rn || fixupoffset > b->wn - 4)
546 return 0;
547 smbhnputl(b->buf + fixupoffset, b->wn - fixupoffset);
548 return 1;
549 }
550
551 int
smbbufferfill(SmbBuffer * b,uchar val,ulong len)552 smbbufferfill(SmbBuffer *b, uchar val, ulong len)
553 {
554 if (b->maxlen - b->wn < len)
555 return 0;
556 memset(b->buf + b->wn, val, len);
557 b->wn += len;
558 return 1;
559 }
560
561 int
smbbufferoffsetgetb(SmbBuffer * b,ulong offset,uchar * bp)562 smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp)
563 {
564 if (offset >= b->rn && offset + 1 <= b->wn) {
565 *bp = b->buf[b->rn + offset];
566 return 1;
567 }
568 return 0;
569 }
570
571 int
smbbuffercopy(SmbBuffer * to,SmbBuffer * from,ulong amount)572 smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount)
573 {
574 if (smbbufferreadspace(from) < amount)
575 return 0;
576 if (smbbufferputbytes(to, smbbufferreadpointer(from), amount)) {
577 assert(smbbuffergetbytes(from, nil, amount));
578 return 1;
579 }
580 return 0;
581 }
582
583 int
smbbufferoffsetcopystr(SmbBuffer * b,ulong offset,char * buf,int buflen,int * lenp)584 smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp)
585 {
586 uchar *np;
587 if (offset < b->rn || offset >= b->wn)
588 return 0;
589 np = memchr(b->buf + offset, 0, b->wn - offset);
590 if (np == nil)
591 return 0;
592 *lenp = np - (b->buf + offset) + 1;
593 if (*lenp > buflen)
594 return 0;
595 memcpy(buf, b->buf + offset, *lenp);
596 return 1;
597 }
598