librpc:ndr: Introduce ‘libndr_flags’ type
[vlendec/samba-autobuild/.git] / source4 / torture / ndr / ndr.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for winreg ndr operations
4
5    Copyright (C) Jelmer Vernooij 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "torture/ndr/ndr.h"
23 #include "torture/ndr/proto.h"
24 #include "../lib/util/dlinklist.h"
25 #include "param/param.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27
28 struct ndr_pull_test_data {
29         DATA_BLOB data;
30         DATA_BLOB data_context;
31         size_t struct_size;
32         ndr_pull_flags_fn_t pull_fn;
33         ndr_push_flags_fn_t push_fn;
34         ndr_print_fn_t print_fn;
35         ndr_print_function_t print_function;
36         int ndr_flags;
37         libndr_flags flags;
38         enum ndr_err_code ndr_err;
39 };
40
41 static enum ndr_err_code torture_ndr_push_struct_blob_flags(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, uint32_t flags, libndr_flags ndr_flags, const void *p, ndr_push_flags_fn_t fn)
42 {
43         struct ndr_push *ndr;
44         ndr = ndr_push_init_ctx(mem_ctx);
45         NDR_ERR_HAVE_NO_MEMORY(ndr);
46
47         ndr->flags |= ndr_flags;
48
49         NDR_CHECK(fn(ndr, flags, p));
50
51         *blob = ndr_push_blob(ndr);
52         talloc_steal(mem_ctx, blob->data);
53         talloc_free(ndr);
54
55         return NDR_ERR_SUCCESS;
56 }
57
58 static bool torture_ndrdump(struct torture_context *tctx,
59                             struct ndr_pull *ndr,
60                             const struct ndr_pull_test_data *data,
61                             uint32_t flags,
62                             void *ds,
63                             const char *name)
64 {
65         struct ndr_print *ndr_print;
66         const char *name_raw;
67         uint32_t ndr_flags = data->ndr_flags | flags;
68
69         ndr_print = talloc_zero(tctx, struct ndr_print);
70         torture_assert(tctx, ndr_print, "out of memory");
71
72         if (DEBUGLEVEL >= 10) {
73                 ndr_print->print = ndr_print_debug_helper;
74         } else {
75                 ndr_print->print = ndr_print_string_helper;
76         }
77
78         ndr_print->depth = 1;
79
80         torture_assert(tctx, ndr_flags, "no flags have been set");
81
82         if (ndr_flags & (NDR_BUFFERS|NDR_SCALARS)) {
83                 data->print_fn(ndr_print, name, ds);
84         } else {
85                 data->print_function(ndr_print, name, ndr_flags, ds);
86         }
87
88         name_raw = talloc_asprintf(tctx, "%s (RAW DATA)", name);
89         torture_assert(tctx, name_raw, "out of memory");
90
91         ndr_print_DATA_BLOB(ndr_print, name_raw, data->data);
92
93         talloc_free(ndr_print);
94
95         return true;
96 }
97
98 static bool wrap_ndr_pullpush_test(struct torture_context *tctx,
99                                    struct torture_tcase *tcase,
100                                    struct torture_test *test)
101 {
102         bool (*check_fn) (struct torture_context *ctx, void *data) = test->fn;
103         const struct ndr_pull_test_data *data = (const struct ndr_pull_test_data *)test->data;
104         struct ndr_pull *ndr = ndr_pull_init_blob(&(data->data), tctx);
105         void *ds = talloc_zero_size(ndr, data->struct_size);
106         bool ret = true;
107         uint32_t highest_ofs;
108
109         torture_assert(tctx, data, "out of memory");
110         torture_assert(tctx, ndr, "out of memory");
111         torture_assert(tctx, ds, "out of memory");
112
113         ndr->flags |= data->flags;
114
115         ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
116
117         torture_assert_ndr_success(tctx, data->pull_fn(ndr, data->ndr_flags, ds),
118                                    "pulling");
119
120         if (ndr->offset > ndr->relative_highest_offset) {
121                 highest_ofs = ndr->offset;
122         } else {
123                 highest_ofs = ndr->relative_highest_offset;
124         }
125
126         torture_assert(tctx, highest_ofs == ndr->data_size,
127                                    talloc_asprintf(tctx,
128                                            "%d unread bytes", ndr->data_size - highest_ofs));
129
130         if (check_fn != NULL) {
131                 ret = check_fn(tctx, ds);
132         } else {
133                 ret = true;
134         }
135
136         torture_ndrdump(tctx, ndr, data, data->ndr_flags, ds, "ds");
137
138         if (data->push_fn != NULL) {
139                 DATA_BLOB outblob;
140                 torture_assert_ndr_success(tctx, torture_ndr_push_struct_blob_flags(&outblob, ndr, data->ndr_flags, ndr->flags, ds, data->push_fn), "pushing");
141                 torture_assert_data_blob_equal(tctx, outblob, data->data, "ndr push compare");
142         }
143
144         talloc_free(ndr);
145         return ret;
146 }
147
148 _PUBLIC_ struct torture_test *_torture_suite_add_ndr_pullpush_test(
149         struct torture_suite *suite,
150         const char *name,
151         ndr_pull_flags_fn_t pull_fn,
152         ndr_push_flags_fn_t push_fn,
153         ndr_print_fn_t print_fn,
154         ndr_print_function_t print_function,
155         const char *db_name,
156         DATA_BLOB db,
157         size_t struct_size,
158         int ndr_flags,
159         libndr_flags flags,
160         const char *check_fn_name,
161         bool (*check_fn) (struct torture_context *ctx, void *data))
162 {
163         struct torture_test *test;
164         struct torture_tcase *tcase;
165         struct ndr_pull_test_data *data;
166
167         tcase = torture_suite_add_tcase(suite, name);
168
169         test = talloc(tcase, struct torture_test);
170
171         test->name = talloc_strdup(test, check_fn_name);
172         test->description = talloc_asprintf(test, "db:%s",
173                                             db_name);
174         test->run = wrap_ndr_pullpush_test;
175
176         data = talloc_zero(test, struct ndr_pull_test_data);
177         data->data = db;
178         data->ndr_flags = ndr_flags;
179         data->flags = flags;
180         data->struct_size = struct_size;
181         data->pull_fn = pull_fn;
182         data->push_fn = push_fn;
183         data->print_fn = print_fn;
184         data->print_function = print_function;
185
186         test->data = data;
187         test->fn = check_fn;
188         test->dangerous = false;
189
190         DLIST_ADD_END(tcase->tests, test);
191
192         return test;
193 }
194
195
196 static bool wrap_ndr_inout_pull_test(struct torture_context *tctx,
197                                      struct torture_tcase *tcase,
198                                      struct torture_test *test)
199 {
200         bool (*check_fn) (struct torture_context *ctx, void *data) = test->fn;
201         const struct ndr_pull_test_data *data = (const struct ndr_pull_test_data *)test->data;
202         void *ds = talloc_zero_size(tctx, data->struct_size);
203         struct ndr_pull *ndr;
204         uint32_t highest_ofs;
205         bool ret = false;
206
207         torture_assert(tctx, data, "out of memory");
208         torture_assert(tctx, ds, "out of memory");
209
210         /* handle NDR_IN context */
211
212         ndr = ndr_pull_init_blob(&(data->data_context), tctx);
213         torture_assert(tctx, ndr, "ndr init failed");
214
215         ndr->flags |= data->flags;
216         ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
217
218         torture_assert_ndr_success(tctx,
219                 data->pull_fn(ndr, NDR_IN, ds),
220                 "ndr pull of context failed");
221
222         if (ndr->offset > ndr->relative_highest_offset) {
223                 highest_ofs = ndr->offset;
224         } else {
225                 highest_ofs = ndr->relative_highest_offset;
226         }
227
228         torture_assert(tctx, highest_ofs == ndr->data_size,
229                 talloc_asprintf(tctx, "%d unread bytes", ndr->data_size - highest_ofs));
230
231         torture_ndrdump(tctx, ndr, data, NDR_IN, ds, "ds");
232
233         talloc_free(ndr);
234
235         /* handle NDR_OUT */
236
237         ndr = ndr_pull_init_blob(&(data->data), tctx);
238         torture_assert(tctx, ndr, "ndr init failed");
239
240         ndr->flags |= data->flags;
241         ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
242
243         torture_assert_ndr_success(tctx,
244                 data->pull_fn(ndr, NDR_OUT, ds),
245                 "ndr pull failed");
246
247         if (ndr->offset > ndr->relative_highest_offset) {
248                 highest_ofs = ndr->offset;
249         } else {
250                 highest_ofs = ndr->relative_highest_offset;
251         }
252
253         torture_assert(tctx, highest_ofs == ndr->data_size,
254                 talloc_asprintf(tctx, "%d unread bytes", ndr->data_size - highest_ofs));
255
256         if (check_fn) {
257                 ret = check_fn(tctx, ds);
258         } else {
259                 ret = true;
260         }
261
262         torture_ndrdump(tctx, ndr, data, NDR_OUT, ds, "ds");
263
264         talloc_free(ndr);
265
266         return ret;
267 }
268
269 _PUBLIC_ struct torture_test *_torture_suite_add_ndr_pull_inout_test(
270                                         struct torture_suite *suite,
271                                         const char *name,
272                                         ndr_pull_flags_fn_t pull_fn,
273                                         ndr_print_function_t print_function,
274                                         const char *db_in_name,
275                                         DATA_BLOB db_in,
276                                         const char *db_out_name,
277                                         DATA_BLOB db_out,
278                                         size_t struct_size,
279                                         libndr_flags flags,
280                                         const char *check_fn_name,
281                                         bool (*check_fn) (struct torture_context *ctx, void *data))
282 {
283         struct torture_test *test;
284         struct torture_tcase *tcase;
285         struct ndr_pull_test_data *data;
286
287         tcase = torture_suite_add_tcase(suite, name);
288
289         test = talloc(tcase, struct torture_test);
290
291         test->name = talloc_strdup(test, check_fn_name);
292         test->description = talloc_asprintf(test, "db_in:%s db_out:%s",
293                                             db_in_name,
294                                             db_out_name);
295         test->run = wrap_ndr_inout_pull_test;
296         data = talloc_zero(test, struct ndr_pull_test_data);
297         data->data = db_out;
298         data->data_context = db_in;
299         data->ndr_flags = 0;
300         data->flags = flags;
301         data->struct_size = struct_size;
302         data->pull_fn = pull_fn;
303         data->print_function = print_function;
304         test->data = data;
305         test->fn = check_fn;
306         test->dangerous = false;
307
308         DLIST_ADD_END(tcase->tests, test);
309
310         return test;
311 }
312
313 static bool wrap_ndr_pull_invalid_data_test(struct torture_context *tctx,
314                                             struct torture_tcase *tcase,
315                                             struct torture_test *test)
316 {
317         const struct ndr_pull_test_data *data = (const struct ndr_pull_test_data *)test->data;
318         struct ndr_pull *ndr = ndr_pull_init_blob(&(data->data), tctx);
319         void *ds = talloc_zero_size(ndr, data->struct_size);
320         bool ret = true;
321
322         torture_assert(tctx, data, "out of memory");
323         torture_assert(tctx, ndr, "out of memory");
324         torture_assert(tctx, ds, "out of memory");
325
326         ndr->flags |= data->flags;
327
328         ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
329
330         torture_assert_ndr_err_equal(
331                 tctx,
332                 data->pull_fn(ndr, data->ndr_flags, ds),
333                 NDR_ERR_BUFSIZE,
334                 "pulling invalid data");
335
336         talloc_free(ndr);
337         return ret;
338 }
339
340 _PUBLIC_ struct torture_test *_torture_suite_add_ndr_pull_invalid_data_test(
341         struct torture_suite *suite,
342         const char *name,
343         ndr_pull_flags_fn_t pull_fn,
344         const char *db_name,
345         DATA_BLOB db,
346         size_t struct_size,
347         int ndr_flags,
348         libndr_flags flags,
349         enum ndr_err_code ndr_err)
350 {
351         struct torture_test *test;
352         struct torture_tcase *tcase;
353         struct ndr_pull_test_data *data;
354
355         tcase = torture_suite_add_tcase(suite, name);
356
357         test = talloc(tcase, struct torture_test);
358
359         test->name = talloc_strdup(test, db_name);
360         test->description = NULL;
361         test->run = wrap_ndr_pull_invalid_data_test;
362
363         data = talloc_zero(test, struct ndr_pull_test_data);
364         data->data = db;
365         data->ndr_flags = ndr_flags;
366         data->flags = flags;
367         data->struct_size = struct_size;
368         data->pull_fn = pull_fn;
369         data->ndr_err = ndr_err;
370
371         test->data = data;
372         test->fn = NULL;
373         test->dangerous = false;
374
375         DLIST_ADD_END(tcase->tests, test);
376
377         return test;
378 }
379
380 static bool test_check_string_terminator(struct torture_context *tctx)
381 {
382         struct ndr_pull *ndr;
383         DATA_BLOB blob;
384         TALLOC_CTX *mem_ctx = tctx;
385
386         /* Simple test */
387         blob = strhex_to_data_blob(tctx, "0000");
388
389         ndr = ndr_pull_init_blob(&blob, mem_ctx);
390
391         torture_assert_ndr_success(tctx, ndr_check_string_terminator(ndr, 1, 2),
392                                    "simple check_string_terminator test failed");
393
394         torture_assert(tctx, ndr->offset == 0,
395                 "check_string_terminator did not reset offset");
396
397         if (NDR_ERR_CODE_IS_SUCCESS(ndr_check_string_terminator(ndr, 1, 3))) {
398                 torture_fail(tctx, "check_string_terminator checked beyond string boundaries");
399         }
400
401         torture_assert(tctx, ndr->offset == 0,
402                 "check_string_terminator did not reset offset");
403
404         talloc_free(ndr);
405
406         blob = strhex_to_data_blob(tctx, "11220000");
407         ndr = ndr_pull_init_blob(&blob, mem_ctx);
408
409         torture_assert_ndr_success(tctx,
410                 ndr_check_string_terminator(ndr, 4, 1),
411                 "check_string_terminator failed to recognize terminator");
412
413         torture_assert_ndr_success(tctx,
414                 ndr_check_string_terminator(ndr, 3, 1),
415                 "check_string_terminator failed to recognize terminator");
416
417         if (NDR_ERR_CODE_IS_SUCCESS(ndr_check_string_terminator(ndr, 2, 1))) {
418                 torture_fail(tctx, "check_string_terminator erroneously reported terminator");
419         }
420
421         torture_assert(tctx, ndr->offset == 0,
422                 "check_string_terminator did not reset offset");
423         return true;
424 }
425
426 static bool test_guid_from_string_valid(struct torture_context *tctx)
427 {
428         /* FIXME */
429         return true;
430 }
431
432 static bool test_guid_from_string_null(struct torture_context *tctx)
433 {
434         struct GUID guid;
435         torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER,
436                                       GUID_from_string(NULL, &guid),
437                                       "NULL failed");
438         return true;
439 }
440
441 static bool test_guid_from_string_invalid(struct torture_context *tctx)
442 {
443         struct GUID g1;
444         bool failed = false;
445         int i;
446         const char *bad_guids[] = {
447                 "bla",
448                 "",
449                 /*
450                 "00000001-0002-0003-0405-060708090a0b",  correct
451                 */
452                 "00000001-0002-0003-0405-060708090a0b1", /* too long */
453                 "00000001-0002-0003-0405-060708090a0",  /* too short */
454                 "00000001-0002-0003-0405--060708090a0",  /* negative */
455                 "00000001-0002-0003--0405-060708090a0",  /* negative */
456                 "-0000001-0002-0003-0405-060708090a0b",  /* negative */
457                 "-0000001-0002-0003-04-5-060708090a0b",  /* negative */
458                 "d0000001-0002-0003-0405-060708090a-b",  /* negative */
459                 "00000001-  -2-0003-0405-060708090a0b",  /* negative, space */
460                 "00000001-0002-0003-0405- 060708090a0",  /* whitespace */
461                 " 0000001-0002-0003--0405-060708090a0",  /* whitespace */
462                 "00000001-0002-0003--0405-060708090a ",  /* whitespace */
463                 "0000001-00002-0003-04050-60708090a0b",  /* misshapen */
464                 "00000010-0002-0003-04050-60708090a0b",  /* misshapen */
465                 "00000001-0002-0003-0405-0z0708090a0b",  /* bad char */
466                 "00000001-00x2-0x03-0405-060708090a0b",  /* bad char (00x) */
467                 "0x000001-0002-0003-0405-060708090a0b",  /* 0x char */
468                 "00000001-0x02-0x03-0405-060708090a0b",  /* 0x char */
469         };
470
471         for (i = 0; i < ARRAY_SIZE(bad_guids); i++) {
472                 NTSTATUS status = GUID_from_string(bad_guids[i], &g1);
473                 if (! NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
474                         torture_comment(tctx, "bad guid %s parsed as OK\n",
475                                         bad_guids[i]);
476                         failed = true;
477                 }
478         }
479         if (failed) {
480                 torture_fail(tctx, "wrongly allowing invalid guids");
481         }
482         return true;
483 }
484
485 static bool test_guid_from_string(struct torture_context *tctx)
486 {
487         struct GUID g1, exp;
488         /* we are asserting all these guids are valid and equal */
489         const char *guids[5] = {
490                 "00000001-0002-0003-0405-060708090a0b",
491                 "{00000001-0002-0003-0405-060708090a0b}",
492                 "{00000001-0002-0003-0405-060708090a0B}", /* mixed */
493                 "00000001-0002-0003-0405-060708090A0B",   /* upper */
494                 "01000000020003000405060708090a0b",       /* hex string */
495         };
496         int i;
497
498         torture_assert_ntstatus_ok(tctx,
499                                    GUID_from_string(guids[0], &g1),
500                                    "invalid return code");
501         exp.time_low = 1;
502         exp.time_mid = 2;
503         exp.time_hi_and_version = 3;
504         exp.clock_seq[0] = 4;
505         exp.clock_seq[1] = 5;
506         exp.node[0] = 6;
507         exp.node[1] = 7;
508         exp.node[2] = 8;
509         exp.node[3] = 9;
510         exp.node[4] = 10;
511         exp.node[5] = 11;
512
513         for (i = 1; i < ARRAY_SIZE(guids); i++) {
514                 torture_assert_ntstatus_ok(tctx,
515                                            GUID_from_string(guids[i], &g1),
516                                            "invalid return code");
517                 torture_assert(tctx, GUID_equal(&g1, &exp),
518                                "UUID parsed incorrectly");
519         }
520         return true;
521 }
522
523 static bool test_guid_from_data_blob(struct torture_context *tctx)
524 {
525         struct GUID g1, exp;
526         const uint8_t bin[16] = {
527                 0x01, 0x00, 0x00, 0x00,
528                 0x02, 0x00,
529                 0x03, 0x00,
530                 0x04, 0x05,
531                 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b };
532         const char *hexstr = "01000000020003000405060708090a0b";
533         const DATA_BLOB blobs[2] = {
534                 data_blob_const(bin, sizeof(bin)),
535                 data_blob_string_const(hexstr),
536         };
537         int i;
538
539         exp.time_low = 1;
540         exp.time_mid = 2;
541         exp.time_hi_and_version = 3;
542         exp.clock_seq[0] = 4;
543         exp.clock_seq[1] = 5;
544         exp.node[0] = 6;
545         exp.node[1] = 7;
546         exp.node[2] = 8;
547         exp.node[3] = 9;
548         exp.node[4] = 10;
549         exp.node[5] = 11;
550
551         for (i = 1; i < ARRAY_SIZE(blobs); i++) {
552                 torture_assert_ntstatus_ok(tctx,
553                                            GUID_from_data_blob(&blobs[i], &g1),
554                                            "invalid return code");
555                 torture_assert(tctx, GUID_equal(&g1, &exp),
556                                "UUID parsed incorrectly");
557         }
558
559         return true;
560 }
561
562 static bool test_guid_string_valid(struct torture_context *tctx)
563 {
564         struct GUID g;
565         g.time_low = 1;
566         g.time_mid = 2;
567         g.time_hi_and_version = 3;
568         g.clock_seq[0] = 4;
569         g.clock_seq[1] = 5;
570         g.node[0] = 6;
571         g.node[1] = 7;
572         g.node[2] = 8;
573         g.node[3] = 9;
574         g.node[4] = 10;
575         g.node[5] = 11;
576         torture_assert_str_equal(tctx, "00000001-0002-0003-0405-060708090a0b",
577                                  GUID_string(tctx, &g),
578                                  "parsing guid failed");
579         return true;
580 }
581
582 static bool test_guid_string2_valid(struct torture_context *tctx)
583 {
584         struct GUID g;
585         g.time_low = 1;
586         g.time_mid = 2;
587         g.time_hi_and_version = 3;
588         g.clock_seq[0] = 4;
589         g.clock_seq[1] = 5;
590         g.node[0] = 6;
591         g.node[1] = 7;
592         g.node[2] = 8;
593         g.node[3] = 9;
594         g.node[4] = 10;
595         g.node[5] = 11;
596         torture_assert_str_equal(tctx, "{00000001-0002-0003-0405-060708090a0b}",
597                                  GUID_string2(tctx, &g),
598                                  "parsing guid failed");
599         return true;
600 }
601
602 static bool test_guid_into_blob(struct torture_context *tctx)
603 {
604         enum ndr_err_code ndr_err;
605         static const char exp_guid[16] =
606                 { 0x1, 0x0, 0x0, 0x0,
607                   0x2, 0x0, 0x3, 0x0,
608                   0x4, 0x5, 0x6, 0x7,
609                   0x8, 0x9, 0xa, 0xb };
610         DATA_BLOB exp = data_blob_const(exp_guid, 16);
611         char ndr_guid[16] =
612                 { 0x0, 0x0, 0x0, 0x0,
613                   0x0, 0x0, 0x0, 0x0,
614                   0x0, 0x0, 0x0, 0x0,
615                   0x0, 0x0, 0x0, 0x0 };
616         DATA_BLOB b = data_blob_const(ndr_guid, 16);
617         struct GUID guid;
618         guid.time_low = 1;
619         guid.time_mid = 2;
620         guid.time_hi_and_version = 3;
621         guid.clock_seq[0] = 4;
622         guid.clock_seq[1] = 5;
623         guid.node[0] = 6;
624         guid.node[1] = 7;
625         guid.node[2] = 8;
626         guid.node[3] = 9;
627         guid.node[4] = 10;
628         guid.node[5] = 11;
629         
630         ndr_err = ndr_push_struct_into_fixed_blob(&b, &guid,
631                                                   (ndr_push_flags_fn_t)ndr_push_GUID);
632         torture_assert_ndr_err_equal(tctx, ndr_err, NDR_ERR_SUCCESS,
633                                      "wrong NDR error");
634         torture_assert_data_blob_equal(tctx, b, exp,
635                                        "GUID packed wrongly");
636
637         return true;
638 }
639
640 /* Really a test of ndr_push_struct_into_fixed_blob error handling */
641 static bool test_guid_into_long_blob(struct torture_context *tctx)
642 {
643         enum ndr_err_code ndr_err;
644         char ndr_guid[17] =
645                 { 0x0, 0x0, 0x0, 0x0,
646                   0x0, 0x0, 0x0, 0x0,
647                   0x0, 0x0, 0x0, 0x0,
648                   0x0, 0x0, 0x0, 0x0, 0x0 };
649         DATA_BLOB b = data_blob_const(ndr_guid, 17);
650         struct GUID guid;
651         guid.time_low = 1;
652         guid.time_mid = 2;
653         guid.time_hi_and_version = 3;
654         guid.clock_seq[0] = 4;
655         guid.clock_seq[1] = 5;
656         guid.node[0] = 6;
657         guid.node[1] = 7;
658         guid.node[2] = 8;
659         guid.node[3] = 9;
660         guid.node[4] = 10;
661         guid.node[5] = 11;
662
663         torture_assert(tctx, b.data != NULL, "data_blob_talloc failed");
664         ndr_err = ndr_push_struct_into_fixed_blob(
665                 &b, &guid, (ndr_push_flags_fn_t)ndr_push_GUID);
666         torture_assert_ndr_err_equal(tctx, ndr_err, NDR_ERR_BUFSIZE,
667                                      "wrong NDR error");
668
669         return true;
670 }
671
672 static bool test_guid_into_short_blob(struct torture_context *tctx)
673 {
674         enum ndr_err_code ndr_err;
675         char ndr_guid[15] =
676                 { 0x0, 0x0, 0x0, 0x0,
677                   0x0, 0x0, 0x0, 0x0,
678                   0x0, 0x0, 0x0, 0x0,
679                   0x0, 0x0, 0x0 };
680         DATA_BLOB b = data_blob_const(ndr_guid, 15);
681         struct GUID guid;
682         guid.time_low = 1;
683         guid.time_mid = 2;
684         guid.time_hi_and_version = 3;
685         guid.clock_seq[0] = 4;
686         guid.clock_seq[1] = 5;
687         guid.node[0] = 6;
688         guid.node[1] = 7;
689         guid.node[2] = 8;
690         guid.node[3] = 9;
691         guid.node[4] = 10;
692         guid.node[5] = 11;
693
694         ndr_err = ndr_push_struct_into_fixed_blob(
695                 &b, &guid, (ndr_push_flags_fn_t)ndr_push_GUID);
696         torture_assert_ndr_err_equal(tctx, ndr_err, NDR_ERR_BUFSIZE,
697                                      "wrong NDR error");
698
699         return true;
700 }
701
702 static bool test_compare_uuid(struct torture_context *tctx)
703 {
704         struct GUID g1, g2;
705         ZERO_STRUCT(g1); ZERO_STRUCT(g2);
706         torture_assert_int_equal(tctx, 0, GUID_compare(&g1, &g2),
707                                  "GUIDs not equal");
708         g1.time_low = 1;
709         torture_assert_int_equal(tctx, 1, GUID_compare(&g1, &g2),
710                                  "GUID diff invalid");
711
712         g1.time_low = 10;
713         torture_assert_int_equal(tctx, 1, GUID_compare(&g1, &g2),
714                                  "GUID diff invalid");
715
716         g1.time_low = 0;
717         g1.clock_seq[1] = 20;
718         torture_assert_int_equal(tctx, 1, GUID_compare(&g1, &g2),
719                                  "GUID diff invalid");
720
721         g1.time_low = ~0;
722         torture_assert_int_equal(tctx, 1, GUID_compare(&g1, &g2),
723                                  "GUID diff invalid");
724
725         g1.time_low = 0;
726         g2.time_low = ~0;
727         torture_assert_int_equal(tctx, -1, GUID_compare(&g1, &g2),
728                                  "GUID diff invalid");
729         return true;
730 }
731
732 static bool test_syntax_id_from_string(struct torture_context *tctx)
733 {
734         struct ndr_syntax_id s, exp;
735         const char *id = "00000001-0002-0003-0405-060708090a0b/0x12345678";
736
737         exp.uuid.time_low = 1;
738         exp.uuid.time_mid = 2;
739         exp.uuid.time_hi_and_version = 3;
740         exp.uuid.clock_seq[0] = 4;
741         exp.uuid.clock_seq[1] = 5;
742         exp.uuid.node[0] = 6;
743         exp.uuid.node[1] = 7;
744         exp.uuid.node[2] = 8;
745         exp.uuid.node[3] = 9;
746         exp.uuid.node[4] = 10;
747         exp.uuid.node[5] = 11;
748         exp.if_version = 0x12345678;
749
750         torture_assert(tctx,
751                        ndr_syntax_id_from_string(id, &s),
752                        "invalid return code");
753         torture_assert(tctx, ndr_syntax_id_equal(&s, &exp),
754                        "NDR syntax id parsed incorrectly");
755         return true;
756 }
757
758 struct torture_suite *torture_local_ndr(TALLOC_CTX *mem_ctx)
759 {
760         struct torture_suite *suite = torture_suite_create(mem_ctx, "ndr");
761
762         torture_suite_add_suite(suite, ndr_dcerpc_suite(suite));
763         torture_suite_add_suite(suite, ndr_winreg_suite(suite));
764         torture_suite_add_suite(suite, ndr_atsvc_suite(suite));
765         torture_suite_add_suite(suite, ndr_lsa_suite(suite));
766         torture_suite_add_suite(suite, ndr_epmap_suite(suite));
767         torture_suite_add_suite(suite, ndr_dfs_suite(suite));
768         torture_suite_add_suite(suite, ndr_dfsblob_suite(suite));
769         torture_suite_add_suite(suite, ndr_netlogon_suite(suite));
770         torture_suite_add_suite(suite, ndr_drsuapi_suite(suite));
771         torture_suite_add_suite(suite, ndr_spoolss_suite(suite));
772         torture_suite_add_suite(suite, ndr_winspool_suite(suite));
773         torture_suite_add_suite(suite, ndr_ntprinting_suite(suite));
774         torture_suite_add_suite(suite, ndr_samr_suite(suite));
775         torture_suite_add_suite(suite, ndr_drsblobs_suite(suite));
776         torture_suite_add_suite(suite, ndr_dnsp_suite(suite));
777         torture_suite_add_suite(suite, ndr_nbt_suite(suite));
778         torture_suite_add_suite(suite, ndr_ntlmssp_suite(suite));
779         torture_suite_add_suite(suite, ndr_backupkey_suite(suite));
780         torture_suite_add_suite(suite, ndr_witness_suite(suite));
781         torture_suite_add_suite(suite, ndr_clusapi_suite(suite));
782         torture_suite_add_suite(suite, ndr_negoex_suite(suite));
783         torture_suite_add_suite(suite, ndr_string_suite(suite));
784         torture_suite_add_suite(suite, ndr_krb5pac_suite(suite));
785         torture_suite_add_suite(suite, ndr_cabinet_suite(suite));
786         torture_suite_add_suite(suite, ndr_charset_suite(suite));
787         torture_suite_add_suite(suite, ndr_svcctl_suite(suite));
788         torture_suite_add_suite(suite, ndr_ODJ_suite(suite));
789
790         torture_suite_add_simple_test(suite, "string terminator",
791                                       test_check_string_terminator);
792
793         torture_suite_add_simple_test(suite, "guid_from_string_null",
794                                       test_guid_from_string_null);
795
796         torture_suite_add_simple_test(suite, "guid_from_string",
797                                       test_guid_from_string);
798
799         torture_suite_add_simple_test(suite, "guid_from_data_blob",
800                                       test_guid_from_data_blob);
801
802         torture_suite_add_simple_test(suite, "guid_from_string_invalid",
803                                       test_guid_from_string_invalid);
804
805         torture_suite_add_simple_test(suite, "guid_string_valid",
806                                       test_guid_string_valid);
807
808         torture_suite_add_simple_test(suite, "guid_string2_valid",
809                                       test_guid_string2_valid);
810
811         torture_suite_add_simple_test(suite, "guid_from_string_valid",
812                                       test_guid_from_string_valid);
813
814         torture_suite_add_simple_test(suite, "compare_uuid",
815                                       test_compare_uuid);
816
817         torture_suite_add_simple_test(suite, "guid_into_blob",
818                                       test_guid_into_blob);
819
820         torture_suite_add_simple_test(suite, "guid_into_short_blob",
821                                       test_guid_into_short_blob);
822
823         torture_suite_add_simple_test(suite, "guid_into_long_blob",
824                                       test_guid_into_long_blob);
825
826         torture_suite_add_simple_test(suite, "syntax_id_from_string",
827                                       test_syntax_id_from_string);
828
829         return suite;
830 }
831