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 2018 Nexenta Systems, 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_atrunc() 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_atrunc encode\n"); 154 goto out; 155 } 156 /* Trunc should put exactly 4 */ 157 if (mbc->chain->m_len != 4) { 158 printf("Fail: mbm_put_atrunc 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_atrunc cmp:\n"); 165 hexdump((uchar_t *)mbc->chain->m_data, 4); 166 return; 167 } 168 169 printf("Pass: mbm_put_atrunc\n"); 170 171 out: 172 smb_mbc_free(mbc); 173 } 174 175 /* 176 * Put unicode string with NULL 177 */ 178 static void 179 mbm_put_u0() 180 { 181 uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 182 mbuf_chain_t *mbc; 183 int rc; 184 185 mbc = smb_mbc_alloc(100); 186 187 rc = smb_mbc_encodef(mbc, "Uw", "one", 42); 188 if (rc != 0) { 189 printf("Fail: mbm_put_u0 encode\n"); 190 goto out; 191 } 192 if (mbc->chain->m_len != 10) { 193 printf("Fail: mbm_put_u0 len=%d\n", 194 mbc->chain->m_len); 195 return; 196 } 197 198 if (memcmp(mbc->chain->m_data, wire, 10)) { 199 printf("Fail: mbm_put_u0 cmp:\n"); 200 hexdump((uchar_t *)mbc->chain->m_data, 10); 201 return; 202 } 203 204 printf("Pass: mbm_put_u0\n"); 205 206 out: 207 smb_mbc_free(mbc); 208 } 209 210 /* 211 * Put unicode string, no NULL 212 */ 213 static void 214 mbm_put_u1() 215 { 216 uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 217 mbuf_chain_t *mbc; 218 int rc; 219 220 mbc = smb_mbc_alloc(100); 221 222 rc = smb_mbc_encodef(mbc, "8Uw", "one.", 42); 223 if (rc != 0) { 224 printf("Fail: mbm_put_u1 encode\n"); 225 goto out; 226 } 227 if (mbc->chain->m_len != 10) { 228 printf("Fail: mbm_put_u1 len=%d\n", 229 mbc->chain->m_len); 230 return; 231 } 232 233 if (memcmp(mbc->chain->m_data, wire, 10)) { 234 printf("Fail: mbm_put_u1 cmp:\n"); 235 hexdump((uchar_t *)mbc->chain->m_data, 10); 236 return; 237 } 238 239 printf("Pass: mbm_put_u1\n"); 240 241 out: 242 smb_mbc_free(mbc); 243 } 244 245 static void 246 mbm_put_u3() 247 { 248 mbuf_chain_t *mbc; 249 int rc; 250 251 mbc = smb_mbc_alloc(100); 252 253 rc = smb_mbc_encodef(mbc, "U", mbsa); 254 if (rc != 0) { 255 printf("Fail: mbm_put_u3 encode\n"); 256 goto out; 257 } 258 if (mbc->chain->m_len != 8) { 259 printf("Fail: mbm_put_u3 len=%d\n", 260 mbc->chain->m_len); 261 return; 262 } 263 264 if (memcmp(mbc->chain->m_data, wcsa, 8)) { 265 printf("Fail: mbm_put_u3 cmp:\n"); 266 hexdump((uchar_t *)mbc->chain->m_data, 8); 267 return; 268 } 269 270 printf("Pass: mbm_put_u3\n"); 271 272 out: 273 smb_mbc_free(mbc); 274 } 275 276 static void 277 mbm_put_u4() 278 { 279 mbuf_chain_t *mbc; 280 int rc; 281 282 mbc = smb_mbc_alloc(100); 283 284 rc = smb_mbc_encodef(mbc, "U", mbsp); 285 if (rc != 0) { 286 printf("Fail: mbm_put_u4 encode\n"); 287 goto out; 288 } 289 if (mbc->chain->m_len != 10) { 290 printf("Fail: mbm_put_u4 len=%d\n", 291 mbc->chain->m_len); 292 return; 293 } 294 295 if (memcmp(mbc->chain->m_data, wcsp, 10)) { 296 printf("Fail: mbm_put_u4 cmp:\n"); 297 hexdump((uchar_t *)mbc->chain->m_data, 10); 298 return; 299 } 300 301 printf("Pass: mbm_put_u4\n"); 302 303 out: 304 smb_mbc_free(mbc); 305 } 306 307 static void 308 mbm_put_upad() 309 { 310 uint16_t wire[] = { 'o', 'n', 'e', 0, 0 }; 311 mbuf_chain_t *mbc; 312 int rc; 313 314 mbc = smb_mbc_alloc(100); 315 316 /* Encode with wire length > strlen */ 317 rc = smb_mbc_encodef(mbc, "10U", "one"); 318 if (rc != 0) { 319 printf("Fail: mbm_put_upad encode\n"); 320 goto out; 321 } 322 if (mbc->chain->m_len != 10) { 323 printf("Fail: mbm_put_upad len=%d\n", 324 mbc->chain->m_len); 325 return; 326 } 327 328 if (memcmp(mbc->chain->m_data, wire, 10)) { 329 printf("Fail: mbm_put_upad cmp:\n"); 330 hexdump((uchar_t *)mbc->chain->m_data, 10); 331 return; 332 } 333 334 printf("Pass: mbm_put_upad\n"); 335 336 out: 337 smb_mbc_free(mbc); 338 } 339 340 static void 341 mbm_put_utrunc() 342 { 343 uint16_t wire[] = { 'o', 'n', 'e', 't' }; 344 mbuf_chain_t *mbc; 345 int rc; 346 347 mbc = smb_mbc_alloc(100); 348 349 /* Encode with wire length < strlen */ 350 rc = smb_mbc_encodef(mbc, "8U", "onetwo"); 351 if (rc != 0) { 352 printf("Fail: mbm_put_utrunc encode\n"); 353 goto out; 354 } 355 /* Trunc should put exactly 8 */ 356 if (mbc->chain->m_len != 8) { 357 printf("Fail: mbm_put_utrunc len=%d\n", 358 mbc->chain->m_len); 359 return; 360 } 361 362 if (memcmp(mbc->chain->m_data, wire, 8)) { 363 printf("Fail: mbm_put_utrunc cmp:\n"); 364 hexdump((uchar_t *)mbc->chain->m_data, 8); 365 return; 366 } 367 368 printf("Pass: mbm_put_utrunc\n"); 369 370 out: 371 smb_mbc_free(mbc); 372 } 373 374 /* 375 * Parse an ascii string. 376 */ 377 static void 378 mbm_get_a0() 379 { 380 uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 381 mbuf_chain_t mbc; 382 char *s; 383 int rc; 384 uint16_t w; 385 386 bzero(&mbc, sizeof (mbc)); 387 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 388 389 rc = smb_mbc_decodef(&mbc, "%sw", &test_sr, &s, &w); 390 if (rc != 0) { 391 printf("Fail: mbm_get_a0 decode\n"); 392 goto out; 393 } 394 /* 395 * Decode a word after the string to make sure we 396 * end up positioned correctly after the string. 397 */ 398 if (w != 42) { 399 printf("Fail: mbm_get_a0 w=%d\n", w); 400 return; 401 } 402 if (strcmp(s, "one") != 0) { 403 printf("Fail: mbm_get_a0 cmp: <%s>\n", s); 404 return; 405 } 406 407 printf("Pass: mbm_get_a0\n"); 408 409 out: 410 MBC_FLUSH(&mbc); 411 } 412 413 /* 414 * Parse an ascii string, no NULL 415 */ 416 static void 417 mbm_get_a1() 418 { 419 uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 420 mbuf_chain_t mbc; 421 char *s; 422 int rc; 423 uint16_t w; 424 425 bzero(&mbc, sizeof (mbc)); 426 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 427 428 rc = smb_mbc_decodef(&mbc, "%3s.w", &test_sr, &s, &w); 429 if (rc != 0) { 430 printf("Fail: mbm_get_a1 decode\n"); 431 goto out; 432 } 433 /* 434 * Decode a word after the string to make sure we 435 * end up positioned correctly after the string. 436 */ 437 if (w != 42) { 438 printf("Fail: mbm_get_a1 w=%d\n", w); 439 return; 440 } 441 if (strcmp(s, "one") != 0) { 442 printf("Fail: mbm_get_a1 cmp: <%s>\n", s); 443 return; 444 } 445 446 printf("Pass: mbm_get_a1\n"); 447 448 out: 449 MBC_FLUSH(&mbc); 450 } 451 452 /* parse exactly to end of data */ 453 static void 454 mbm_get_a2() 455 { 456 uint8_t wire[] = { 'o', 'n', 'e' }; 457 mbuf_chain_t mbc; 458 char *s; 459 int rc; 460 461 bzero(&mbc, sizeof (mbc)); 462 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 463 464 rc = smb_mbc_decodef(&mbc, "%3s", &test_sr, &s); 465 if (rc != 0) { 466 printf("Fail: mbm_get_a2 decode\n"); 467 goto out; 468 } 469 if (mbc.chain_offset != 3) { 470 printf("Fail: mbm_get_a2 wrong pos\n"); 471 return; 472 } 473 if (strcmp(s, "one") != 0) { 474 printf("Fail: mbm_get_a2 cmp: <%s>\n", s); 475 return; 476 } 477 478 printf("Pass: mbm_get_a2\n"); 479 480 out: 481 MBC_FLUSH(&mbc); 482 } 483 484 /* 485 * Parse a unicode string. 486 */ 487 static void 488 mbm_get_u0() 489 { 490 uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; 491 mbuf_chain_t mbc; 492 char *s; 493 int rc; 494 uint16_t w; 495 496 bzero(&mbc, sizeof (mbc)); 497 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 498 499 rc = smb_mbc_decodef(&mbc, "%Uw", &test_sr, &s, &w); 500 if (rc != 0) { 501 printf("Fail: mbm_get_u0 decode\n"); 502 goto out; 503 } 504 /* 505 * Decode a word after the string to make sure we 506 * end up positioned correctly after the string. 507 */ 508 if (w != 42) { 509 printf("Fail: mbm_get_u0 w=%d\n", w); 510 return; 511 } 512 if (strcmp(s, "one") != 0) { 513 printf("Fail: mbm_get_u0 cmp: <%s>\n", s); 514 return; 515 } 516 517 printf("Pass: mbm_get_u0\n"); 518 519 out: 520 MBC_FLUSH(&mbc); 521 } 522 523 /* 524 * Parse a string that's NOT null terminated. 525 */ 526 static void 527 mbm_get_u1() 528 { 529 uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; 530 mbuf_chain_t mbc; 531 char *s; 532 int rc; 533 uint16_t w; 534 535 bzero(&mbc, sizeof (mbc)); 536 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 537 538 rc = smb_mbc_decodef(&mbc, "%6U..w", &test_sr, &s, &w); 539 if (rc != 0) { 540 printf("Fail: mbm_get_u1 decode\n"); 541 goto out; 542 } 543 /* 544 * Decode a word after the string to make sure we 545 * end up positioned correctly after the string. 546 */ 547 if (w != 42) { 548 printf("Fail: mbm_get_u1 w=%d\n", w); 549 return; 550 } 551 if (strcmp(s, "one") != 0) { 552 printf("Fail: mbm_get_u1 cmp: <%s>\n", s); 553 return; 554 } 555 556 printf("Pass: mbm_get_u1\n"); 557 558 out: 559 MBC_FLUSH(&mbc); 560 } 561 562 /* parse exactly to end of data */ 563 static void 564 mbm_get_u2() 565 { 566 uint16_t wire[] = { 't', 'w', 'o' }; 567 mbuf_chain_t mbc; 568 char *s; 569 int rc; 570 571 bzero(&mbc, sizeof (mbc)); 572 MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); 573 574 rc = smb_mbc_decodef(&mbc, "%6U", &test_sr, &s); 575 if (rc != 0) { 576 printf("Fail: mbm_get_u2 decode\n"); 577 goto out; 578 } 579 if (mbc.chain_offset != 6) { 580 printf("Fail: mbm_get_u2 wrong pos\n"); 581 return; 582 } 583 if (strcmp(s, "two") != 0) { 584 printf("Fail: mbm_get_u2 cmp: <%s>\n", s); 585 return; 586 } 587 588 printf("Pass: mbm_get_a2\n"); 589 590 out: 591 MBC_FLUSH(&mbc); 592 } 593 594 static void 595 mbm_get_u3() 596 { 597 mbuf_chain_t mbc; 598 char *s; 599 int rc; 600 601 bzero(&mbc, sizeof (mbc)); 602 MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsa, sizeof (wcsa)); 603 604 rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsa), &s); 605 if (rc != 0) { 606 printf("Fail: mbm_get_u3 decode\n"); 607 goto out; 608 } 609 if (strcmp(s, mbsa) != 0) { 610 printf("Fail: mbm_get_u3 cmp: <%s>\n", s); 611 return; 612 } 613 614 printf("Pass: mbm_get_u3\n"); 615 616 out: 617 MBC_FLUSH(&mbc); 618 } 619 620 static void 621 mbm_get_u4() 622 { 623 mbuf_chain_t mbc; 624 char *s; 625 int rc; 626 627 bzero(&mbc, sizeof (mbc)); 628 MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsp, sizeof (wcsp)); 629 630 rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsp), &s); 631 if (rc != 0) { 632 printf("Fail: mbm_get_u4 decode\n"); 633 goto out; 634 } 635 if (strcmp(s, mbsp) != 0) { 636 printf("Fail: mbm_get_u4 cmp: <%s>\n", s); 637 return; 638 } 639 640 printf("Pass: mbm_get_u4\n"); 641 642 out: 643 MBC_FLUSH(&mbc); 644 } 645 646 void 647 test_mbmarshal() 648 { 649 650 smb_mbc_init(); 651 652 test_ssn.dialect = 0x210; // SMB 2.1 653 test_sr.session = &test_ssn; 654 test_sr.sr_magic = SMB_REQ_MAGIC; 655 smb_srm_init(&test_sr); 656 657 mbm_put_a0(); 658 mbm_put_a1(); 659 mbm_put_apad(); 660 mbm_put_atrunc(); 661 662 mbm_put_u0(); 663 mbm_put_u1(); 664 mbm_put_u3(); 665 mbm_put_u4(); 666 mbm_put_upad(); 667 mbm_put_utrunc(); 668 669 mbm_get_a0(); 670 mbm_get_a1(); 671 mbm_get_a2(); 672 mbm_get_u0(); 673 mbm_get_u1(); 674 mbm_get_u2(); 675 mbm_get_u3(); 676 mbm_get_u4(); 677 678 smb_srm_fini(&test_sr); 679 smb_mbc_fini(); 680 } 681