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
30static char mbsa[] = "A\xef\xbc\xa1.";		// A fwA . (5)
31static char mbsp[] = "P\xf0\x9f\x92\xa9.";	// P poop . (6)
32static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 };	// (3)
33static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4)
34
35/*
36 * Put ASCII string with NULL
37 */
38static void
39msg_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
63out:
64	smb_msgbuf_term(&mb);
65}
66
67/*
68 * Put ASCII string, no NULL
69 */
70static void
71msg_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
95out:
96	smb_msgbuf_term(&mb);
97}
98
99static void
100msg_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
125out:
126	smb_msgbuf_term(&mb);
127}
128
129static void
130msg_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
156out:
157	smb_msgbuf_term(&mb);
158}
159
160/*
161 * Put unicode string with NULL
162 */
163static void
164msg_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
188out:
189	smb_msgbuf_term(&mb);
190}
191
192/*
193 * Put unicode string, no NULL
194 */
195static void
196msg_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
220out:
221	smb_msgbuf_term(&mb);
222}
223
224static void
225msg_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
248out:
249	smb_msgbuf_term(&mb);
250}
251
252static void
253msg_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
276out:
277	smb_msgbuf_term(&mb);
278}
279
280static void
281msg_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
306out:
307	smb_msgbuf_term(&mb);
308}
309
310static void
311msg_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
337out:
338	smb_msgbuf_term(&mb);
339}
340
341/*
342 * Parse an ascii string.
343 */
344static void
345msg_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
376out:
377	smb_msgbuf_term(&mb);
378}
379
380/*
381 * Parse an ascii string, no NULL
382 */
383static void
384msg_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
415out:
416	smb_msgbuf_term(&mb);
417}
418
419/* parse exactly to end of data */
420static void
421msg_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
447out:
448	smb_msgbuf_term(&mb);
449}
450
451/*
452 * Parse a unicode string.
453 */
454static void
455msg_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
486out:
487	smb_msgbuf_term(&mb);
488}
489
490/*
491 * Parse a string that's NOT null terminated.
492 */
493static void
494msg_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
525out:
526	smb_msgbuf_term(&mb);
527}
528
529/* parse exactly to end of data */
530static void
531msg_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
557out:
558	smb_msgbuf_term(&mb);
559}
560
561static void
562msg_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
583out:
584	smb_msgbuf_term(&mb);
585}
586
587static void
588msg_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
609out:
610	smb_msgbuf_term(&mb);
611}
612
613void
614test_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