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