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 /*
  36  * Put ASCII string with NULL
  37  */
  38 static void
  39 msg_put_a0()
  40 {
  41         uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
  42         uint8_t temp[32];
  43         smb_msgbuf_t mb;
  44         int mbflags = 0;
  45         int rc;
  46 
  47         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
  48 
  49         rc = smb_msgbuf_encode(&mb, "sw", "one", 42);
  50         if (rc != 6) {
  51                 printf("Fail: msg_put_a0 encode\n");
  52                 goto out;
  53         }
  54 
  55         if (memcmp(temp, wire, 6)) {
  56                 printf("Fail: msg_put_a0 cmp:\n");
  57                 hexdump((uchar_t *)temp, 6);
  58                 return;
  59         }
  60 
  61         printf("Pass: msg_put_a0\n");
  62 
  63 out:
  64         smb_msgbuf_term(&mb);
  65 }
  66 
  67 /*
  68  * Put ASCII string, no NULL
  69  */
  70 static void
  71 msg_put_a1()
  72 {
  73         uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
  74         uint8_t temp[32];
  75         smb_msgbuf_t mb;
  76         int mbflags = 0;
  77         int rc;
  78 
  79         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
  80 
  81         rc = smb_msgbuf_encode(&mb, "4sw", "one.", 42);
  82         if (rc != 6) {
  83                 printf("Fail: msg_put_a1 encode\n");
  84                 goto out;
  85         }
  86 
  87         if (memcmp(temp, wire, 6)) {
  88                 printf("Fail: msg_put_a1 cmp:\n");
  89                 hexdump((uchar_t *)temp, 6);
  90                 return;
  91         }
  92 
  93         printf("Pass: msg_put_a1\n");
  94 
  95 out:
  96         smb_msgbuf_term(&mb);
  97 }
  98 
  99 static void
 100 msg_put_apad()
 101 {
 102         uint8_t wire[] = { 'o', 'n', 'e', 0, 0 };
 103         uint8_t temp[32];
 104         smb_msgbuf_t mb;
 105         int mbflags = 0;
 106         int rc;
 107 
 108         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 109 
 110         /* Encode with wire length > strlen */
 111         rc = smb_msgbuf_encode(&mb, "5s", "one");
 112         if (rc != 5) {
 113                 printf("Fail: msg_put_apad encode\n");
 114                 goto out;
 115         }
 116 
 117         if (memcmp(temp, wire, 5)) {
 118                 printf("Fail: msg_put_apad cmp:\n");
 119                 hexdump((uchar_t *)temp, 5);
 120                 return;
 121         }
 122 
 123         printf("Pass: msg_put_apad\n");
 124 
 125 out:
 126         smb_msgbuf_term(&mb);
 127 }
 128 
 129 static void
 130 msg_put_atrunc()
 131 {
 132         uint8_t wire[] = { 'o', 'n', 'e', 't', };
 133         uint8_t temp[32];
 134         smb_msgbuf_t mb;
 135         int mbflags = 0;
 136         int rc;
 137 
 138         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 139 
 140         /* Encode with wire length < strlen */
 141         rc = smb_msgbuf_encode(&mb, "4s", "onetwo");
 142         /* Trunc should put exactly 4 */
 143         if (rc != 4) {
 144                 printf("Fail: msg_put_atrunc encode\n");
 145                 goto out;
 146         }
 147 
 148         if (memcmp(temp, wire, 4)) {
 149                 printf("Fail: msg_put_atrunc cmp:\n");
 150                 hexdump((uchar_t *)temp, 4);
 151                 return;
 152         }
 153 
 154         printf("Pass: msg_put_atrunc\n");
 155 
 156 out:
 157         smb_msgbuf_term(&mb);
 158 }
 159 
 160 /*
 161  * Put unicode string with NULL
 162  */
 163 static void
 164 msg_put_u0()
 165 {
 166         uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
 167         uint8_t temp[32];
 168         smb_msgbuf_t mb;
 169         int mbflags = 0;
 170         int rc;
 171 
 172         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 173 
 174         rc = smb_msgbuf_encode(&mb, "Uw", "one", 42);
 175         if (rc != 10) {
 176                 printf("Fail: msg_put_u0 encode\n");
 177                 goto out;
 178         }
 179 
 180         if (memcmp(temp, wire, 10)) {
 181                 printf("Fail: msg_put_u0 cmp:\n");
 182                 hexdump((uchar_t *)temp, 10);
 183                 return;
 184         }
 185 
 186         printf("Pass: msg_put_u0\n");
 187 
 188 out:
 189         smb_msgbuf_term(&mb);
 190 }
 191 
 192 /*
 193  * Put unicode string, no NULL
 194  */
 195 static void
 196 msg_put_u1()
 197 {
 198         uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
 199         uint8_t temp[32];
 200         smb_msgbuf_t mb;
 201         int mbflags = 0;
 202         int rc;
 203 
 204         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 205 
 206         rc = smb_msgbuf_encode(&mb, "8Uw", "one.", 42);
 207         if (rc != 10) {
 208                 printf("Fail: msg_put_u1 encode\n");
 209                 goto out;
 210         }
 211 
 212         if (memcmp(temp, wire, 10)) {
 213                 printf("Fail: msg_put_u1 cmp:\n");
 214                 hexdump((uchar_t *)temp, 10);
 215                 return;
 216         }
 217 
 218         printf("Pass: msg_put_u1\n");
 219 
 220 out:
 221         smb_msgbuf_term(&mb);
 222 }
 223 
 224 static void
 225 msg_put_u3()
 226 {
 227         uint8_t temp[32];
 228         smb_msgbuf_t mb;
 229         int mbflags = 0;
 230         int rc;
 231 
 232         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 233 
 234         rc = smb_msgbuf_encode(&mb, "U", mbsa);
 235         if (rc != 8) {
 236                 printf("Fail: msg_put_u3 encode\n");
 237                 goto out;
 238         }
 239 
 240         if (memcmp(temp, wcsa, 8)) {
 241                 printf("Fail: msg_put_u3 cmp:\n");
 242                 hexdump((uchar_t *)temp, 8);
 243                 return;
 244         }
 245 
 246         printf("Pass: msg_put_u3\n");
 247 
 248 out:
 249         smb_msgbuf_term(&mb);
 250 }
 251 
 252 static void
 253 msg_put_u4()
 254 {
 255         uint8_t temp[32];
 256         smb_msgbuf_t mb;
 257         int mbflags = 0;
 258         int rc;
 259 
 260         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 261 
 262         rc = smb_msgbuf_encode(&mb, "U", mbsp);
 263         if (rc != 10) {
 264                 printf("Fail: msg_put_u4 encode\n");
 265                 goto out;
 266         }
 267 
 268         if (memcmp(temp, wcsp, 10)) {
 269                 printf("Fail: msg_put_u4 cmp:\n");
 270                 hexdump((uchar_t *)temp, 10);
 271                 return;
 272         }
 273 
 274         printf("Pass: msg_put_u4\n");
 275 
 276 out:
 277         smb_msgbuf_term(&mb);
 278 }
 279 
 280 static void
 281 msg_put_upad()
 282 {
 283         uint16_t wire[] = { 'o', 'n', 'e', 0, 0 };
 284         uint8_t temp[32];
 285         smb_msgbuf_t mb;
 286         int mbflags = 0;
 287         int rc;
 288 
 289         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 290 
 291         /* Encode with wire length > strlen */
 292         rc = smb_msgbuf_encode(&mb, "10U", "one");
 293         if (rc != 10) {
 294                 printf("Fail: msg_put_upad encode\n");
 295                 goto out;
 296         }
 297 
 298         if (memcmp(temp, wire, 10)) {
 299                 printf("Fail: msg_put_upad cmp:\n");
 300                 hexdump((uchar_t *)temp, 10);
 301                 return;
 302         }
 303 
 304         printf("Pass: msg_put_upad\n");
 305 
 306 out:
 307         smb_msgbuf_term(&mb);
 308 }
 309 
 310 static void
 311 msg_put_utrunc()
 312 {
 313         uint16_t wire[] = { 'o', 'n', 'e', 't' };
 314         uint8_t temp[32];
 315         smb_msgbuf_t mb;
 316         int mbflags = 0;
 317         int rc;
 318 
 319         smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags);
 320 
 321         /* Encode with wire length < strlen */
 322         rc = smb_msgbuf_encode(&mb, "8U", "onetwo");
 323         /* Trunc should put exactly 8 */
 324         if (rc != 8) {
 325                 printf("Fail: msg_put_utrunc encode\n");
 326                 goto out;
 327         }
 328 
 329         if (memcmp(temp, wire, 8)) {
 330                 printf("Fail: msg_put_utrunc cmp:\n");
 331                 hexdump((uchar_t *)temp, 8);
 332                 return;
 333         }
 334 
 335         printf("Pass: msg_put_utrunc\n");
 336 
 337 out:
 338         smb_msgbuf_term(&mb);
 339 }
 340 
 341 /*
 342  * Parse an ascii string.
 343  */
 344 static void
 345 msg_get_a0()
 346 {
 347         uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
 348         smb_msgbuf_t mb;
 349         int mbflags = 0;
 350         char *s;
 351         int rc;
 352         uint16_t w;
 353 
 354         smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags);
 355 
 356         rc = smb_msgbuf_decode(&mb, "sw", &s, &w);
 357         if (rc != 6) {
 358                 printf("Fail: msg_get_a0 decode\n");
 359                 goto out;
 360         }
 361         /*
 362          * Decode a word after the string to make sure we
 363          * end up positioned correctly after the string.
 364          */
 365         if (w != 42) {
 366                 printf("Fail: msg_get_a0 w=%d\n", w);
 367                 return;
 368         }
 369         if (strcmp(s, "one") != 0) {
 370                 printf("Fail: msg_get_a0 cmp: <%s>\n", s);
 371                 return;
 372         }
 373 
 374         printf("Pass: msg_get_a0\n");
 375 
 376 out:
 377         smb_msgbuf_term(&mb);
 378 }
 379 
 380 /*
 381  * Parse an ascii string, no NULL
 382  */
 383 static void
 384 msg_get_a1()
 385 {
 386         uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
 387         smb_msgbuf_t mb;
 388         int mbflags = 0;
 389         char *s;
 390         int rc;
 391         uint16_t w;
 392 
 393         smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags);
 394 
 395         rc = smb_msgbuf_decode(&mb, "3s.w", &s, &w);
 396         if (rc != 6) {
 397                 printf("Fail: msg_get_a1 decode\n");
 398                 goto out;
 399         }
 400         /*
 401          * Decode a word after the string to make sure we
 402          * end up positioned correctly after the string.
 403          */
 404         if (w != 42) {
 405                 printf("Fail: msg_get_a1 w=%d\n", w);
 406                 return;
 407         }
 408         if (strcmp(s, "one") != 0) {
 409                 printf("Fail: msg_get_a1 cmp: <%s>\n", s);
 410                 return;
 411         }
 412 
 413         printf("Pass: msg_get_a1\n");
 414 
 415 out:
 416         smb_msgbuf_term(&mb);
 417 }
 418 
 419 /* parse exactly to end of data */
 420 static void
 421 msg_get_a2()
 422 {
 423         uint8_t wire[] = { 'o', 'n', 'e' };
 424         smb_msgbuf_t mb;
 425         int mbflags = 0;
 426         char *s;
 427         int rc;
 428 
 429         smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags);
 430 
 431         rc = smb_msgbuf_decode(&mb, "3s", &s);
 432         if (rc != 3) {
 433                 printf("Fail: msg_get_a2 decode\n");
 434                 goto out;
 435         }
 436         if (mb.scan != mb.end) {
 437                 printf("Fail: msg_get_a2 wrong pos\n");
 438                 return;
 439         }
 440         if (strcmp(s, "one") != 0) {
 441                 printf("Fail: msg_get_a2 cmp: <%s>\n", s);
 442                 return;
 443         }
 444 
 445         printf("Pass: msg_get_a2\n");
 446 
 447 out:
 448         smb_msgbuf_term(&mb);
 449 }
 450 
 451 /*
 452  * Parse a unicode string.
 453  */
 454 static void
 455 msg_get_u0()
 456 {
 457         uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 };
 458         smb_msgbuf_t mb;
 459         int mbflags = 0;
 460         char *s;
 461         int rc;
 462         uint16_t w;
 463 
 464         smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags);
 465 
 466         rc = smb_msgbuf_decode(&mb, "Uw", &s, &w);
 467         if (rc != 10) {
 468                 printf("Fail: msg_get_u0 decode\n");
 469                 goto out;
 470         }
 471         /*
 472          * Decode a word after the string to make sure we
 473          * end up positioned correctly after the string.
 474          */
 475         if (w != 42) {
 476                 printf("Fail: msg_get_u0 w=%d\n", w);
 477                 return;
 478         }
 479         if (strcmp(s, "one") != 0) {
 480                 printf("Fail: msg_get_u0 cmp: <%s>\n", s);
 481                 return;
 482         }
 483 
 484         printf("Pass: msg_get_u0\n");
 485 
 486 out:
 487         smb_msgbuf_term(&mb);
 488 }
 489 
 490 /*
 491  * Parse a string that's NOT null terminated.
 492  */
 493 static void
 494 msg_get_u1()
 495 {
 496         uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 };
 497         smb_msgbuf_t mb;
 498         int mbflags = 0;
 499         char *s;
 500         int rc;
 501         uint16_t w;
 502 
 503         smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags);
 504 
 505         rc = smb_msgbuf_decode(&mb, "6U..w", &s, &w);
 506         if (rc != 10) {
 507                 printf("Fail: msg_get_u1 decode\n");
 508                 goto out;
 509         }
 510         /*
 511          * Decode a word after the string to make sure we
 512          * end up positioned correctly after the string.
 513          */
 514         if (w != 42) {
 515                 printf("Fail: msg_get_u1 w=%d\n", w);
 516                 return;
 517         }
 518         if (strcmp(s, "one") != 0) {
 519                 printf("Fail: msg_get_u1 cmp: <%s>\n", s);
 520                 return;
 521         }
 522 
 523         printf("Pass: msg_get_u1\n");
 524 
 525 out:
 526         smb_msgbuf_term(&mb);
 527 }
 528 
 529 /* parse exactly to end of data */
 530 static void
 531 msg_get_u2()
 532 {
 533         uint16_t wire[] = { 'o', 'n', 'e' };
 534         smb_msgbuf_t mb;
 535         int mbflags = 0;
 536         char *s;
 537         int rc;
 538 
 539         smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags);
 540 
 541         rc = smb_msgbuf_decode(&mb, "6U", &s);
 542         if (rc != 6) {
 543                 printf("Fail: msg_get_u2 decode\n");
 544                 goto out;
 545         }
 546         if (mb.scan != mb.end) {
 547                 printf("Fail: msg_get_u2 wrong pos\n");
 548                 return;
 549         }
 550         if (strcmp(s, "one") != 0) {
 551                 printf("Fail: msg_get_u2 cmp: <%s>\n", s);
 552                 return;
 553         }
 554 
 555         printf("Pass: msg_get_u2\n");
 556 
 557 out:
 558         smb_msgbuf_term(&mb);
 559 }
 560 
 561 static void
 562 msg_get_u3()
 563 {
 564         smb_msgbuf_t mb;
 565         int mbflags = 0;
 566         char *s;
 567         int rc;
 568 
 569         smb_msgbuf_init(&mb, (uint8_t *)wcsa, sizeof (wcsa), mbflags);
 570 
 571         rc = smb_msgbuf_decode(&mb, "#U", sizeof (wcsa), &s);
 572         if (rc != 8) {
 573                 printf("Fail: msg_get_u3 decode\n");
 574                 goto out;
 575         }
 576         if (strcmp(s, mbsa) != 0) {
 577                 printf("Fail: msg_get_u3 cmp: <%s>\n", s);
 578                 return;
 579         }
 580 
 581         printf("Pass: msg_get_u3\n");
 582 
 583 out:
 584         smb_msgbuf_term(&mb);
 585 }
 586 
 587 static void
 588 msg_get_u4()
 589 {
 590         smb_msgbuf_t mb;
 591         int mbflags = 0;
 592         char *s;
 593         int rc;
 594 
 595         smb_msgbuf_init(&mb, (uint8_t *)wcsp, sizeof (wcsp), mbflags);
 596 
 597         rc = smb_msgbuf_decode(&mb, "#U", sizeof (wcsp), &s);
 598         if (rc != 10) {
 599                 printf("Fail: msg_get_u4 decode\n");
 600                 goto out;
 601         }
 602         if (strcmp(s, mbsp) != 0) {
 603                 printf("Fail: msg_get_u4 cmp: <%s>\n", s);
 604                 return;
 605         }
 606 
 607         printf("Pass: msg_get_u4\n");
 608 
 609 out:
 610         smb_msgbuf_term(&mb);
 611 }
 612 
 613 void
 614 test_msgbuf()
 615 {
 616 
 617         msg_put_a0();
 618         msg_put_a1();
 619         msg_put_apad();
 620         msg_put_atrunc();
 621 
 622         msg_put_u0();
 623         msg_put_u1();
 624         msg_put_u3();
 625         msg_put_u4();
 626         msg_put_upad();
 627         msg_put_utrunc();
 628 
 629         msg_get_a0();
 630         msg_get_a1();
 631         msg_get_a2();
 632         msg_get_u0();
 633         msg_get_u1();
 634         msg_get_u2();
 635         msg_get_u3();
 636         msg_get_u4();
 637 
 638 }