1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. 14 */ 15 16 /* 17 * Test putting/getting unicode strings in mbchains. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/debug.h> 22 #include <sys/varargs.h> 23 #include <smbsrv/smb_kproto.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <strings.h> 27 28 #include "test_defs.h" 29 30 static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) 31 static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) 32 static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 }; // (3) 33 static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) 34 35 smb_session_t test_ssn; 36 smb_request_t test_sr; 37 38 /* 39 * Put ASCII string with NULL 40 */ 41 static void 42 mbm_put_a0() 43 { 44 uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 45 mbuf_chain_t *mbc; 46 int rc; 47 48 mbc = smb_mbc_alloc(100); 49 50 rc = smb_mbc_encodef(mbc, "sw", "one", 42); 51 if (rc != 0) { 52 printf("Fail: mbm_put_a0 encode\n"); 53 goto out; 54 } 55 if (mbc->chain->m_len != 6) { 56 printf("Fail: mbm_put_a0 len=%d\n", 57 mbc->chain->m_len); 58 return; 59 } 60 61 if (memcmp(mbc->chain->m_data, wire, 6)) { 62 printf("Fail: mbm_put_a0 cmp:\n"); 63 hexdump((uchar_t *)mbc->chain->m_data, 6); 64 return; 65 } 66 67 printf("Pass: mbm_put_a0\n"); 68 69 out: 70 smb_mbc_free(mbc); 71 } 72 73 /* 74 * Put ASCII string, no NULL 75 */ 76 static void 77 mbm_put_a1() 78 { 79 uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 80 mbuf_chain_t *mbc; 81 int rc; 82 83 mbc = smb_mbc_alloc(100); 84 85 rc = smb_mbc_encodef(mbc, "4sw", "one.", 42); 86 if (rc != 0) { 87 printf("Fail: mbm_put_a1 encode\n"); 88 goto out; 89 } 90 if (mbc->chain->m_len != 6) { 91 printf("Fail: mbm_put_a1 len=%d\n", 92 mbc->chain->m_len); 93 return; 94 } 95 96 if (memcmp(mbc->chain->m_data, wire, 6)) { 97 printf("Fail: mbm_put_a1 cmp:\n"); 98 hexdump((uchar_t *)mbc->chain->m_data, 6); 99 return; 100 } 101 102 printf("Pass: mbm_put_a1\n"); 103 104 out: 105 smb_mbc_free(mbc); 106 } 107 108 static void 109 mbm_put_apad() 110 { 111 uint8_t wire[] = { 'o', 'n', 'e', 0, 0 }; 112 mbuf_chain_t *mbc; 113 int rc; 114 115 mbc = smb_mbc_alloc(100); 116 117 /* Encode with wire length > strlen */ 118 rc = smb_mbc_encodef(mbc, "5s", "one"); 119 if (rc != 0) { 120 printf("Fail: mbm_put_apad encode\n"); 121 goto out; 122 } 123 if (mbc->chain->m_len != 5) { 124 printf("Fail: mbm_put_apad len=%d\n", 125 mbc->chain->m_len); 126 return; 127 } 128 129 if (memcmp(mbc->chain->m_data, wire, 5)) { 130 printf("Fail: mbm_put_apad cmp:\n"); 131 hexdump((uchar_t *)mbc->chain->m_data, 5); 132 return; 133 } 134 135 printf("Pass: mbm_put_apad\n"); 136 137 out: 138 smb_mbc_free(mbc); 139 } 140 141 static void 142 mbm_put_atrunc1() 143 { 144 uint8_t wire[] = { 'o', 'n', 'e', 't', }; 145 mbuf_chain_t *mbc; 146 int rc; 147 148 mbc = smb_mbc_alloc(100); 149 150 /* Encode with wire length < strlen */ 151 rc = smb_mbc_encodef(mbc, "4s", "onetwo"); 152 if (rc != 0) { 153 printf("Fail: mbm_put_atrunc1 encode\n"); 154 goto out; 155 } 156 /* Trunc should put exactly 4 */ 157 if (mbc->chain->m_len != 4) { 158 printf("Fail: mbm_put_atrunc1 len=%d\n", 159 mbc->chain->m_len); 160 return; 161 } 162 163 if (memcmp(mbc->chain->m_data, wire, 4)) { 164 printf("Fail: mbm_put_atrunc1 cmp:\n"); 165 hexdump((uchar_t *)mbc->chain->m_data, 4); 166 return; 167 } 168 169 printf("Pass: mbm_put_atrunc1\n"); 170 171 out: 172 smb_mbc_free(mbc); 173 } 174 175 static void 176 mbm_put_atrunc2() 177 { 178 uint8_t wire[] = { 'o', 'n', 'e', 't', 0 }; 179 mbuf_chain_t *mbc; 180 int rc; 181 182 mbc = smb_mbc_alloc(4); 183 184 /* Encode with wire length < strlen */ 185 rc = smb_mbc_encodef(mbc, "s", "onetwo"); 186 if (rc != 1) { 187 printf("Fail: mbm_put_atrunc2 encode rc=%d\n", rc); 188 goto out; 189 } 190 /* Trunc should put exactly 4 */ 191 if (mbc->chain->m_len != 4) { 192 printf("Fail: mbm_put_atrunc2 len=%d\n", 193 mbc->chain->m_len); 194 return; 195 } 196 197 if (memcmp(mbc->chain->m_data, wire, 5)) { 198 printf("Fail: mbm_put_atrunc2 cmp:\n"); 199 hexdump((uchar_t *)mbc->chain->m_data, 4); 200 return; 201 } 202 203 printf("Pass: mbm_put_atrunc2\n"); 204 205 out: 206 smb_mbc_free(mbc); 207 } 208 209 /* 210 * Put unicode string with NULL 211 */ 212 static void 213 mbm_put_u0() 214 { 215 uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 216 mbuf_chain_t *mbc; 217 int rc; 218 219 mbc = smb_mbc_alloc(100); 220 221 rc = smb_mbc_encodef(mbc, "Uw", "one", 42); 222 if (rc != 0) { 223 printf("Fail: mbm_put_u0 encode\n"); 224 goto out; 225 } 226 if (mbc->chain->m_len != 10) { 227 printf("Fail: mbm_put_u0 len=%d\n", 228 mbc->chain->m_len); 229 return; 230 } 231 232 if (memcmp(mbc->chain->m_data, wire, 10)) { 233 printf("Fail: mbm_put_u0 cmp:\n"); 234 hexdump((uchar_t *)mbc->chain->m_data, 10); 235 return; 236 } 237 238 printf("Pass: mbm_put_u0\n"); 239 240 out: 241 smb_mbc_free(mbc); 242 } 243 244 /* 245 * Put unicode string, no NULL 246 */ 247 static void 248 mbm_put_u1() 249 { 250 uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 251 mbuf_chain_t *mbc; 252 int rc; 253 254 mbc = smb_mbc_alloc(100); 255 256 rc = smb_mbc_encodef(mbc, "8Uw", "one.", 42); 257 if (rc != 0) { 258 printf("Fail: mbm_put_u1 encode\n"); 259 goto out; 260 } 261 if (mbc->chain->m_len != 10) { 262 printf("Fail: mbm_put_u1 len=%d\n", 263 mbc->chain->m_len); 264 return; 265 } 266 267 if (memcmp(mbc->chain->m_data, wire, 10)) { 268 printf("Fail: mbm_put_u1 cmp:\n"); 269 hexdump((uchar_t *)mbc->chain->m_data, 10); 270 return; 271 } 272 273 printf("Pass: mbm_put_u1\n"); 274 275 out: 276 smb_mbc_free(mbc); 277 } 278 279 static void 280 mbm_put_u3() 281 { 282 mbuf_chain_t *mbc; 283 int rc; 284 285 mbc = smb_mbc_alloc(100); 286 287 rc = smb_mbc_encodef(mbc, "U", mbsa); 288 if (rc != 0) { 289 printf("Fail: mbm_put_u3 encode\n"); 290 goto out; 291 } 292 if (mbc->chain->m_len != 8) { 293 printf("Fail: mbm_put_u3 len=%d\n", 294 mbc->chain->m_len); 295 return; 296 } 297 298 if (memcmp(mbc->chain->m_data, wcsa, 8)) { 299 printf("Fail: mbm_put_u3 cmp:\n"); 300 hexdump((uchar_t *)mbc->chain->m_data, 8); 301 return; 302 } 303 304 printf("Pass: mbm_put_u3\n"); 305 306 out: 307 smb_mbc_free(mbc); 308 } 309 310 static void 311 mbm_put_u4() 312 { 313 mbuf_chain_t *mbc; 314 int rc; 315 316 mbc = smb_mbc_alloc(100); 317 318 rc = smb_mbc_encodef(mbc, "U", mbsp); 319 if (rc != 0) { 320 printf("Fail: mbm_put_u4 encode\n"); 321 goto out; 322 } 323 if (mbc->chain->m_len != 10) { 324 printf("Fail: mbm_put_u4 len=%d\n", 325 mbc->chain->m_len); 326 return; 327 } 328 329 if (memcmp(mbc->chain->m_data, wcsp, 10)) { 330 printf("Fail: mbm_put_u4 cmp:\n"); 331 hexdump((uchar_t *)mbc->chain->m_data, 10); 332 return; 333 } 334 335 printf("Pass: mbm_put_u4\n"); 336 337 out: 338 smb_mbc_free(mbc); 339 } 340 341 static void 342 mbm_put_upad() 343 { 344 uint16_t wire[] = { 'o', 'n', 'e', 0, 0 }; 345 mbuf_chain_t *mbc; 346 int rc; 347 348 mbc = smb_mbc_alloc(100); 349 350 /* Encode with wire length > strlen */ 351 rc = smb_mbc_encodef(mbc, "10U", "one"); 352 if (rc != 0) { 353 printf("Fail: mbm_put_upad encode\n"); 354 goto out; 355 } 356 if (mbc->chain->m_len != 10) { 357 printf("Fail: mbm_put_upad len=%d\n", 358 mbc->chain->m_len); 359 return; 360 } 361 362 if (memcmp(mbc->chain->m_data, wire, 10)) { 363 printf("Fail: mbm_put_upad cmp:\n"); 364 hexdump((uchar_t *)mbc->chain->m_data, 10); 365 return; 366 } 367 368 printf("Pass: mbm_put_upad\n"); 369 370 out: 371 smb_mbc_free(mbc); 372 } 373 374 static void 375 mbm_put_utrunc1() 376 { 377 uint16_t wire[] = { 'o', 'n', 'e', 't' }; 378 mbuf_chain_t *mbc; 379 int rc; 380 381 mbc = smb_mbc_alloc(100); 382 383 /* Encode with wire length < strlen */ 384 rc = smb_mbc_encodef(mbc, "8U", "onetwo"); 385 if (rc != 0) { 386 printf("Fail: mbm_put_utrunc1 encode\n"); 387 goto out; 388 } 389 /* Trunc should put exactly 8 */ 390 if (mbc->chain->m_len != 8) { 391 printf("Fail: mbm_put_utrunc1 len=%d\n", 392 mbc->chain->m_len); 393 return; 394 } 395 396 if (memcmp(mbc->chain->m_data, wire, 8)) { 397 printf("Fail: mbm_put_utrunc1 cmp:\n"); 398 hexdump((uchar_t *)mbc->chain->m_data, 8); 399 return; 400 } 401 402 printf("Pass: mbm_put_utrunc1\n"); 403 404 out: 405 smb_mbc_free(mbc); 406 } 407 408 static void 409 mbm_put_utrunc2() 410 { 411 uint16_t wire[] = { 'o', 'n', 'e', 't', 0 }; 412 mbuf_chain_t *mbc; 413 int rc; 414 415 mbc = smb_mbc_alloc(8); 416 417 /* Encode with wire length < strlen */ 418 rc = smb_mbc_encodef(mbc, "U", "onetwo"); 419 if (rc != 1) { 420 printf("Fail: mbm_put_utrunc2 encode rc=%d\n", rc); 421 goto out; 422 } 423 /* Trunc should put exactly 8 */ 424 if (mbc->chain->m_len != 8) { 425 printf("Fail: mbm_put_utrunc2 len=%d\n", 426 mbc->chain->m_len); 427 return; 428 } 429 430 if (memcmp(mbc->chain->m_data, wire, 10)) { 431 printf("Fail: mbm_put_utrunc2 cmp:\n"); 432 hexdump((uchar_t *)mbc->chain->m_data, 8); 433 return; 434 } 435 436 printf("Pass: mbm_put_utrunc2\n"); 437 438 out: 439 smb_mbc_free(mbc); 440 } 441 442 /* 443 * Parse an ascii string. 444 */ 445 static void 446 mbm_get_a0() 447 { 448 uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 449 mbuf_chain_t mbc; 450 char *s; 451 int rc; 452 uint16_t w; 453 454 bzero(&mbc, sizeof (mbc)); 455 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 456 457 rc = smb_mbc_decodef(&mbc, "%sw", &test_sr, &s, &w); 458 if (rc != 0) { 459 printf("Fail: mbm_get_a0 decode\n"); 460 goto out; 461 } 462 /* 463 * Decode a word after the string to make sure we 464 * end up positioned correctly after the string. 465 */ 466 if (w != 42) { 467 printf("Fail: mbm_get_a0 w=%d\n", w); 468 return; 469 } 470 if (strcmp(s, "one") != 0) { 471 printf("Fail: mbm_get_a0 cmp: <%s>\n", s); 472 return; 473 } 474 475 printf("Pass: mbm_get_a0\n"); 476 477 out: 478 MBC_FLUSH(&mbc); 479 } 480 481 /* 482 * Parse an ascii string, no NULL 483 */ 484 static void 485 mbm_get_a1() 486 { 487 uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 488 mbuf_chain_t mbc; 489 char *s; 490 int rc; 491 uint16_t w; 492 493 bzero(&mbc, sizeof (mbc)); 494 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 495 496 rc = smb_mbc_decodef(&mbc, "%3s.w", &test_sr, &s, &w); 497 if (rc != 0) { 498 printf("Fail: mbm_get_a1 decode\n"); 499 goto out; 500 } 501 /* 502 * Decode a word after the string to make sure we 503 * end up positioned correctly after the string. 504 */ 505 if (w != 42) { 506 printf("Fail: mbm_get_a1 w=%d\n", w); 507 return; 508 } 509 if (strcmp(s, "one") != 0) { 510 printf("Fail: mbm_get_a1 cmp: <%s>\n", s); 511 return; 512 } 513 514 printf("Pass: mbm_get_a1\n"); 515 516 out: 517 MBC_FLUSH(&mbc); 518 } 519 520 /* parse exactly to end of data */ 521 static void 522 mbm_get_a2() 523 { 524 uint8_t wire[] = { 'o', 'n', 'e' }; 525 mbuf_chain_t mbc; 526 char *s; 527 int rc; 528 529 bzero(&mbc, sizeof (mbc)); 530 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 531 532 rc = smb_mbc_decodef(&mbc, "%3s", &test_sr, &s); 533 if (rc != 0) { 534 printf("Fail: mbm_get_a2 decode\n"); 535 goto out; 536 } 537 if (mbc.chain_offset != 3) { 538 printf("Fail: mbm_get_a2 wrong pos\n"); 539 return; 540 } 541 if (strcmp(s, "one") != 0) { 542 printf("Fail: mbm_get_a2 cmp: <%s>\n", s); 543 return; 544 } 545 546 printf("Pass: mbm_get_a2\n"); 547 548 out: 549 MBC_FLUSH(&mbc); 550 } 551 552 /* 553 * Parse a unicode string. 554 */ 555 static void 556 mbm_get_u0() 557 { 558 uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 559 mbuf_chain_t mbc; 560 char *s; 561 int rc; 562 uint16_t w; 563 564 bzero(&mbc, sizeof (mbc)); 565 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 566 567 rc = smb_mbc_decodef(&mbc, "%Uw", &test_sr, &s, &w); 568 if (rc != 0) { 569 printf("Fail: mbm_get_u0 decode\n"); 570 goto out; 571 } 572 /* 573 * Decode a word after the string to make sure we 574 * end up positioned correctly after the string. 575 */ 576 if (w != 42) { 577 printf("Fail: mbm_get_u0 w=%d\n", w); 578 return; 579 } 580 if (strcmp(s, "one") != 0) { 581 printf("Fail: mbm_get_u0 cmp: <%s>\n", s); 582 return; 583 } 584 585 printf("Pass: mbm_get_u0\n"); 586 587 out: 588 MBC_FLUSH(&mbc); 589 } 590 591 /* 592 * Parse a string that's NOT null terminated. 593 */ 594 static void 595 mbm_get_u1() 596 { 597 uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 598 mbuf_chain_t mbc; 599 char *s; 600 int rc; 601 uint16_t w; 602 603 bzero(&mbc, sizeof (mbc)); 604 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 605 606 rc = smb_mbc_decodef(&mbc, "%6U..w", &test_sr, &s, &w); 607 if (rc != 0) { 608 printf("Fail: mbm_get_u1 decode\n"); 609 goto out; 610 } 611 /* 612 * Decode a word after the string to make sure we 613 * end up positioned correctly after the string. 614 */ 615 if (w != 42) { 616 printf("Fail: mbm_get_u1 w=%d\n", w); 617 return; 618 } 619 if (strcmp(s, "one") != 0) { 620 printf("Fail: mbm_get_u1 cmp: <%s>\n", s); 621 return; 622 } 623 624 printf("Pass: mbm_get_u1\n"); 625 626 out: 627 MBC_FLUSH(&mbc); 628 } 629 630 /* parse exactly to end of data */ 631 static void 632 mbm_get_u2() 633 { 634 uint16_t wire[] = { 't', 'w', 'o' }; 635 mbuf_chain_t mbc; 636 char *s; 637 int rc; 638 639 bzero(&mbc, sizeof (mbc)); 640 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 641 642 rc = smb_mbc_decodef(&mbc, "%6U", &test_sr, &s); 643 if (rc != 0) { 644 printf("Fail: mbm_get_u2 decode\n"); 645 goto out; 646 } 647 if (mbc.chain_offset != 6) { 648 printf("Fail: mbm_get_u2 wrong pos\n"); 649 return; 650 } 651 if (strcmp(s, "two") != 0) { 652 printf("Fail: mbm_get_u2 cmp: <%s>\n", s); 653 return; 654 } 655 656 printf("Pass: mbm_get_a2\n"); 657 658 out: 659 MBC_FLUSH(&mbc); 660 } 661 662 static void 663 mbm_get_u3() 664 { 665 mbuf_chain_t mbc; 666 char *s; 667 int rc; 668 669 bzero(&mbc, sizeof (mbc)); 670 MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsa, sizeof (wcsa)); 671 672 rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsa), &s); 673 if (rc != 0) { 674 printf("Fail: mbm_get_u3 decode\n"); 675 goto out; 676 } 677 if (strcmp(s, mbsa) != 0) { 678 printf("Fail: mbm_get_u3 cmp: <%s>\n", s); 679 return; 680 } 681 682 printf("Pass: mbm_get_u3\n"); 683 684 out: 685 MBC_FLUSH(&mbc); 686 } 687 688 static void 689 mbm_get_u4() 690 { 691 mbuf_chain_t mbc; 692 char *s; 693 int rc; 694 695 bzero(&mbc, sizeof (mbc)); 696 MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsp, sizeof (wcsp)); 697 698 rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsp), &s); 699 if (rc != 0) { 700 printf("Fail: mbm_get_u4 decode\n"); 701 goto out; 702 } 703 if (strcmp(s, mbsp) != 0) { 704 printf("Fail: mbm_get_u4 cmp: <%s>\n", s); 705 return; 706 } 707 708 printf("Pass: mbm_get_u4\n"); 709 710 out: 711 MBC_FLUSH(&mbc); 712 } 713 714 void 715 test_mbmarshal() 716 { 717 718 smb_mbc_init(); 719 720 test_ssn.dialect = 0x210; // SMB 2.1 721 test_sr.session = &test_ssn; 722 test_sr.sr_magic = SMB_REQ_MAGIC; 723 smb_srm_init(&test_sr); 724 725 mbm_put_a0(); 726 mbm_put_a1(); 727 mbm_put_apad(); 728 mbm_put_atrunc1(); 729 mbm_put_atrunc2(); 730 731 mbm_put_u0(); 732 mbm_put_u1(); 733 mbm_put_u3(); 734 mbm_put_u4(); 735 mbm_put_upad(); 736 mbm_put_utrunc1(); 737 mbm_put_utrunc2(); 738 739 mbm_get_a0(); 740 mbm_get_a1(); 741 mbm_get_a2(); 742 mbm_get_u0(); 743 mbm_get_u1(); 744 mbm_get_u2(); 745 mbm_get_u3(); 746 mbm_get_u4(); 747 748 smb_srm_fini(&test_sr); 749 smb_mbc_fini(); 750 } 751