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 }