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
mbm_put_a0()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
mbm_put_a1()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
mbm_put_apad()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
mbm_put_atrunc1()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
mbm_put_atrunc2()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
mbm_put_u0()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
mbm_put_u1()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
mbm_put_u3()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
mbm_put_u4()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
mbm_put_upad()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
mbm_put_utrunc1()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
mbm_put_utrunc2()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
mbm_get_a0()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
mbm_get_a1()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
mbm_get_a2()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
mbm_get_u0()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
mbm_get_u1()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
mbm_get_u2()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
mbm_get_u3()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
mbm_get_u4()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
test_mbmarshal()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