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 }