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 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 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 * 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 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 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 83 smbbufferspace(SmbBuffer *sess) 84 { 85 return sess->maxlen - sess->wn; 86 } 87 88 int 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 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 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 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 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 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 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 159 smbbufferwriteoffset(SmbBuffer *s) 160 { 161 return s->wn; 162 } 163 164 ulong 165 smbbufferwritemaxoffset(SmbBuffer *s) 166 { 167 return s->maxlen; 168 } 169 170 ulong 171 smbbufferreadoffset(SmbBuffer *s) 172 { 173 return s->rn; 174 } 175 176 void * 177 smbbufferreadpointer(SmbBuffer *s) 178 { 179 return s->buf + s->rn; 180 } 181 182 void * 183 smbbufferwritepointer(SmbBuffer *s) 184 { 185 return s->buf + s->wn; 186 } 187 188 ulong 189 smbbufferwritespace(SmbBuffer *b) 190 { 191 return b->maxlen - b->wn; 192 } 193 194 SmbBuffer * 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 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 * 224 smbbufferbase(SmbBuffer *b) 225 { 226 return b->buf; 227 } 228 229 int 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 241 smbbuffersetreadlen(SmbBuffer *b, ulong len) 242 { 243 b->wn = b->rn + len; 244 } 245 246 int 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 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 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 281 smbbuffergetstr(SmbBuffer *b, ulong flags, char **sp) 282 { 283 uchar *np; 284 USED(flags); 285 np = memchr(b->buf + b->rn, 0, b->wn - b->rn); 286 if (np == nil) 287 return 0; 288 *sp = strdup((char *)b->buf + b->rn); 289 b->rn = np - b->buf + 1; 290 return 1; 291 } 292 293 int 294 smbbuffergetstrinline(SmbBuffer *b, char **sp) 295 { 296 uchar *np; 297 np = memchr(b->buf + b->rn, 0, b->wn - b->rn); 298 if (np == nil) 299 return 0; 300 *sp = (char *)b->buf + b->rn; 301 b->rn = np - b->buf + 1; 302 return 1; 303 } 304 305 int 306 smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp) 307 { 308 uchar *bdata = b->buf + b->rn; 309 uchar *edata = b->buf + b->wn; 310 Rune r; 311 int l; 312 char *p, *q; 313 uchar *savebdata; 314 int first; 315 316 l = 0; 317 if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1) 318 bdata++; 319 savebdata = bdata; 320 first = 1; 321 do { 322 if (bdata + 2 > edata) { 323 l++; 324 break; 325 } 326 r = smbnhgets(bdata); bdata += 2; 327 if (first && (flags & SMB_STRING_PATH) && r != '\\') 328 l++; 329 first = 0; 330 if (flags & SMB_STRING_CONVERT_MASK) 331 r = smbruneconvert(r, flags); 332 l += runelen(r); 333 } while (r != 0); 334 p = smbemalloc(l); 335 bdata = savebdata; 336 q = p; 337 first = 1; 338 do { 339 if (bdata + 2 > edata) { 340 *q = 0; 341 break; 342 } 343 r = smbnhgets(bdata); bdata += 2; 344 if (first && (flags & SMB_STRING_PATH) && r != '\\') 345 *q++ = '/'; 346 first = 0; 347 if (flags & SMB_STRING_CONVERT_MASK) 348 r = smbruneconvert(r, flags); 349 q += runetochar(q, &r); 350 } while (r != 0); 351 b->rn = bdata - b->buf; 352 *sp = p; 353 return 1; 354 } 355 356 int 357 smbbuffergetstring(SmbBuffer *b, SmbHeader *h, ulong flags, char **sp) 358 { 359 if (flags & SMB_STRING_UNICODE) 360 return smbbuffergetucs2(b, flags, sp); 361 else if (flags & SMB_STRING_ASCII) 362 return smbbuffergetstr(b, flags, sp); 363 else if (h->flags2 & SMB_FLAGS2_UNICODE) 364 return smbbuffergetucs2(b, flags, sp); 365 else 366 return smbbuffergetstr(b, flags, sp); 367 } 368 369 void * 370 smbbufferpointer(SmbBuffer *b, ulong offset) 371 { 372 return b->buf + offset; 373 } 374 375 int 376 smbbuffergetb(SmbBuffer *b, uchar *bp) 377 { 378 if (b->rn < b->wn) { 379 *bp = b->buf[b->rn++]; 380 return 1; 381 } 382 return 0; 383 } 384 385 int 386 smbbuffergetl(SmbBuffer *b, ulong *lp) 387 { 388 if (b->rn + 4 <= b->wn) { 389 *lp = smbnhgetl(b->buf + b->rn); 390 b->rn += 4; 391 return 1; 392 } 393 return 0; 394 } 395 396 int 397 smbbuffergetv(SmbBuffer *b, vlong *vp) 398 { 399 if (b->rn + 8 <= b->wn) { 400 *vp = smbnhgetv(b->buf + b->rn); 401 b->rn += 8; 402 return 1; 403 } 404 return 0; 405 } 406 407 ulong 408 smbbufferreadspace(SmbBuffer *b) 409 { 410 return b->wn - b->rn; 411 } 412 413 void 414 smbbufferwritelimit(SmbBuffer *b, ulong limit) 415 { 416 if (b->rn + limit < b->maxlen) 417 b->maxlen = b->rn + limit; 418 } 419 420 int 421 smbbufferreadskipto(SmbBuffer *b, ulong offset) 422 { 423 if (offset < b->rn || offset >= b->wn) 424 return 0; 425 b->rn = offset; 426 return 1; 427 } 428 429 int 430 smbbufferpushreadlimit(SmbBuffer *b, ulong limit) 431 { 432 if (b->flags & PUSHED) 433 return 0; 434 if (limit > b->wn || limit < b->rn) 435 return 0; 436 b->savewn = b->wn; 437 b->wn = limit; 438 b->flags |= PUSHED; 439 return 1; 440 } 441 442 int 443 smbbufferpopreadlimit(SmbBuffer *b) 444 { 445 if ((b->flags & PUSHED) == 0) 446 return 0; 447 b->wn = b->savewn; 448 b->flags &= ~PUSHED; 449 return 1; 450 } 451 452 int 453 smbbufferwritebackup(SmbBuffer *b, ulong offset) 454 { 455 if (offset >= b->rn && offset <= b->wn) { 456 b->wn = offset; 457 return 1; 458 } 459 return 0; 460 } 461 462 int 463 smbbufferreadbackup(SmbBuffer *b, ulong offset) 464 { 465 if (offset <= b->rn) { 466 b->rn = offset; 467 return 1; 468 } 469 return 0; 470 } 471 472 int 473 smbbufferfixuprelatives(SmbBuffer *b, ulong fixupoffset) 474 { 475 ulong fixval; 476 if (fixupoffset < b->rn || fixupoffset > b->wn - 2) 477 return 0; 478 fixval = b->wn - fixupoffset - 2; 479 if (fixval > 65535) 480 return 0; 481 smbhnputs(b->buf + fixupoffset, fixval); 482 return 1; 483 } 484 485 int 486 smbbufferfixuprelativel(SmbBuffer *b, ulong fixupoffset) 487 { 488 ulong fixval; 489 if (fixupoffset < b->rn || fixupoffset > b->wn - 4) 490 return 0; 491 fixval = b->wn - fixupoffset - 4; 492 smbhnputl(b->buf + fixupoffset, fixval); 493 return 1; 494 } 495 496 int 497 smbbufferfixupabsolutes(SmbBuffer *b, ulong fixupoffset) 498 { 499 if (fixupoffset < b->rn || fixupoffset > b->wn - 2) 500 return 0; 501 if (b->wn > 65535) 502 return 0; 503 smbhnputs(b->buf + fixupoffset, b->wn); 504 return 1; 505 } 506 507 int 508 smbbufferfixupl(SmbBuffer *b, ulong fixupoffset, ulong fixupval) 509 { 510 if (fixupoffset < b->rn || fixupoffset > b->wn - 4) 511 return 0; 512 smbhnputl(b->buf + fixupoffset, fixupval); 513 return 1; 514 } 515 516 int 517 smbbufferfixupabsolutel(SmbBuffer *b, ulong fixupoffset) 518 { 519 if (fixupoffset < b->rn || fixupoffset > b->wn - 2) 520 return 0; 521 smbhnputl(b->buf + fixupoffset, b->wn); 522 return 1; 523 } 524 525 int 526 smbbufferfixuprelativeinclusivel(SmbBuffer *b, ulong fixupoffset) 527 { 528 if (fixupoffset < b->rn || fixupoffset > b->wn - 4) 529 return 0; 530 smbhnputl(b->buf + fixupoffset, b->wn - fixupoffset); 531 return 1; 532 } 533 534 int 535 smbbufferfill(SmbBuffer *b, uchar val, ulong len) 536 { 537 if (b->maxlen - b->wn < len) 538 return 0; 539 memset(b->buf + b->wn, val, len); 540 b->wn += len; 541 return 1; 542 } 543 544 int 545 smbbufferoffsetgetb(SmbBuffer *b, ulong offset, uchar *bp) 546 { 547 if (offset >= b->rn && offset + 1 <= b->wn) { 548 *bp = b->buf[b->rn + offset]; 549 return 1; 550 } 551 return 0; 552 } 553 554 int 555 smbbuffercopy(SmbBuffer *to, SmbBuffer *from, ulong amount) 556 { 557 if (smbbufferreadspace(from) < amount) 558 return 0; 559 if (smbbufferputbytes(to, smbbufferreadpointer(from), amount)) { 560 assert(smbbuffergetbytes(from, nil, amount)); 561 return 1; 562 } 563 return 0; 564 } 565 566 int 567 smbbufferoffsetcopystr(SmbBuffer *b, ulong offset, char *buf, int buflen, int *lenp) 568 { 569 uchar *np; 570 if (offset < b->rn || offset >= b->wn) 571 return 0; 572 np = memchr(b->buf + offset, 0, b->wn - offset); 573 if (np == nil) 574 return 0; 575 *lenp = np - (b->buf + offset) + 1; 576 if (*lenp > buflen) 577 return 0; 578 memcpy(buf, b->buf + offset, *lenp); 579 return 1; 580 } 581