1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 26 */ 27 28 /* 29 * SMB mbuf marshaling encode/decode. 30 */ 31 32 #include <smbsrv/smb_kproto.h> 33 34 35 #define MALLOC_QUANTUM 80 36 37 #define DECODE_NO_ERROR 0 38 #define DECODE_NO_MORE_DATA 1 39 #define DECODE_ALLOCATION_ERROR 2 40 #define DECODE_CONVERSION_ERROR 3 41 42 static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t); 43 static int mbc_marshal_make_room(mbuf_chain_t *, int32_t); 44 static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t); 45 static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t); 46 static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t); 47 static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t); 48 static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t); 49 static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int); 50 static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int); 51 static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *); 52 static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m); 53 static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc); 54 static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc); 55 static int mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data); 56 static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data); 57 static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data); 58 static uint64_t qswap(uint64_t ll); 59 static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data); 60 static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data); 61 static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *, 62 uint8_t **ascii, int); 63 static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *, 64 uint8_t **, int); 65 static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **); 66 static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *); 67 static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *); 68 static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t); 69 70 /* 71 * smb_mbc_vdecodef 72 * 73 * This function reads the contents of the mbc chain passed in under the list 74 * of arguments passed in. 75 * 76 * The format string provides a description of the parameters passed in as well 77 * as an action to be taken by smb_mbc_vdecodef(). 78 * 79 * % Pointer to an SMB request structure (smb_request_t *). There 80 * should be only one of these in the string. 81 * 82 * C Pointer to an mbuf chain. Copy to that mbuf chain the number of 83 * bytes specified (number preceding C). 84 * 85 * m Pointer to an mbuf. Copy to that mbuf the number of bytes 86 * specified (number preceding m). 87 * 88 * M Read the 32 bit value at the current location of the mbuf chain 89 * and check if it matches the signature of an SMB1 request (SMBx). 90 * 91 * N Read the 32 bit value at the current location of the mbuf chain 92 * and check if it matches the signature of an SMB2 request (SMBx). 93 * 94 * b Pointer to a buffer. Copy to that buffer the number of bytes 95 * specified (number preceding b). 96 * 97 * c Same as 'b'. 98 * 99 * w Pointer to a word (16bit value). Copy the next 16bit value into 100 * that location. 101 * 102 * l Pointer to a long (32bit value). Copy the next 32bit value into 103 * that location. 104 * 105 * q Pointer to a quad (64bit value). Copy the next 64bit value into 106 * that location. 107 * 108 * Q Same as above with a call to qswap(). 109 * 110 * B Pointer to a vardata_block structure. That structure is used to 111 * retrieve data from the mbuf chain (an iovec type structure is 112 * embedded in a vardata_block). 113 * 114 * D Pointer to a vardata_block structure. That structure is used to 115 * retrieve data from the mbuf chain, however, two fields of the 116 * vardata_block structure (tag and len) are first initialized 117 * using the mbuf chain itself. 118 * 119 * V Same as 'D'. 120 * 121 * L 122 * 123 * A 124 * 125 * P Same as 'A' 126 * 127 * S Same as 'A' 128 * 129 * u Pointer to a string pointer. Allocate memory and retrieve the 130 * string at the current location in the mbuf chain. Store the 131 * address to the buffer allocated at the address specified by 132 * the pointer. In addition if an sr was passed and it indicates 133 * that the string is an unicode string, convert it. 134 * 135 * s Same as 'u' without convertion. 136 * 137 * U Same as 'u'. The string to retrieve is unicode. 138 * 139 * y Pointer to a 32bit value. Read the dos time at the current mbuf 140 * chain location, convert it to unix time and store it at the 141 * location indicated by the pointer. 142 * 143 * Y Same as 'y' bt the dos time coded in the mbuf chain is inverted. 144 * 145 * . Skip the number of bytes indicated by the number preceding '.'. 146 * 147 * , Same as '.' but take in account it is an unicode string. 148 */ 149 int 150 smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) 151 { 152 uint8_t c; 153 uint8_t cval; 154 uint8_t *cvalp; 155 uint8_t **cvalpp; 156 uint16_t wval; 157 uint16_t *wvalp; 158 uint32_t *lvalp; 159 uint64_t *llvalp; 160 smb_vdb_t *vdp; 161 smb_request_t *sr = NULL; 162 uint32_t lval; 163 int unicode = 0; 164 int repc; 165 boolean_t repc_specified; 166 167 while ((c = *fmt++) != 0) { 168 repc_specified = B_FALSE; 169 repc = 1; 170 171 if ('0' <= c && c <= '9') { 172 repc = 0; 173 do { 174 repc = repc * 10 + c - '0'; 175 c = *fmt++; 176 } while ('0' <= c && c <= '9'); 177 repc_specified = B_TRUE; 178 } else if (c == '#') { 179 repc = va_arg(ap, int); 180 c = *fmt++; 181 repc_specified = B_TRUE; 182 } 183 184 switch (c) { 185 case '%': 186 sr = va_arg(ap, struct smb_request *); 187 if (sr->session->dialect >= SMB_VERS_2_BASE) { 188 unicode = 1; 189 break; 190 } 191 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE; 192 break; 193 194 case 'C': /* Mbuf_chain */ 195 if (mbc_marshal_get_mbuf_chain(mbc, repc, 196 va_arg(ap, mbuf_chain_t *)) != 0) 197 return (-1); 198 break; 199 200 case 'm': /* struct_mbuf */ 201 if (mbc_marshal_get_mbufs(mbc, repc, 202 va_arg(ap, mbuf_t **)) != 0) 203 return (-1); 204 break; 205 206 case 'M': 207 if (mbc_marshal_get_long(mbc, &lval) != 0) 208 return (-1); 209 if (lval != 0x424D53FF) /* 0xFF S M B */ 210 return (-1); 211 break; 212 213 case 'N': 214 if (mbc_marshal_get_long(mbc, &lval) != 0) 215 return (-1); 216 if (lval != 0x424D53FE) /* 0xFE S M B */ 217 return (-1); 218 break; 219 220 case 'b': 221 case 'c': 222 cvalp = va_arg(ap, uint8_t *); 223 if (MBC_ROOM_FOR(mbc, repc) == 0) 224 /* Data will never be available */ 225 return (-1); 226 227 while (repc-- > 0) 228 *cvalp++ = mbc_marshal_fetch_byte(mbc); 229 break; 230 231 case 'w': 232 wvalp = va_arg(ap, uint16_t *); 233 while (repc-- > 0) 234 if (mbc_marshal_get_short(mbc, wvalp++) != 0) 235 return (-1); 236 break; 237 238 case 'l': 239 lvalp = va_arg(ap, uint32_t *); 240 while (repc-- > 0) 241 if (mbc_marshal_get_long(mbc, lvalp++) != 0) 242 return (-1); 243 break; 244 245 case 'q': 246 llvalp = va_arg(ap, uint64_t *); 247 while (repc-- > 0) 248 if (mbc_marshal_get_long_long( 249 mbc, llvalp++) != 0) 250 return (-1); 251 break; 252 253 case 'Q': 254 llvalp = va_arg(ap, uint64_t *); 255 while (repc-- > 0) 256 if (mbc_marshal_get_odd_long_long( 257 mbc, llvalp++) != 0) 258 return (-1); 259 break; 260 261 case 'B': 262 vdp = va_arg(ap, struct vardata_block *); 263 vdp->vdb_tag = 0; 264 vdp->vdb_len = repc; 265 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0]; 266 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC; 267 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 268 vdp->vdb_uio.uio_resid = repc; 269 if (mbc_marshal_get_uio(mbc, &vdp->vdb_uio) != 0) 270 return (-1); 271 break; 272 273 case 'D': 274 case 'V': 275 vdp = va_arg(ap, struct vardata_block *); 276 if (mbc_marshal_get_char(mbc, &vdp->vdb_tag) != 0) 277 return (-1); 278 if (mbc_marshal_get_short(mbc, &wval) != 0) 279 return (-1); 280 vdp->vdb_len = (uint32_t)wval; 281 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0]; 282 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC; 283 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 284 vdp->vdb_uio.uio_resid = vdp->vdb_len; 285 if (vdp->vdb_len != 0) { 286 if (mbc_marshal_get_uio(mbc, 287 &vdp->vdb_uio) != 0) 288 return (-1); 289 } 290 break; 291 292 case 'L': 293 if (mbc_marshal_get_char(mbc, &cval) != 0) 294 return (-1); 295 if (cval != 2) 296 return (-1); 297 goto ascii_conversion; 298 299 case 'A': 300 case 'S': 301 if (mbc_marshal_get_char(mbc, &cval) != 0) 302 return (-1); 303 if (((c == 'A' || c == 'S') && cval != 4) || 304 (c == 'L' && cval != 2)) 305 return (-1); 306 /* FALLTHROUGH */ 307 308 case 'u': /* Convert from unicode if flags are set */ 309 if (unicode) 310 goto unicode_translation; 311 /* FALLTHROUGH */ 312 313 case 's': 314 ascii_conversion: 315 ASSERT(sr != NULL); 316 cvalpp = va_arg(ap, uint8_t **); 317 if (!repc_specified) 318 repc = 0; 319 if (mbc_marshal_get_ascii_string(sr, 320 mbc, cvalpp, repc) != 0) 321 return (-1); 322 break; 323 324 case 'U': /* Convert from unicode */ 325 unicode_translation: 326 ASSERT(sr != 0); 327 cvalpp = va_arg(ap, uint8_t **); 328 if (!repc_specified) 329 repc = 0; 330 if (mbc->chain_offset & 1) 331 mbc->chain_offset++; 332 if (mbc_marshal_get_unicode_string(sr, 333 mbc, cvalpp, repc) != 0) 334 return (-1); 335 break; 336 337 case 'Y': /* dos time to unix time tt/dd */ 338 lvalp = va_arg(ap, uint32_t *); 339 while (repc-- > 0) { 340 short d, t; 341 342 if (mbc_marshal_get_short(mbc, 343 (uint16_t *)&t) != 0) 344 return (-1); 345 if (mbc_marshal_get_short(mbc, 346 (uint16_t *)&d) != 0) 347 return (-1); 348 *lvalp++ = smb_time_dos_to_unix(d, t); 349 } 350 break; 351 352 case 'y': /* dos time to unix time dd/tt */ 353 lvalp = va_arg(ap, uint32_t *); 354 while (repc-- > 0) { 355 short d, t; 356 357 if (mbc_marshal_get_short(mbc, 358 (uint16_t *)&d) != 0) 359 return (-1); 360 if (mbc_marshal_get_short(mbc, 361 (uint16_t *)&t) != 0) 362 return (-1); 363 *lvalp++ = smb_time_dos_to_unix(d, t); 364 } 365 break; 366 367 case ',': 368 if (unicode) 369 repc *= 2; 370 /* FALLTHROUGH */ 371 372 case '.': 373 if (mbc_marshal_get_skip(mbc, repc) != 0) 374 return (-1); 375 break; 376 377 default: 378 ASSERT(0); 379 return (-1); 380 } 381 } 382 return (0); 383 } 384 385 /* 386 * smb_mbc_decodef 387 * 388 * This function reads the contents of the mbc chain passed in under the 389 * control of the format fmt. 390 * 391 * (for a description of the format string see smb_mbc_vencodef()). 392 */ 393 int 394 smb_mbc_decodef(mbuf_chain_t *mbc, const char *fmt, ...) 395 { 396 int xx; 397 va_list ap; 398 399 va_start(ap, fmt); 400 xx = smb_mbc_vdecodef(mbc, fmt, ap); 401 va_end(ap); 402 return (xx); 403 } 404 405 /* 406 * smb_mbc_peek 407 * 408 * This function reads the contents of the mbc passed in at the specified offset 409 * under the control of the format fmt. The offset of the chain passed in is not 410 * modified. 411 * 412 * (for a description of the format string see smb_mbc_vdecodef()). 413 */ 414 int 415 smb_mbc_peek(mbuf_chain_t *mbc, int offset, const char *fmt, ...) 416 { 417 mbuf_chain_t tmp; 418 va_list ap; 419 int xx; 420 421 va_start(ap, fmt); 422 423 (void) MBC_SHADOW_CHAIN(&tmp, mbc, offset, mbc->max_bytes - offset); 424 xx = smb_mbc_vdecodef(&tmp, fmt, ap); 425 va_end(ap); 426 return (xx); 427 } 428 429 /* 430 * smb_mbc_vencodef 431 * 432 * This function builds a stream of bytes in the mbc chain passed in under the 433 * control of the list of arguments passed in. 434 * 435 * The format string provides a description of the parameters passed in as well 436 * as an action to be taken by smb_mbc_vencodef(). 437 * 438 * \b Restore the mbuf chain offset to its initial value. 439 * 440 * % Pointer to an SMB request structure (smb_request_t *). There 441 * should be only one of these in the string. If an sr in present 442 * it will be used to determine if unicode conversion should be 443 * applied to the strings. 444 * 445 * C Pointer to an mbuf chain. Copy that mbuf chain into the 446 * destination mbuf chain. 447 * 448 * D Pointer to a vardata_block structure. Copy the data described 449 * by that structure into the mbuf chain. The tag field is hard 450 * coded to '1'. 451 * 452 * M Write the SMB1 request signature ('SMBX') into the mbuf chain. 453 * 454 * N Write the SMB2 request signature ('SMBX') into the mbuf chain. 455 * 456 * T Pointer to a timestruc_t. Convert the content of the structure 457 * into NT time and store the result of the conversion in the 458 * mbuf chain. 459 * 460 * V Same as 'D' but the tag field is hard coded to '5'. 461 * 462 * b Byte. Store the byte or the nymber of bytes specified into the 463 * the mbuf chain. A format string like this "2b" would require 2 464 * bytes to be passed in. 465 * 466 * m Pointer to an mbuf. Copy the contents of the mbuf into the mbuf 467 * chain. 468 * 469 * c Pointer to a buffer. Copy the buffer into the mbuf chain. The 470 * size of the buffer is indicated by the number preceding 'c'. 471 * 472 * w Word (16bit value). Store the word or the number of words 473 * specified into the the mbuf chain. A format string like this 474 * "2w" would require 2 words to be passed in. 475 * 476 * l Long (32bit value). Store the long or the number of longs 477 * specified into the the mbuf chain. A format string like this 478 * "2l" would require 2 longs to be passed in. 479 * 480 * q Quad (64bit value). Store the quad or the number of quads 481 * specified into the the mbuf chain. A format string like this 482 * "2q" would require 2 quads to be passed in. 483 * 484 * L Pointer to a string. Store the string passed in into the mbuf 485 * chain preceded with a tag value of '2'. 486 * 487 * S Pointer to a string. Store the string passed in into the mbuf 488 * chain preceded with a tag value of '4'. Applied a unicode 489 * conversion is appropriate. 490 * 491 * A Same as 'S' 492 * 493 * P Pointer to a string. Store the string passed in into the mbuf 494 * chain preceded with a tag value of '5'. Applied a unicode 495 * conversion is appropriate. 496 * 497 * u Pointer to a string. Store the string passed in into the mbuf 498 * chain. Applied a unicode conversion is appropriate. 499 * 500 * s Pointer to a string. Store the string passed in into the mbuf 501 * chain. 502 * 503 * Y Date/Time. Store the Date/Time or the number of Date/Time(s) 504 * specified into the the mbuf chain. A format string like this 505 * "2Y" would require 2 Date/Time values. The Date/Time is 506 * converted to DOS before storing. 507 * 508 * y Same as 'Y'. The order of Date and Time is reversed. 509 * 510 * , Character. Store the character or number of character specified 511 * into the mbuf chain. A format string like this "2c" would 512 * require 2 characters to be passed in. A unicode conversion is 513 * applied if appropriate. 514 * 515 * . Same as '`' without unicode conversion. 516 * 517 * U Align the offset of the mbuf chain on a 16bit boundary. 518 */ 519 int 520 smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) 521 { 522 uint8_t *cvalp; 523 timestruc_t *tvp; 524 smb_vdb_t *vdp; 525 smb_request_t *sr = NULL; 526 uint64_t llval; 527 int64_t nt_time; 528 uint32_t lval; 529 uint_t tag; 530 int unicode = 0; 531 int repc; 532 boolean_t repc_specified; 533 uint16_t wval; 534 uint8_t cval; 535 uint8_t c; 536 537 while ((c = *fmt++) != 0) { 538 repc_specified = B_FALSE; 539 repc = 1; 540 541 if ('0' <= c && c <= '9') { 542 repc = 0; 543 do { 544 repc = repc * 10 + c - '0'; 545 c = *fmt++; 546 } while ('0' <= c && c <= '9'); 547 repc_specified = B_TRUE; 548 } else if (c == '#') { 549 repc = va_arg(ap, int); 550 c = *fmt++; 551 repc_specified = B_TRUE; 552 553 } 554 555 switch (c) { 556 case '%': 557 sr = va_arg(ap, struct smb_request *); 558 if (sr->session->dialect >= SMB_VERS_2_BASE) { 559 unicode = 1; 560 break; 561 } 562 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE; 563 break; 564 565 case 'C': /* Mbuf_chain */ 566 if (mbc_marshal_put_mbuf_chain(mbc, 567 va_arg(ap, mbuf_chain_t *)) != 0) 568 return (DECODE_NO_MORE_DATA); 569 break; 570 571 case 'D': 572 vdp = va_arg(ap, struct vardata_block *); 573 574 if (mbc_marshal_put_char(mbc, 1) != 0) 575 return (DECODE_NO_MORE_DATA); 576 if (mbc_marshal_put_short(mbc, vdp->vdb_len) != 0) 577 return (DECODE_NO_MORE_DATA); 578 if (mbc_marshal_put_uio(mbc, &vdp->vdb_uio) != 0) 579 return (DECODE_NO_MORE_DATA); 580 break; 581 582 case 'M': 583 /* 0xFF S M B */ 584 if (mbc_marshal_put_long(mbc, 0x424D53FF)) 585 return (DECODE_NO_MORE_DATA); 586 break; 587 588 case 'N': 589 /* 0xFE S M B */ 590 if (mbc_marshal_put_long(mbc, 0x424D53FE)) 591 return (DECODE_NO_MORE_DATA); 592 break; 593 594 case 'T': 595 tvp = va_arg(ap, timestruc_t *); 596 nt_time = smb_time_unix_to_nt(tvp); 597 if (mbc_marshal_put_long_long(mbc, nt_time) != 0) 598 return (DECODE_NO_MORE_DATA); 599 break; 600 601 case 'V': 602 vdp = va_arg(ap, struct vardata_block *); 603 604 if (mbc_marshal_put_char(mbc, 5) != 0) 605 return (DECODE_NO_MORE_DATA); 606 if (mbc_marshal_put_short(mbc, vdp->vdb_len) != 0) 607 return (DECODE_NO_MORE_DATA); 608 if (mbc_marshal_put_uio(mbc, &vdp->vdb_uio) != 0) 609 return (DECODE_NO_MORE_DATA); 610 break; 611 612 case 'b': 613 while (repc-- > 0) { 614 cval = va_arg(ap, int); 615 if (mbc_marshal_put_char(mbc, cval) != 0) 616 return (DECODE_NO_MORE_DATA); 617 } 618 break; 619 620 case 'm': /* struct_mbuf */ 621 if (mbc_marshal_put_mbufs(mbc, 622 va_arg(ap, mbuf_t *)) != 0) 623 return (DECODE_NO_MORE_DATA); 624 break; 625 626 case 'c': 627 cvalp = va_arg(ap, uint8_t *); 628 while (repc-- > 0) { 629 if (mbc_marshal_put_char(mbc, 630 *cvalp++) != 0) 631 return (DECODE_NO_MORE_DATA); 632 } 633 break; 634 635 case 'w': 636 while (repc-- > 0) { 637 wval = va_arg(ap, int); 638 if (mbc_marshal_put_short(mbc, wval) != 0) 639 return (DECODE_NO_MORE_DATA); 640 } 641 break; 642 643 case 'l': 644 while (repc-- > 0) { 645 lval = va_arg(ap, uint32_t); 646 if (mbc_marshal_put_long(mbc, lval) != 0) 647 return (DECODE_NO_MORE_DATA); 648 } 649 break; 650 651 case 'q': 652 while (repc-- > 0) { 653 llval = va_arg(ap, uint64_t); 654 if (mbc_marshal_put_long_long(mbc, llval) != 0) 655 return (DECODE_NO_MORE_DATA); 656 } 657 break; 658 659 660 case 'L': 661 tag = 2; 662 goto ascii_conversion; 663 664 case 'S': 665 case 'A': 666 tag = 4; 667 goto tagged_str; 668 669 case 'P': 670 tag = 3; 671 goto tagged_str; 672 673 tagged_str: 674 if (mbc_marshal_put_char(mbc, tag) != 0) 675 return (DECODE_NO_MORE_DATA); 676 /* FALLTHROUGH */ 677 678 case 'u': /* Convert from unicode if flags are set */ 679 if (unicode) 680 goto unicode_translation; 681 /* FALLTHROUGH */ 682 683 case 's': /* ASCII/multibyte string */ 684 ascii_conversion: cvalp = va_arg(ap, uint8_t *); 685 if (!repc_specified) 686 repc = 0; 687 if (mbc_marshal_put_ascii_string(mbc, 688 (char *)cvalp, repc) != 0) 689 return (DECODE_NO_MORE_DATA); 690 break; 691 692 case 'Y': /* int32_t, encode dos date/time */ 693 while (repc-- > 0) { 694 uint16_t d, t; 695 696 lval = va_arg(ap, uint32_t); 697 smb_time_unix_to_dos(lval, 698 (short *)&d, (short *)&t); 699 if (mbc_marshal_put_short(mbc, t) != 0) 700 return (DECODE_NO_MORE_DATA); 701 if (mbc_marshal_put_short(mbc, d) != 0) 702 return (DECODE_NO_MORE_DATA); 703 } 704 break; 705 706 case 'y': /* int32_t, encode dos date/time */ 707 while (repc-- > 0) { 708 uint16_t d, t; 709 710 lval = va_arg(ap, uint32_t); 711 smb_time_unix_to_dos(lval, 712 (short *)&d, (short *)&t); 713 if (mbc_marshal_put_short(mbc, d) != 0) 714 return (DECODE_NO_MORE_DATA); 715 if (mbc_marshal_put_short(mbc, t) != 0) 716 return (DECODE_NO_MORE_DATA); 717 } 718 break; 719 720 case ',': 721 if (unicode) 722 repc *= 2; 723 /* FALLTHROUGH */ 724 725 case '.': 726 while (repc-- > 0) 727 if (mbc_marshal_put_char(mbc, 0) != 0) 728 return (DECODE_NO_MORE_DATA); 729 break; 730 731 case 'U': /* Convert to unicode, align to word boundary */ 732 unicode_translation: 733 if (mbc->chain_offset & 1) 734 mbc->chain_offset++; 735 cvalp = va_arg(ap, uint8_t *); 736 if (!repc_specified) 737 repc = 0; 738 if (mbc_marshal_put_unicode_string(mbc, 739 (char *)cvalp, repc) != 0) 740 return (DECODE_NO_MORE_DATA); 741 break; 742 743 default: 744 ASSERT(0); 745 return (-1); 746 } 747 } 748 return (0); 749 } 750 751 /* 752 * smb_mbc_encodef 753 * 754 * This function builds a stream of bytes in the mbc chain passed in under the 755 * control of the format fmt. 756 * 757 * (for a description of the format string see smb_mbc_vencodef()). 758 */ 759 int 760 smb_mbc_encodef(mbuf_chain_t *mbc, const char *fmt, ...) 761 { 762 int rc; 763 va_list ap; 764 765 va_start(ap, fmt); 766 rc = smb_mbc_vencodef(mbc, fmt, ap); 767 va_end(ap); 768 return (rc); 769 } 770 771 /* 772 * smb_mbc_poke 773 * 774 * This function writes a stream of bytes in the mbc passed in at the specified 775 * offset under the control of the format fmt. The offset of the chain passed in 776 * is not modified. 777 * 778 * (for a description of the format string see smb_mbc_vencodef()). 779 */ 780 int 781 smb_mbc_poke(mbuf_chain_t *mbc, int offset, const char *fmt, ...) 782 { 783 int len, rc; 784 mbuf_chain_t tmp; 785 va_list ap; 786 787 if ((len = mbc->max_bytes - offset) < 0) 788 return (DECODE_NO_MORE_DATA); 789 rc = MBC_SHADOW_CHAIN(&tmp, mbc, offset, len); 790 if (rc) 791 return (DECODE_NO_MORE_DATA); 792 793 va_start(ap, fmt); 794 rc = smb_mbc_vencodef(&tmp, fmt, ap); 795 va_end(ap); 796 797 return (rc); 798 } 799 800 /* 801 * Copy data from the src mbuf chain to the dst mbuf chain, 802 * at the given offset in the src and current offset in dst, 803 * for copy_len bytes. Does NOT update src->chain_offset. 804 */ 805 int 806 smb_mbc_copy(mbuf_chain_t *dst_mbc, const mbuf_chain_t *src_mbc, 807 int copy_offset, int copy_len) 808 { 809 mbuf_t *src_m; 810 int offset, len; 811 int rc; 812 813 if (copy_len <= 0) 814 return (0); 815 if (copy_offset < 0) 816 return (EINVAL); 817 if ((copy_offset + copy_len) > src_mbc->max_bytes) 818 return (EMSGSIZE); 819 820 /* 821 * Advance to the src mbuf where we start copying. 822 */ 823 offset = copy_offset; 824 src_m = src_mbc->chain; 825 while (src_m && offset >= src_m->m_len) { 826 offset -= src_m->m_len; 827 src_m = src_m->m_next; 828 } 829 if (src_m == NULL) 830 return (EFAULT); 831 832 /* 833 * Copy the first part, which may start somewhere past 834 * the beginning of the current mbuf. 835 */ 836 len = src_m->m_len - offset; 837 if (len > copy_len) 838 len = copy_len; 839 rc = smb_mbc_put_mem(dst_mbc, src_m->m_data + offset, len); 840 if (rc != 0) 841 return (rc); 842 copy_len -= len; 843 844 /* 845 * Copy remaining mbufs... 846 */ 847 while (copy_len > 0) { 848 src_m = src_m->m_next; 849 if (src_m == NULL) 850 break; 851 len = src_m->m_len; 852 if (len > copy_len) 853 len = copy_len; 854 rc = smb_mbc_put_mem(dst_mbc, src_m->m_data, len); 855 copy_len -= len; 856 } 857 858 return (0); 859 } 860 861 /* 862 * Copy data from the passed memory buffer into the mbuf chain 863 * at the current offset. 864 */ 865 int 866 smb_mbc_put_mem(mbuf_chain_t *mbc, void *vmem, int mem_len) 867 { 868 caddr_t mem = vmem; 869 mbuf_t *m; 870 int32_t offset, tlen; 871 int rc; 872 873 if (mem_len <= 0) 874 return (0); 875 876 if ((rc = mbc_marshal_make_room(mbc, mem_len)) != 0) 877 return (rc); 878 879 /* 880 * Advance to the dst mbuf where we start copying. 881 * Allocations were done by _make_room(). 882 */ 883 offset = mbc->chain_offset; 884 m = mbc->chain; 885 while (offset >= m->m_len) { 886 ASSERT(m->m_len > 0); 887 offset -= m->m_len; 888 m = m->m_next; 889 } 890 891 /* 892 * Copy the first part, which may start somewhere past 893 * the beginning of the current mbuf. 894 */ 895 tlen = m->m_len - offset; 896 if (tlen > mem_len) 897 tlen = mem_len; 898 bcopy(mem, m->m_data + offset, tlen); 899 mbc->chain_offset += tlen; 900 mem += tlen; 901 mem_len -= tlen; 902 903 /* 904 * Copy remaining mem into mbufs. These all start 905 * at the beginning of each mbuf, and the last may 906 * end somewhere short of m_len. 907 */ 908 while (mem_len > 0) { 909 m = m->m_next; 910 tlen = m->m_len; 911 if (tlen > mem_len) 912 tlen = mem_len; 913 bcopy(mem, m->m_data, tlen); 914 mbc->chain_offset += tlen; 915 mem += tlen; 916 mem_len -= tlen; 917 } 918 919 return (0); 920 } 921 922 /* 923 * Put data into mbuf chain allocating as needed. 924 * Adds room to end of mbuf chain if needed. 925 */ 926 static int 927 mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed) 928 { 929 mbuf_t *m; 930 mbuf_t *l; 931 int32_t bytes_available; 932 933 bytes_needed += mbc->chain_offset; 934 if (bytes_needed > mbc->max_bytes) 935 return (EMSGSIZE); 936 937 if ((m = mbc->chain) == 0) { 938 MGET(m, M_WAIT, MT_DATA); 939 m->m_len = 0; 940 MCLGET(m, M_WAIT); 941 mbc->chain = m; 942 /* xxxx */ 943 /* ^ */ 944 } 945 946 /* ---- ----- --xx ---xxx */ 947 /* ^ */ 948 949 l = 0; 950 while ((m != 0) && (bytes_needed >= m->m_len)) { 951 l = m; 952 bytes_needed -= m->m_len; 953 m = m->m_next; 954 } 955 956 if ((bytes_needed == 0) || (m != 0)) { 957 /* We have enough room already */ 958 return (0); 959 } 960 961 /* ---- ----- --xx ---xxx */ 962 /* ^ */ 963 /* Back up to start of last mbuf */ 964 m = l; 965 bytes_needed += m->m_len; 966 967 /* ---- ----- --xx ---xxx */ 968 /* ^ */ 969 970 bytes_available = (m->m_flags & M_EXT) ? 971 m->m_ext.ext_size : MLEN; 972 973 /* ---- ----- --xx ---xxx */ 974 /* ^ */ 975 while ((bytes_needed != 0) && (bytes_needed > bytes_available)) { 976 m->m_len = bytes_available; 977 bytes_needed -= m->m_len; 978 /* ---- ----- --xx ------ */ 979 /* ^ */ 980 981 MGET(m->m_next, M_WAIT, MT_DATA); 982 m = m->m_next; 983 m->m_len = 0; 984 MCLGET(m, M_WAIT); 985 986 ASSERT((m->m_flags & M_EXT) != 0); 987 bytes_available = m->m_ext.ext_size; 988 989 /* ---- ----- --xx ------ xxxx */ 990 /* ^ */ 991 } 992 993 /* ---- ----- --xx ------ xxxx */ 994 /* ^ */ 995 /* Expand last tail as needed */ 996 if (m->m_len <= bytes_needed) { 997 m->m_len = bytes_needed; 998 /* ---- ----- --xx ------ --xx */ 999 /* ^ */ 1000 } 1001 1002 return (0); 1003 } 1004 1005 static void 1006 mbc_marshal_store_byte(mbuf_chain_t *mbc, uint8_t data) 1007 { 1008 mbuf_t *m = mbc->chain; 1009 int32_t cur_offset = mbc->chain_offset; 1010 1011 /* 1012 * Scan forward looking for the last data currently in chain. 1013 */ 1014 while (cur_offset >= m->m_len) { 1015 cur_offset -= m->m_len; 1016 m = m->m_next; 1017 } 1018 ((char *)m->m_data)[cur_offset] = data; 1019 mbc->chain_offset++; 1020 } 1021 1022 static int 1023 mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t data) 1024 { 1025 if (mbc_marshal_make_room(mbc, sizeof (char)) != 0) 1026 return (DECODE_NO_MORE_DATA); 1027 mbc_marshal_store_byte(mbc, data); 1028 return (0); 1029 } 1030 1031 static int 1032 mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t data) 1033 { 1034 if (mbc_marshal_make_room(mbc, sizeof (short))) 1035 return (DECODE_NO_MORE_DATA); 1036 mbc_marshal_store_byte(mbc, data); 1037 mbc_marshal_store_byte(mbc, data >> 8); 1038 return (0); 1039 } 1040 1041 static int 1042 mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t data) 1043 { 1044 if (mbc_marshal_make_room(mbc, sizeof (int32_t))) 1045 return (DECODE_NO_MORE_DATA); 1046 mbc_marshal_store_byte(mbc, data); 1047 mbc_marshal_store_byte(mbc, data >> 8); 1048 mbc_marshal_store_byte(mbc, data >> 16); 1049 mbc_marshal_store_byte(mbc, data >> 24); 1050 return (0); 1051 } 1052 1053 static int 1054 mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t data) 1055 { 1056 if (mbc_marshal_make_room(mbc, sizeof (int64_t))) 1057 return (DECODE_NO_MORE_DATA); 1058 1059 mbc_marshal_store_byte(mbc, data); 1060 mbc_marshal_store_byte(mbc, data >> 8); 1061 mbc_marshal_store_byte(mbc, data >> 16); 1062 mbc_marshal_store_byte(mbc, data >> 24); 1063 mbc_marshal_store_byte(mbc, data >> 32); 1064 mbc_marshal_store_byte(mbc, data >> 40); 1065 mbc_marshal_store_byte(mbc, data >> 48); 1066 mbc_marshal_store_byte(mbc, data >> 56); 1067 return (0); 1068 } 1069 1070 /* 1071 * When need to convert from UTF-8 (internal format) to a single 1072 * byte string (external format ) when marshalling a string. 1073 */ 1074 static int 1075 mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc) 1076 { 1077 smb_wchar_t wide_char; 1078 int nbytes; 1079 int length; 1080 1081 if ((length = smb_sbequiv_strlen(mbs)) == -1) 1082 return (DECODE_NO_MORE_DATA); 1083 1084 length += sizeof (char); 1085 1086 if ((repc > 0) && (repc < length)) 1087 length = repc; 1088 if (mbc_marshal_make_room(mbc, length)) 1089 return (DECODE_NO_MORE_DATA); 1090 1091 while (*mbs) { 1092 /* 1093 * We should restore oem chars here. 1094 */ 1095 nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); 1096 if (nbytes == -1) 1097 return (DECODE_NO_MORE_DATA); 1098 1099 mbc_marshal_store_byte(mbc, (uint8_t)wide_char); 1100 1101 if (wide_char & 0xFF00) 1102 mbc_marshal_store_byte(mbc, wide_char >> 8); 1103 1104 mbs += nbytes; 1105 } 1106 1107 mbc_marshal_store_byte(mbc, 0); 1108 return (0); 1109 } 1110 1111 static int 1112 mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc) 1113 { 1114 smb_wchar_t wchar; 1115 int consumed; 1116 int length; 1117 1118 if ((length = smb_wcequiv_strlen(ascii)) == -1) 1119 return (DECODE_NO_MORE_DATA); 1120 1121 length += sizeof (smb_wchar_t); 1122 1123 if ((repc > 0) && (repc < length)) 1124 length = repc; 1125 1126 if (mbc_marshal_make_room(mbc, length)) 1127 return (DECODE_NO_MORE_DATA); 1128 while (length > 0) { 1129 consumed = smb_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX); 1130 if (consumed == -1) 1131 break; /* Invalid sequence */ 1132 /* 1133 * Note that consumed will be 0 when the null terminator 1134 * is encountered and ascii will not be advanced beyond 1135 * that point. Length will continue to be decremented so 1136 * we won't get stuck here. 1137 */ 1138 ascii += consumed; 1139 mbc_marshal_store_byte(mbc, wchar); 1140 mbc_marshal_store_byte(mbc, wchar >> 8); 1141 length -= sizeof (smb_wchar_t); 1142 } 1143 return (0); 1144 } 1145 1146 static int /*ARGSUSED*/ 1147 uiorefnoop(caddr_t p, int size, int adj) 1148 { 1149 return (0); 1150 } 1151 1152 static int 1153 mbc_marshal_put_uio(mbuf_chain_t *mbc, struct uio *uio) 1154 { 1155 mbuf_t **t; 1156 mbuf_t *m = NULL; 1157 struct iovec *iov = uio->uio_iov; 1158 int32_t i, iov_cnt = uio->uio_iovcnt; 1159 1160 iov = uio->uio_iov; 1161 t = &mbc->chain; 1162 for (i = 0; i < iov_cnt; i++) { 1163 MGET(m, M_WAIT, MT_DATA); 1164 m->m_ext.ext_buf = iov->iov_base; 1165 m->m_ext.ext_ref = uiorefnoop; 1166 m->m_data = m->m_ext.ext_buf; 1167 m->m_flags |= M_EXT; 1168 m->m_len = m->m_ext.ext_size = iov->iov_len; 1169 mbc->max_bytes += m->m_len; 1170 m->m_next = 0; 1171 *t = m; 1172 t = &m->m_next; 1173 iov++; 1174 } 1175 return (0); 1176 } 1177 1178 static int 1179 mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m) 1180 { 1181 mbuf_t *mt; 1182 mbuf_t **t; 1183 int bytes; 1184 1185 if (m != NULL) { 1186 mt = m; 1187 bytes = mt->m_len; 1188 while (mt->m_next != 0) { 1189 mt = mt->m_next; 1190 bytes += mt->m_len; 1191 } 1192 if (bytes != 0) { 1193 t = &mbc->chain; 1194 while (*t != 0) { 1195 bytes += (*t)->m_len; 1196 t = &(*t)->m_next; 1197 } 1198 *t = m; 1199 mbc->chain_offset = bytes; 1200 } else { 1201 m_freem(m); 1202 } 1203 } 1204 return (0); 1205 } 1206 1207 static int 1208 mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc) 1209 { 1210 if (nmbc->chain != 0) { 1211 if (mbc_marshal_put_mbufs(mbc, nmbc->chain)) 1212 return (DECODE_NO_MORE_DATA); 1213 MBC_SETUP(nmbc, nmbc->max_bytes); 1214 } 1215 return (0); 1216 } 1217 1218 static uint8_t 1219 mbc_marshal_fetch_byte(mbuf_chain_t *mbc) 1220 { 1221 uint8_t data; 1222 mbuf_t *m = mbc->chain; 1223 int32_t offset = mbc->chain_offset; 1224 1225 while (offset >= m->m_len) { 1226 offset -= m->m_len; 1227 m = m->m_next; 1228 } 1229 data = ((uint8_t *)m->m_data)[offset]; 1230 mbc->chain_offset++; 1231 return (data); 1232 } 1233 1234 static int 1235 mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data) 1236 { 1237 if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) { 1238 /* Data will never be available */ 1239 return (DECODE_NO_MORE_DATA); 1240 } 1241 *data = mbc_marshal_fetch_byte(mbc); 1242 return (0); 1243 } 1244 1245 static int 1246 mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data) 1247 { 1248 uint16_t tmp; 1249 mbuf_t *m = mbc->chain; 1250 int32_t offset = mbc->chain_offset; 1251 1252 if (MBC_ROOM_FOR(mbc, sizeof (short)) == 0) { 1253 /* Data will never be available */ 1254 return (DECODE_NO_MORE_DATA); 1255 } 1256 1257 while (offset >= m->m_len) { 1258 offset -= m->m_len; 1259 m = m->m_next; 1260 } 1261 if ((m->m_len - offset) >= sizeof (short)) { 1262 *data = LE_IN16(m->m_data + offset); 1263 mbc->chain_offset += sizeof (short); 1264 } else { 1265 tmp = (uint16_t)mbc_marshal_fetch_byte(mbc); 1266 tmp |= ((uint16_t)mbc_marshal_fetch_byte(mbc)) << 8; 1267 *data = tmp; 1268 } 1269 return (0); 1270 } 1271 1272 static int 1273 mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data) 1274 { 1275 uint32_t tmp; 1276 mbuf_t *m = mbc->chain; 1277 int32_t offset = mbc->chain_offset; 1278 1279 if (MBC_ROOM_FOR(mbc, sizeof (int32_t)) == 0) { 1280 /* Data will never be available */ 1281 return (DECODE_NO_MORE_DATA); 1282 } 1283 while (offset >= m->m_len) { 1284 offset -= m->m_len; 1285 m = m->m_next; 1286 } 1287 if ((m->m_len - offset) >= sizeof (int32_t)) { 1288 *data = LE_IN32(m->m_data + offset); 1289 mbc->chain_offset += sizeof (int32_t); 1290 } else { 1291 tmp = (uint32_t)mbc_marshal_fetch_byte(mbc); 1292 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 8; 1293 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 16; 1294 tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 24; 1295 *data = tmp; 1296 } 1297 return (0); 1298 } 1299 1300 static uint64_t 1301 qswap(uint64_t ll) 1302 { 1303 uint64_t v; 1304 1305 v = ll >> 32; 1306 v |= ll << 32; 1307 1308 return (v); 1309 } 1310 1311 static int 1312 mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data) 1313 { 1314 uint64_t tmp; 1315 mbuf_t *m = mbc->chain; 1316 int32_t offset = mbc->chain_offset; 1317 1318 if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) { 1319 /* Data will never be available */ 1320 return (DECODE_NO_MORE_DATA); 1321 } 1322 while (offset >= m->m_len) { 1323 offset -= m->m_len; 1324 m = m->m_next; 1325 } 1326 1327 if ((m->m_len - offset) >= sizeof (int64_t)) { 1328 *data = qswap(LE_IN64(m->m_data + offset)); 1329 mbc->chain_offset += sizeof (int64_t); 1330 } else { 1331 tmp = (uint64_t)mbc_marshal_fetch_byte(mbc) << 32; 1332 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 40; 1333 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 48; 1334 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 56; 1335 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc); 1336 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 8; 1337 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 16; 1338 tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 24; 1339 1340 *(uint64_t *)data = tmp; 1341 } 1342 return (0); 1343 } 1344 1345 static int 1346 mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data) 1347 { 1348 uint64_t tmp; 1349 mbuf_t *m = mbc->chain; 1350 int32_t offset = mbc->chain_offset; 1351 1352 if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) { 1353 /* Data will never be available */ 1354 return (DECODE_NO_MORE_DATA); 1355 } 1356 while (offset >= m->m_len) { 1357 offset -= m->m_len; 1358 m = m->m_next; 1359 } 1360 if ((m->m_len - offset) >= sizeof (int64_t)) { 1361 *data = LE_IN64(m->m_data + offset); 1362 mbc->chain_offset += sizeof (int64_t); 1363 } else { 1364 tmp = (uint32_t)mbc_marshal_fetch_byte(mbc); 1365 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 8; 1366 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 16; 1367 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 24; 1368 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 32; 1369 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 40; 1370 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 48; 1371 tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 56; 1372 *(uint64_t *)data = tmp; 1373 } 1374 return (0); 1375 } 1376 1377 /* 1378 * mbc_marshal_get_ascii_string 1379 * 1380 * The ascii string in smb includes oem chars. Since the 1381 * system needs utf8 encodes unicode char, conversion is 1382 * required to convert the oem char to unicode and then 1383 * to encode the converted wchars to utf8 format. 1384 * Therefore, the **ascii returned will be in such format 1385 * instead of the real ASCII format. 1386 */ 1387 static int 1388 mbc_marshal_get_ascii_string( 1389 smb_request_t *sr, 1390 mbuf_chain_t *mbc, 1391 uint8_t **ascii, 1392 int max_ascii) 1393 { 1394 char *rcvbuf; 1395 char *ch; 1396 int max; 1397 int length = 0; 1398 1399 max = MALLOC_QUANTUM; 1400 rcvbuf = smb_srm_zalloc(sr, max); 1401 1402 if (max_ascii == 0) 1403 max_ascii = 0xffff; 1404 1405 ch = rcvbuf; 1406 for (;;) { 1407 while (length < max) { 1408 if (max_ascii-- <= 0) { 1409 *ch++ = 0; 1410 goto multibyte_encode; 1411 } 1412 if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) { 1413 /* Data will never be available */ 1414 return (DECODE_NO_MORE_DATA); 1415 } 1416 if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0) 1417 goto multibyte_encode; 1418 length++; 1419 } 1420 max += MALLOC_QUANTUM; 1421 rcvbuf = smb_srm_rezalloc(sr, rcvbuf, max); 1422 ch = rcvbuf + length; 1423 } 1424 1425 multibyte_encode: 1426 /* 1427 * UTF-8 encode the string for internal system use. 1428 */ 1429 length = strlen(rcvbuf) + 1; 1430 *ascii = smb_srm_zalloc(sr, length * MTS_MB_CHAR_MAX); 1431 return (mbc_marshal_cstou8("CP850", (char *)*ascii, 1432 (size_t)length * MTS_MB_CHAR_MAX, rcvbuf, (size_t)length)); 1433 } 1434 1435 static int 1436 mbc_marshal_get_unicode_string(smb_request_t *sr, 1437 mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode) 1438 { 1439 int max; 1440 uint16_t wchar; 1441 char *ch; 1442 int emitted; 1443 int length = 0; 1444 1445 if (max_unicode == 0) 1446 max_unicode = 0xffff; 1447 1448 max = MALLOC_QUANTUM; 1449 *ascii = smb_srm_zalloc(sr, max); 1450 1451 ch = (char *)*ascii; 1452 for (;;) { 1453 while ((length + MTS_MB_CHAR_MAX) < max) { 1454 if (max_unicode <= 0) 1455 goto done; 1456 max_unicode -= 2; 1457 1458 if (mbc_marshal_get_short(mbc, &wchar) != 0) 1459 return (DECODE_NO_MORE_DATA); 1460 1461 if (wchar == 0) goto done; 1462 1463 emitted = smb_wctomb(ch, wchar); 1464 length += emitted; 1465 ch += emitted; 1466 } 1467 max += MALLOC_QUANTUM; 1468 *ascii = smb_srm_rezalloc(sr, *ascii, max); 1469 ch = (char *)*ascii + length; 1470 } 1471 done: *ch = 0; 1472 return (0); 1473 } 1474 1475 static int /*ARGSUSED*/ 1476 mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m) 1477 { 1478 *m = NULL; 1479 if (MBC_ROOM_FOR(mbc, bytes) == 0) { 1480 /* Data will never be available */ 1481 return (DECODE_NO_MORE_DATA); 1482 } 1483 /* not yet implemented */ 1484 return (-1); 1485 } 1486 1487 static int 1488 mbc_marshal_get_mbuf_chain(mbuf_chain_t *mbc, int32_t bytes, mbuf_chain_t *nmbc) 1489 { 1490 int rc; 1491 mbuf_t *m; 1492 1493 if (bytes == 0) { 1494 /* Get all the rest */ 1495 bytes = mbc->max_bytes - mbc->chain_offset; 1496 } 1497 1498 MBC_SETUP(nmbc, mbc->max_bytes); 1499 if ((rc = mbc_marshal_get_mbufs(mbc, bytes, &m)) != 0) { 1500 if (m) 1501 m_freem(m); 1502 return (rc); 1503 } 1504 nmbc->chain = m; 1505 while (m != 0) { 1506 bytes += m->m_len; 1507 m = m->m_next; 1508 } 1509 nmbc->max_bytes = bytes; 1510 return (0); 1511 } 1512 1513 static int 1514 mbc_marshal_get_uio(mbuf_chain_t *mbc, struct uio *uio) 1515 { 1516 int i, offset; 1517 int32_t bytes = uio->uio_resid; 1518 int32_t remainder; 1519 struct iovec *iov; 1520 mbuf_t *m; 1521 1522 /* 1523 * The residual count is tested because in the case of write requests 1524 * with no data (smbtorture RAW-WRITE test will generate that type of 1525 * request) this function is called with a residual count of zero 1526 * bytes. 1527 */ 1528 if (bytes != 0) { 1529 iov = uio->uio_iov; 1530 uio->uio_segflg = UIO_SYSSPACE; 1531 uio->uio_extflg = UIO_COPY_DEFAULT; 1532 1533 if (MBC_ROOM_FOR(mbc, bytes) == 0) { 1534 /* Data will never be available */ 1535 return (DECODE_NO_MORE_DATA); 1536 } 1537 1538 m = mbc->chain; 1539 offset = mbc->chain_offset; 1540 while (offset >= m->m_len) { 1541 offset -= m->m_len; 1542 m = m->m_next; 1543 ASSERT((offset == 0) || (offset && m)); 1544 } 1545 1546 for (i = 0; (bytes > 0) && (i < uio->uio_iovcnt); i++) { 1547 iov[i].iov_base = &m->m_data[offset]; 1548 remainder = m->m_len - offset; 1549 if (remainder >= bytes) { 1550 iov[i].iov_len = bytes; 1551 mbc->chain_offset += bytes; 1552 uio->uio_iovcnt = i + 1; 1553 return (0); 1554 } 1555 iov[i].iov_len = remainder; 1556 mbc->chain_offset += remainder; 1557 bytes -= remainder; 1558 m = m->m_next; 1559 offset = 0; 1560 } 1561 return (DECODE_NO_MORE_DATA); 1562 } 1563 return (0); 1564 } 1565 1566 static int 1567 mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip) 1568 { 1569 if (MBC_ROOM_FOR(mbc, skip) == 0) 1570 return (DECODE_NO_MORE_DATA); 1571 mbc->chain_offset += skip; 1572 return (0); 1573 } 1574 1575 /* 1576 * Converts oem string to UTF-8 string with an output string of max 1577 * maxconv bytes. The string may be truncated or not null-terminated if 1578 * there is not enough room. 1579 * 1580 * returns -1, cnt (partial conversion) or 0 (success) 1581 */ 1582 1583 static int 1584 mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv, 1585 char *inbuf, size_t srcbytes) 1586 { 1587 kiconv_t t2u; 1588 size_t inlen = srcbytes; 1589 size_t outlen = maxconv; 1590 int err = 0; 1591 size_t rc; 1592 1593 if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1) 1594 return (-1); 1595 1596 rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err); 1597 (void) kiconv_close(t2u); 1598 return ((int)rc); 1599 } 1600