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 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 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 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 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 * 387 smbbufferpointer(SmbBuffer *b, ulong offset) 388 { 389 return b->buf + offset; 390 } 391 392 int 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 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 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 425 smbbufferreadspace(SmbBuffer *b) 426 { 427 return b->wn - b->rn; 428 } 429 430 void 431 smbbufferwritelimit(SmbBuffer *b, ulong limit) 432 { 433 if (b->rn + limit < b->maxlen) 434 b->maxlen = b->rn + limit; 435 } 436 437 int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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