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 }
639