r24872: Use torture API a bit more
[kai/samba.git] / source / torture / rpc / srvsvc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for srvsvc rpc operations
4
5    Copyright (C) Stefan (metze) Metzmacher 2003
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/torture.h"
23 #include "librpc/gen_ndr/ndr_srvsvc.h"
24 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
25 #include "torture/rpc/rpc.h"
26
27 /**************************/
28 /* srvsvc_NetCharDev      */
29 /**************************/
30 static bool test_NetCharDevGetInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
31                                 const char *devname)
32 {
33         NTSTATUS status;
34         struct srvsvc_NetCharDevGetInfo r;
35         uint32_t levels[] = {0, 1};
36         int i;
37
38         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
39         r.in.device_name = devname;
40
41         for (i=0;i<ARRAY_SIZE(levels);i++) {
42                 ZERO_STRUCT(r.out);
43                 r.in.level = levels[i];
44                 torture_comment(tctx, "testing NetCharDevGetInfo level %u on device '%s'\n",
45                         r.in.level, r.in.device_name);
46                 status = dcerpc_srvsvc_NetCharDevGetInfo(p, tctx, &r);
47                 torture_assert_ntstatus_ok(tctx, status, "NetCharDevGetInfo failed");
48                 torture_assert_werr_ok(tctx, r.out.result, "NetCharDevGetInfo failed");
49         }
50
51         return true;
52 }
53
54 static bool test_NetCharDevControl(struct dcerpc_pipe *p, struct torture_context *tctx,
55                                 const char *devname)
56 {
57         NTSTATUS status;
58         struct srvsvc_NetCharDevControl r;
59         uint32_t opcodes[] = {0, 1};
60         int i;
61
62         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
63         r.in.device_name = devname;
64
65         for (i=0;i<ARRAY_SIZE(opcodes);i++) {
66                 ZERO_STRUCT(r.out);
67                 r.in.opcode = opcodes[i];
68                 torture_comment(tctx, "testing NetCharDevControl opcode %u on device '%s'\n", 
69                         r.in.opcode, r.in.device_name);
70                 status = dcerpc_srvsvc_NetCharDevControl(p, tctx, &r);
71                 torture_assert_ntstatus_ok(tctx, status, "NetCharDevControl failed");
72                 torture_assert_werr_ok(tctx, r.out.result, "NetCharDevControl failed");
73         }
74
75         return true;
76 }
77
78 static bool test_NetCharDevEnum(struct torture_context *tctx, 
79                                                                 struct dcerpc_pipe *p)
80 {
81         NTSTATUS status;
82         struct srvsvc_NetCharDevEnum r;
83         struct srvsvc_NetCharDevCtr0 c0;
84         uint32_t levels[] = {0, 1};
85         int i;
86
87         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
88         r.in.ctr.ctr0 = &c0;
89         r.in.ctr.ctr0->count = 0;
90         r.in.ctr.ctr0->array = NULL;
91         r.in.max_buffer = (uint32_t)-1;
92         r.in.resume_handle = NULL;
93
94         for (i=0;i<ARRAY_SIZE(levels);i++) {
95                 int j;
96
97                 ZERO_STRUCT(r.out);
98                 r.in.level = levels[i];
99                 torture_comment(tctx, "testing NetCharDevEnum level %u\n", r.in.level);
100                 status = dcerpc_srvsvc_NetCharDevEnum(p, tctx, &r);
101                 torture_assert_ntstatus_ok(tctx, status, "NetCharDevEnum failed");
102                 torture_assert_werr_ok(tctx, r.out.result, "NetCharDevEnum failed");
103
104                 /* call test_NetCharDevGetInfo and test_NetCharDevControl for each returned share */
105                 if (r.in.level == 1) {
106                         for (j=0;j<r.out.ctr.ctr1->count;j++) {
107                                 const char *device;
108                                 device = r.out.ctr.ctr1->array[j].device;
109                                 if (!test_NetCharDevGetInfo(p, tctx, device)) {
110                                         return false;
111                                 }
112                                 if (!test_NetCharDevControl(p, tctx, device)) {
113                                         return false;
114                                 }
115                         }
116                 }
117         }
118
119         return true;
120 }
121
122 /**************************/
123 /* srvsvc_NetCharDevQ     */
124 /**************************/
125 static bool test_NetCharDevQGetInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
126                                 const char *devicequeue)
127 {
128         NTSTATUS status;
129         struct srvsvc_NetCharDevQGetInfo r;
130         uint32_t levels[] = {0, 1};
131         int i;
132
133         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
134         r.in.queue_name = devicequeue;
135         r.in.user = talloc_asprintf(tctx,"Administrator");
136
137         for (i=0;i<ARRAY_SIZE(levels);i++) {
138                 ZERO_STRUCT(r.out);
139                 r.in.level = levels[i];
140                 torture_comment(tctx, "testing NetCharDevQGetInfo level %u on devicequeue '%s'\n",
141                         r.in.level, r.in.queue_name);
142                 status = dcerpc_srvsvc_NetCharDevQGetInfo(p, tctx, &r);
143                 torture_assert_ntstatus_ok(tctx, status, "NetCharDevQGetInfo failed");
144                 torture_assert_werr_ok(tctx, r.out.result, "NetCharDevQGetInfo failed");
145         }
146
147         return true;
148 }
149
150 #if 0
151 static bool test_NetCharDevQSetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
152                                 const char *devicequeue)
153 {
154         NTSTATUS status;
155         struct srvsvc_NetCharDevQSetInfo r;
156         uint32_t parm_error;
157         uint32_t levels[] = {0, 1};
158         int i;
159         bool ret = true;
160
161         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
162         r.in.queue_name = devicequeue;
163
164         for (i=0;i<ARRAY_SIZE(levels);i++) {
165                 ZERO_STRUCT(r.out);
166                 parm_error = 0;
167                 r.in.level = levels[i];
168                 d_printf("testing NetCharDevQSetInfo level %u on devicequeue '%s'\n", 
169                         r.in.level, devicequeue);
170                 switch (r.in.level) {
171                 case 0:
172                         r.in.info.info0 = talloc(mem_ctx, struct srvsvc_NetCharDevQInfo0);
173                         r.in.info.info0->device = r.in.queue_name;
174                         break;
175                 case 1:
176                         r.in.info.info1 = talloc(mem_ctx, struct srvsvc_NetCharDevQInfo1);
177                         r.in.info.info1->device = r.in.queue_name;
178                         r.in.info.info1->priority = 0x000;
179                         r.in.info.info1->devices = r.in.queue_name;
180                         r.in.info.info1->users = 0x000;
181                         r.in.info.info1->num_ahead = 0x000;
182                         break;
183                 default:
184                         break;
185                 }
186                 r.in.parm_error = &parm_error;
187                 status = dcerpc_srvsvc_NetCharDevQSetInfo(p, mem_ctx, &r);
188                 if (!NT_STATUS_IS_OK(status)) {
189                         d_printf("NetCharDevQSetInfo level %u on devicequeue '%s' failed - %s\n",
190                                 r.in.level, r.in.queue_name, nt_errstr(status));
191                         ret = false;
192                         continue;
193                 }
194                 if (!W_ERROR_IS_OK(r.out.result)) {
195                         d_printf("NetCharDevQSetInfo level %u on devicequeue '%s' failed - %s\n",
196                                 r.in.level, r.in.queue_name, win_errstr(r.out.result));
197                         continue;
198                 }
199         }
200
201         return ret;
202 }
203 #endif
204
205 static bool test_NetCharDevQEnum(struct torture_context *tctx, 
206                                  struct dcerpc_pipe *p)
207 {
208         NTSTATUS status;
209         struct srvsvc_NetCharDevQEnum r;
210         struct srvsvc_NetCharDevQCtr0 c0;
211         uint32_t levels[] = {0, 1};
212         int i;
213
214         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
215         r.in.user = talloc_asprintf(tctx,"%s","Administrator");
216         r.in.ctr.ctr0 = &c0;
217         r.in.ctr.ctr0->count = 0;
218         r.in.ctr.ctr0->array = NULL;
219         r.in.max_buffer = (uint32_t)-1;
220         r.in.resume_handle = NULL;
221
222         for (i=0;i<ARRAY_SIZE(levels);i++) {
223                 int j;
224
225                 ZERO_STRUCT(r.out);
226                 r.in.level = levels[i];
227                 torture_comment(tctx, "testing NetCharDevQEnum level %u\n", r.in.level);
228                 status = dcerpc_srvsvc_NetCharDevQEnum(p, tctx, &r);
229                 torture_assert_ntstatus_ok(tctx, status, "NetCharDevQEnum failed");
230                 torture_assert_werr_ok(tctx, r.out.result, "NetCharDevQEnum failed");
231
232                 /* call test_NetCharDevGetInfo and test_NetCharDevControl for each returned share */
233                 if (r.in.level == 1) {
234                         for (j=0;j<r.out.ctr.ctr1->count;j++) {
235                                 const char *device;
236                                 device = r.out.ctr.ctr1->array[j].device;
237                                 if (!test_NetCharDevQGetInfo(p, tctx, device)) {
238                                         return false;
239                                 }
240                         }
241                 }
242         }
243
244         return true;
245 }
246
247 /**************************/
248 /* srvsvc_NetConn         */
249 /**************************/
250 static bool test_NetConnEnum(struct torture_context *tctx,
251                              struct dcerpc_pipe *p)
252 {
253         NTSTATUS status;
254         struct srvsvc_NetConnEnum r;
255         struct srvsvc_NetConnCtr0 c0;
256         uint32_t levels[] = {0, 1};
257         int i;
258
259         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
260         r.in.path = talloc_asprintf(tctx,"%s","ADMIN$");
261         r.in.ctr.ctr0 = &c0;
262         r.in.ctr.ctr0->count = 0;
263         r.in.ctr.ctr0->array = NULL;
264         r.in.max_buffer = (uint32_t)-1;
265         r.in.resume_handle = NULL;
266
267         for (i=0;i<ARRAY_SIZE(levels);i++) {
268                 ZERO_STRUCT(r.out);
269                 r.in.level = levels[i];
270                 torture_comment(tctx, "testing NetConnEnum level %u\n", r.in.level);
271                 status = dcerpc_srvsvc_NetConnEnum(p, tctx, &r);
272                 torture_assert_ntstatus_ok(tctx, status, "NetConnEnum failed");
273                 torture_assert_werr_ok(tctx, r.out.result, "NetConnEnum failed");
274         }
275
276         return true;
277 }
278
279 /**************************/
280 /* srvsvc_NetFile         */
281 /**************************/
282 static bool test_NetFileEnum(struct torture_context *tctx,
283                              struct dcerpc_pipe *p)
284 {
285         NTSTATUS status;
286         struct srvsvc_NetFileEnum r;
287         struct srvsvc_NetFileCtr3 c3;
288         uint32_t levels[] = {2, 3};
289         int i;
290
291         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
292         r.in.path = NULL;
293         r.in.user = NULL;
294         r.in.ctr.ctr3 = &c3;
295         r.in.ctr.ctr3->count = 0;
296         r.in.ctr.ctr3->array = NULL;
297         r.in.max_buffer = (uint32_t)4096;
298         r.in.resume_handle = NULL;
299
300         for (i=0;i<ARRAY_SIZE(levels);i++) {
301                 ZERO_STRUCT(r.out);
302                 r.in.level = levels[i];
303                 torture_comment(tctx, "testing NetFileEnum level %u\n", r.in.level);
304                 status = dcerpc_srvsvc_NetFileEnum(p, tctx, &r);
305                 torture_assert_ntstatus_ok(tctx, status, "NetFileEnum failed");
306                 torture_assert_werr_ok(tctx, r.out.result, "NetFileEnum failed");
307         }
308
309         return true;
310 }
311
312 /**************************/
313 /* srvsvc_NetSess         */
314 /**************************/
315 static bool test_NetSessEnum(struct torture_context *tctx,
316                              struct dcerpc_pipe *p)
317 {
318         NTSTATUS status;
319         struct srvsvc_NetSessEnum r;
320         struct srvsvc_NetSessCtr0 c0;
321         uint32_t levels[] = {0, 1, 2, 10, 502};
322         int i;
323
324         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
325         r.in.client = NULL;
326         r.in.user = NULL;
327         r.in.ctr.ctr0 = &c0;
328         r.in.ctr.ctr0->count = 0;
329         r.in.ctr.ctr0->array = NULL;
330         r.in.max_buffer = (uint32_t)-1;
331         r.in.resume_handle = NULL;
332
333         for (i=0;i<ARRAY_SIZE(levels);i++) {
334                 ZERO_STRUCT(r.out);
335                 r.in.level = levels[i];
336                 torture_comment(tctx, "testing NetSessEnum level %u\n", r.in.level);
337                 status = dcerpc_srvsvc_NetSessEnum(p, tctx, &r);
338                 torture_assert_ntstatus_ok(tctx, status, "NetSessEnum failed");
339                 torture_assert_werr_ok(tctx, r.out.result, "NetSessEnum failed");
340         }
341
342         return true;
343 }
344
345 /**************************/
346 /* srvsvc_NetShare        */
347 /**************************/
348 static bool test_NetShareCheck(struct dcerpc_pipe *p, struct torture_context *tctx,
349                                const char *device_name)
350 {
351         NTSTATUS status;
352         struct srvsvc_NetShareCheck r;
353
354         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
355         r.in.device_name = device_name;
356
357         torture_comment(tctx, 
358                         "testing NetShareCheck on device '%s'\n", r.in.device_name);
359
360         status = dcerpc_srvsvc_NetShareCheck(p, tctx, &r);
361         torture_assert_ntstatus_ok(tctx, status, "dcerpc_srvsvc_NetShareCheck failed");
362         torture_assert_werr_ok(tctx, r.out.result, "NetShareCheck failed");
363
364         return true;
365 }
366
367 static bool test_NetShareGetInfo(struct torture_context *tctx, 
368                                  struct dcerpc_pipe *p,
369                                  const char *sharename, bool admin)
370 {
371         NTSTATUS status;
372         struct srvsvc_NetShareGetInfo r;
373         struct {
374                 uint32_t level;
375                 WERROR anon_status;
376                 WERROR admin_status;
377         } levels[] = {
378                  { 0,           WERR_OK,                WERR_OK },
379                  { 1,           WERR_OK,                WERR_OK },
380                  { 2,           WERR_ACCESS_DENIED,     WERR_OK },
381                  { 501,         WERR_OK,                WERR_OK },
382                  { 502,         WERR_ACCESS_DENIED,     WERR_OK },
383                  { 1005,        WERR_OK,                WERR_OK },
384         };
385         int i;
386
387         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
388         r.in.share_name = sharename;
389
390         for (i=0;i<ARRAY_SIZE(levels);i++) {
391                 WERROR expected;
392
393                 r.in.level = levels[i].level;
394                 expected = levels[i].anon_status;
395                 if (admin) expected = levels[i].admin_status;
396                 ZERO_STRUCT(r.out);
397
398                 torture_comment(tctx, "testing NetShareGetInfo level %u on share '%s'\n", 
399                        r.in.level, r.in.share_name);
400
401                 status = dcerpc_srvsvc_NetShareGetInfo(p, tctx, &r);
402                 torture_assert_ntstatus_ok(tctx, status, "NetShareGetInfo failed");
403                 torture_assert_werr_equal(tctx, r.out.result, expected, "NetShareGetInfo failed");
404
405                 if (r.in.level != 2) continue;
406                 if (!r.out.info.info2 || !r.out.info.info2->path) continue;
407                 if (!test_NetShareCheck(p, tctx, r.out.info.info2->path)) {
408                         return false;
409                 }
410         }
411
412         return true;
413 }
414
415 static bool test_NetShareGetInfoAdminFull(struct torture_context *tctx, 
416                                           struct dcerpc_pipe *p)
417 {
418         return test_NetShareGetInfo(tctx, p, "ADMIN$", true);
419 }
420
421 static bool test_NetShareGetInfoAdminAnon(struct torture_context *tctx, 
422                                           struct dcerpc_pipe *p)
423 {
424         return test_NetShareGetInfo(tctx, p, "ADMIN$", false);
425 }
426
427 static bool test_NetShareAddSetDel(struct torture_context *tctx, 
428                                    struct dcerpc_pipe *p)
429 {
430         NTSTATUS status;
431         struct srvsvc_NetShareAdd a;
432         struct srvsvc_NetShareSetInfo r;
433         struct srvsvc_NetShareGetInfo q;
434         struct srvsvc_NetShareDel d;
435         struct {
436                 uint32_t level;
437                 WERROR expected;
438         } levels[] = {
439                  { 0,           WERR_UNKNOWN_LEVEL },
440                  { 1,           WERR_OK },
441                  { 2,           WERR_OK },
442                  { 501,         WERR_UNKNOWN_LEVEL },
443                  { 502,         WERR_OK },
444                  { 1004,        WERR_OK },
445                  { 1005,        WERR_OK },
446                  { 1006,        WERR_OK },
447 /*               { 1007,        WERR_OK }, */
448                  { 1501,        WERR_OK },
449         };
450         int i;
451
452         a.in.server_unc = r.in.server_unc = q.in.server_unc = d.in.server_unc =
453                 talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
454         r.in.share_name = talloc_strdup(tctx, "testshare");
455
456         a.in.level = 2;
457         a.in.info.info2 = talloc(tctx, struct srvsvc_NetShareInfo2);
458         a.in.info.info2->name = r.in.share_name;
459         a.in.info.info2->type = STYPE_DISKTREE;
460         a.in.info.info2->comment = talloc_strdup(tctx, "test comment");
461         a.in.info.info2->permissions = 123434566;
462         a.in.info.info2->max_users = -1;
463         a.in.info.info2->current_users = 0;
464         a.in.info.info2->path = talloc_strdup(tctx, "C:\\");
465         a.in.info.info2->password = NULL;
466
467         a.in.parm_error = NULL;
468
469         status = dcerpc_srvsvc_NetShareAdd(p, tctx, &a);
470         torture_assert_ntstatus_ok(tctx, status, "NetShareAdd level 2 on share 'testshare' failed");
471         torture_assert_werr_ok(tctx, a.out.result, "NetShareAdd level 2 on share 'testshare' failed");
472
473         r.in.parm_error = NULL;
474
475         q.in.level = 502;
476
477         for (i = 0; i < ARRAY_SIZE(levels); i++) {
478
479                 r.in.level = levels[i].level;
480                 ZERO_STRUCT(r.out);
481
482                 torture_comment(tctx, "testing NetShareSetInfo level %u on share '%s'\n", 
483                        r.in.level, r.in.share_name);
484
485                 switch (levels[i].level) {
486                 case 0:
487                         r.in.info.info0 = talloc(tctx, struct srvsvc_NetShareInfo0);
488                         r.in.info.info0->name = r.in.share_name;
489                         break;
490                 case 1:
491                         r.in.info.info1 = talloc(tctx, struct srvsvc_NetShareInfo1);
492                         r.in.info.info1->name = r.in.share_name;
493                         r.in.info.info1->type = STYPE_DISKTREE;
494                         r.in.info.info1->comment = talloc_strdup(tctx, "test comment 1");
495                         break;
496                 case 2: 
497                         r.in.info.info2 = talloc(tctx, struct srvsvc_NetShareInfo2);
498                         r.in.info.info2->name = r.in.share_name;
499                         r.in.info.info2->type = STYPE_DISKTREE;
500                         r.in.info.info2->comment = talloc_strdup(tctx, "test comment 2");
501                         r.in.info.info2->permissions = 0;
502                         r.in.info.info2->max_users = 2;
503                         r.in.info.info2->current_users = 1;
504                         r.in.info.info2->path = talloc_strdup(tctx, "::BLaH::"); /* "C:\\"); */
505                         r.in.info.info2->password = NULL;
506                         break;
507                 case 501:
508                         r.in.info.info501 = talloc(tctx, struct srvsvc_NetShareInfo501);
509                         r.in.info.info501->name = r.in.share_name;
510                         r.in.info.info501->type = STYPE_DISKTREE;
511                         r.in.info.info501->comment = talloc_strdup(tctx, "test comment 501");
512                         r.in.info.info501->csc_policy = 0;
513                         break;
514                 case 502:
515                         r.in.info.info502 = talloc(tctx, struct srvsvc_NetShareInfo502);
516                         r.in.info.info502->name = r.in.share_name;
517                         r.in.info.info502->type = STYPE_DISKTREE;
518                         r.in.info.info502->comment = talloc_strdup(tctx, "test comment 502");
519                         r.in.info.info502->permissions = 0;
520                         r.in.info.info502->max_users = 502;
521                         r.in.info.info502->current_users = 1;
522                         r.in.info.info502->path = talloc_strdup(tctx, "C:\\");
523                         r.in.info.info502->password = NULL;
524                         r.in.info.info502->unknown = 0;
525                         r.in.info.info502->sd = NULL;
526                         break;
527                 case 1004:
528                         r.in.info.info1004 = talloc(tctx, struct srvsvc_NetShareInfo1004);
529                         r.in.info.info1004->comment = talloc_strdup(tctx, "test comment 1004");
530                         break;
531                 case 1005:
532                         r.in.info.info1005 = talloc(tctx, struct srvsvc_NetShareInfo1005);
533                         r.in.info.info1005->dfs_flags = 0;
534                         break;
535                 case 1006:
536                         r.in.info.info1006 = talloc(tctx, struct srvsvc_NetShareInfo1006);
537                         r.in.info.info1006->max_users = 1006;
538                         break;
539 /*              case 1007:
540                         r.in.info.info1007 = talloc(tctx, struct srvsvc_NetShareInfo1007);
541                         r.in.info.info1007->flags = 0;
542                         r.in.info.info1007->alternate_directory_name = talloc_strdup(tctx, "test");
543                         break;
544 */
545                 case 1501:
546                         r.in.info.info1501 = talloc_zero(tctx, struct sec_desc_buf);
547                         break;
548                 }
549                 
550                 status = dcerpc_srvsvc_NetShareSetInfo(p, tctx, &r);
551                 torture_assert_ntstatus_ok(tctx, status, "NetShareGetInfo failed");
552                 torture_assert_werr_equal(tctx, r.out.result, levels[i].expected, "NetShareSetInfo failed");
553                 
554                 q.in.share_name = r.in.share_name;
555
556                 status = dcerpc_srvsvc_NetShareGetInfo(p, tctx, &q);
557                 torture_assert_ntstatus_ok(tctx, status, "NetShareGetInfo failed");
558                 torture_assert_werr_ok(tctx, q.out.result, "NetShareGetInfo failed");
559
560                 torture_assert_str_equal(tctx, q.out.info.info502->name, r.in.share_name, 
561                                          "share name invalid");
562
563                 switch (levels[i].level) {
564                 case 0:
565                         break;
566                 case 1:
567                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 1", "comment");
568                         break;
569                 case 2:
570                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 2", "comment");
571                         torture_assert_int_equal(tctx, q.out.info.info2->max_users, 2, "max users");
572                         torture_assert_str_equal(tctx, q.out.info.info2->path, "C:\\", "path");
573                         break;
574                 case 501:
575                         torture_assert_str_equal(tctx, q.out.info.info501->comment, "test comment 501", "comment");
576                         break;
577                 case 502:
578                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 502", "comment");
579                         torture_assert_int_equal(tctx, q.out.info.info2->max_users, 502, "max users");
580                         torture_assert_str_equal(tctx, q.out.info.info2->path, "C:\\", "path");
581                         break;
582                 case 1004:
583                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 1004", 
584                                                  "comment");
585                         break;
586                 case 1005:
587                         break;
588                 case 1006:
589                         torture_assert_int_equal(tctx, q.out.info.info2->max_users, 1006, "Max users");
590                         break;
591 /*              case 1007:
592                         break;
593 */
594                 case 1501:
595                         break;
596                 }
597         }
598
599         d.in.share_name = r.in.share_name;
600         d.in.reserved = 0;
601
602         status = dcerpc_srvsvc_NetShareDel(p, tctx, &d);
603         torture_assert_ntstatus_ok(tctx, status, "NetShareDel on share 'testshare502' failed");
604         torture_assert_werr_ok(tctx, a.out.result, "NetShareDel on share 'testshare502' failed");
605
606         return true;
607 }
608
609 /**************************/
610 /* srvsvc_NetShare        */
611 /**************************/
612 static bool test_NetShareEnumAll(struct torture_context *tctx, 
613                                  struct dcerpc_pipe *p, 
614                                  bool admin)
615 {
616         NTSTATUS status;
617         struct srvsvc_NetShareEnumAll r;
618         struct srvsvc_NetShareCtr0 c0;
619         struct {
620                 uint32_t level;
621                 WERROR anon_status;
622                 WERROR admin_status;
623         } levels[] = {
624                  { 0,   WERR_OK,                WERR_OK },
625                  { 1,   WERR_OK,                WERR_OK },
626                  { 2,   WERR_ACCESS_DENIED,     WERR_OK },
627                  { 501, WERR_ACCESS_DENIED,     WERR_OK },
628                  { 502, WERR_ACCESS_DENIED,     WERR_OK },
629         };
630         int i;
631         uint32_t resume_handle;
632
633         ZERO_STRUCT(c0);
634
635         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
636         r.in.ctr.ctr0 = &c0;
637         r.in.max_buffer = (uint32_t)-1;
638         r.in.resume_handle = &resume_handle;
639         r.out.resume_handle = &resume_handle;
640
641         for (i=0;i<ARRAY_SIZE(levels);i++) {
642                 int j;
643                 WERROR expected;
644
645                 r.in.level = levels[i].level;
646                 expected = levels[i].anon_status;
647                 if (admin) expected = levels[i].admin_status;
648
649                 ZERO_STRUCT(r.out);
650                 resume_handle = 0;
651
652                 torture_comment(tctx, "testing NetShareEnumAll level %u\n", r.in.level);
653                 status = dcerpc_srvsvc_NetShareEnumAll(p, tctx, &r);
654                 torture_assert_ntstatus_ok(tctx, status, "NetShareEnumAll failed");
655                 torture_assert_werr_equal(tctx, r.out.result, expected, "NetShareEnumAll failed");
656
657                 /* call srvsvc_NetShareGetInfo for each returned share */
658                 if (r.in.level == 2 && r.out.ctr.ctr2) {
659                         for (j=0;j<r.out.ctr.ctr2->count;j++) {
660                                 const char *name;
661                                 name = r.out.ctr.ctr2->array[j].name;
662                                 if (!test_NetShareGetInfo(tctx, p, name, admin)) {
663                                         return false;
664                                 }
665                         }
666                 }
667         }
668
669         return true;
670 }
671
672 static bool test_NetShareEnumAllFull(struct torture_context *tctx,
673                               struct dcerpc_pipe *p)
674 {
675         return test_NetShareEnumAll(tctx, p, true);
676 }
677
678 static bool test_NetShareEnumAllAnon(struct torture_context *tctx,
679                               struct dcerpc_pipe *p)
680 {
681         return test_NetShareEnumAll(tctx, p, false);
682 }
683
684 static bool test_NetShareEnum(struct torture_context *tctx,
685                               struct dcerpc_pipe *p, bool admin)
686 {
687         NTSTATUS status;
688         struct srvsvc_NetShareEnum r;
689         struct srvsvc_NetShareCtr0 c0;
690         struct {
691                 uint32_t level;
692                 WERROR anon_status;
693                 WERROR admin_status;
694         } levels[] = {
695                  { 0,   WERR_OK,                WERR_OK },
696                  { 1,   WERR_OK,                WERR_OK },
697                  { 2,   WERR_ACCESS_DENIED,     WERR_OK },
698                  { 501, WERR_UNKNOWN_LEVEL,     WERR_UNKNOWN_LEVEL },
699                  { 502, WERR_ACCESS_DENIED,     WERR_OK },
700         };
701         int i;
702
703         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
704         r.in.ctr.ctr0 = &c0;
705         r.in.ctr.ctr0->count = 0;
706         r.in.ctr.ctr0->array = NULL;
707         r.in.max_buffer = (uint32_t)-1;
708         r.in.resume_handle = NULL;
709
710         for (i=0;i<ARRAY_SIZE(levels);i++) {
711                 WERROR expected;
712
713                 r.in.level = levels[i].level;
714                 expected = levels[i].anon_status;
715                 if (admin) expected = levels[i].admin_status;
716
717                 ZERO_STRUCT(r.out);
718
719                 torture_comment(tctx, "testing NetShareEnum level %u\n", r.in.level);
720                 status = dcerpc_srvsvc_NetShareEnum(p, tctx, &r);
721                 torture_assert_ntstatus_ok(tctx, status, "NetShareEnum failed");
722                 torture_assert_werr_equal(tctx, r.out.result, expected, "NetShareEnum failed");
723         }
724
725         return true;
726 }
727
728 static bool test_NetShareEnumFull(struct torture_context *tctx,
729                                   struct dcerpc_pipe *p)
730 {
731         return test_NetShareEnum(tctx, p, true);
732 }
733
734 static bool test_NetShareEnumAnon(struct torture_context *tctx,
735                                   struct dcerpc_pipe *p)
736 {
737         return test_NetShareEnum(tctx, p, false);
738 }
739
740 /**************************/
741 /* srvsvc_NetSrv          */
742 /**************************/
743 static bool test_NetSrvGetInfo(struct torture_context *tctx, 
744                                                            struct dcerpc_pipe *p)
745 {
746         NTSTATUS status;
747         struct srvsvc_NetSrvGetInfo r;
748         struct srvsvc_NetSrvInfo503 i503;
749         uint32_t levels[] = {100, 101, 102, 502, 503};
750         int i;
751         uint32_t resume_handle;
752
753         ZERO_STRUCT(i503);
754
755         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
756
757         for (i=0;i<ARRAY_SIZE(levels);i++) {
758                 ZERO_STRUCT(r.out);
759                 resume_handle = 0;
760                 r.in.level = levels[i];
761                 torture_comment(tctx, "testing NetSrvGetInfo level %u\n", r.in.level);
762                 status = dcerpc_srvsvc_NetSrvGetInfo(p, tctx, &r);
763                 torture_assert_ntstatus_ok(tctx, status, "NetSrvGetInfo failed");
764                 torture_assert_werr_ok(tctx, r.out.result, "NetSrvGetInfo failed");
765         }
766
767         return true;
768 }
769
770 /**************************/
771 /* srvsvc_NetDisk         */
772 /**************************/
773 static bool test_NetDiskEnum(struct torture_context *tctx, 
774                              struct dcerpc_pipe *p)
775 {
776         NTSTATUS status;
777         struct srvsvc_NetDiskEnum r;
778         uint32_t levels[] = {0};
779         int i;
780         uint32_t resume_handle=0;
781
782         ZERO_STRUCT(r.in);
783         r.in.server_unc = NULL;
784         r.in.resume_handle = &resume_handle;
785
786         for (i=0;i<ARRAY_SIZE(levels);i++) {
787                 ZERO_STRUCT(r.out);
788                 r.in.level = levels[i];
789                 torture_comment(tctx, "testing NetDiskEnum level %u\n", r.in.level);
790                 status = dcerpc_srvsvc_NetDiskEnum(p, tctx, &r);
791                 torture_assert_ntstatus_ok(tctx, status, "NetDiskEnum failed");
792                 torture_assert_werr_ok(tctx, r.out.result, "NetDiskEnum failed");
793         }
794
795         return true;
796 }
797
798 /**************************/
799 /* srvsvc_NetTransport    */
800 /**************************/
801 static bool test_NetTransportEnum(struct torture_context *tctx, 
802                                                                   struct dcerpc_pipe *p)
803 {
804         NTSTATUS status;
805         struct srvsvc_NetTransportEnum r;
806         struct srvsvc_NetTransportCtr0 c0;
807         uint32_t levels[] = {0, 1};
808         int i;
809
810         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
811         r.in.transports.ctr0 = &c0;
812         r.in.transports.ctr0->count = 0;
813         r.in.transports.ctr0->array = NULL;
814         r.in.max_buffer = (uint32_t)-1;
815         r.in.resume_handle = NULL;
816
817         for (i=0;i<ARRAY_SIZE(levels);i++) {
818                 ZERO_STRUCT(r.out);
819                 r.in.level = levels[i];
820                 torture_comment(tctx, "testing NetTransportEnum level %u\n", r.in.level);
821                 status = dcerpc_srvsvc_NetTransportEnum(p, tctx, &r);
822                 torture_assert_ntstatus_ok(tctx, status, "NetTransportEnum failed");
823                 torture_assert_werr_ok(tctx, r.out.result, "NetTransportEnum failed");
824         }
825
826         return true;
827 }
828
829 /**************************/
830 /* srvsvc_NetRemoteTOD    */
831 /**************************/
832 static bool test_NetRemoteTOD(struct torture_context *tctx, 
833                               struct dcerpc_pipe *p)
834 {
835         NTSTATUS status;
836         struct srvsvc_NetRemoteTOD r;
837
838         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
839
840         ZERO_STRUCT(r.out);
841         torture_comment(tctx, "testing NetRemoteTOD\n");
842         status = dcerpc_srvsvc_NetRemoteTOD(p, tctx, &r);
843         torture_assert_ntstatus_ok(tctx, status, "NetRemoteTOD failed");
844         torture_assert_werr_ok(tctx, r.out.result, "NetRemoteTOD failed");
845
846         return true;
847 }
848
849 /**************************/
850 /* srvsvc_NetName         */
851 /**************************/
852
853 static bool test_NetNameValidate(struct torture_context *tctx, 
854                                                                  struct dcerpc_pipe *p)
855 {
856         NTSTATUS status;
857         struct srvsvc_NetNameValidate r;
858         char *invalidc;
859         char *name;
860         int i, n, min, max;
861
862         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
863         r.in.flags = 0x0;
864
865         d_printf("testing NetNameValidate\n");
866
867         /* valid path types only between 1 and 13 */
868         for (i = 1; i < 14; i++) {
869
870 again:
871                 /* let's limit ourselves to a maximum of 4096 bytes */
872                 r.in.name = name = talloc_array(tctx, char, 4097);
873                 max = 4096;
874                 min = 0;
875                 n = max;
876
877                 while (1) {
878
879                         /* Find maximum length accepted by this type */
880                         ZERO_STRUCT(r.out);
881                         r.in.name_type = i;
882                         memset(name, 'A', n);
883                         name[n] = '\0';
884
885                         status = dcerpc_srvsvc_NetNameValidate(p, tctx, &r);
886                         if (!NT_STATUS_IS_OK(status)) {
887                                 d_printf("NetNameValidate failed while checking maximum size (%s)\n",
888                                                 nt_errstr(status));
889                                 break;
890                         }
891
892                         if (W_ERROR_IS_OK(r.out.result)) {
893                                 min = n;
894                                 n += (max - min + 1)/2;
895                                 continue;
896                                 
897                         } else {
898                                 if ((min + 1) >= max) break; /* found it */
899                                 
900                                 max = n;
901                                 n -= (max - min)/2;
902                                 continue;
903                         }
904                 }
905
906                 talloc_free(name);
907
908                 d_printf("Maximum length for type %2d, flags %08x: %d\n", i, r.in.flags, max);
909
910                 /* find invalid chars for this type check only ASCII between 0x20 and 0x7e */
911
912                 invalidc = talloc_strdup(tctx, "");
913
914                 for (n = 0x20; n < 0x7e; n++) {
915                         r.in.name = name = talloc_asprintf(tctx, "%c", (char)n);
916
917                         status = dcerpc_srvsvc_NetNameValidate(p, tctx, &r);
918                         if (!NT_STATUS_IS_OK(status)) {
919                                 d_printf("NetNameValidate failed while checking valid chars (%s)\n",
920                                                 nt_errstr(status));
921                                 break;
922                         }
923
924                         if (!W_ERROR_IS_OK(r.out.result)) {
925                                 invalidc = talloc_asprintf_append(invalidc, "%c", (char)n);
926                         }
927
928                         talloc_free(name);
929                 }
930
931                 d_printf(" Invalid chars for type %2d, flags %08x: \"%s\"\n", i, r.in.flags, invalidc);
932
933                 /* only two values are accepted for flags: 0x0 and 0x80000000 */
934                 if (r.in.flags == 0x0) {
935                         r.in.flags = 0x80000000;
936                         goto again;
937                 }
938
939                 r.in.flags = 0x0;
940         }
941
942         return true;
943 }
944
945 struct torture_suite *torture_rpc_srvsvc(TALLOC_CTX *mem_ctx)
946 {
947         struct torture_suite *suite = torture_suite_create(mem_ctx, "SRVSVC");
948         struct torture_rpc_tcase *tcase;
949         struct torture_test *test;
950
951         tcase = torture_suite_add_rpc_iface_tcase(suite, "srvsvc (admin access)", &ndr_table_srvsvc);
952
953         torture_rpc_tcase_add_test(tcase, "NetCharDevEnum", test_NetCharDevEnum);
954         torture_rpc_tcase_add_test(tcase, "NetCharDevQEnum", test_NetCharDevQEnum);
955         torture_rpc_tcase_add_test(tcase, "NetConnEnum", test_NetConnEnum);
956         torture_rpc_tcase_add_test(tcase, "NetFileEnum", test_NetFileEnum);
957         torture_rpc_tcase_add_test(tcase, "NetSessEnum", test_NetSessEnum);
958         torture_rpc_tcase_add_test(tcase, "NetShareEnumAll", test_NetShareEnumAllFull);
959         torture_rpc_tcase_add_test(tcase, "NetSrvGetInfo", test_NetSrvGetInfo);
960         torture_rpc_tcase_add_test(tcase, "NetDiskEnum", test_NetDiskEnum);
961         torture_rpc_tcase_add_test(tcase, "NetTransportEnum", test_NetTransportEnum);
962         torture_rpc_tcase_add_test(tcase, "NetRemoteTOD", test_NetRemoteTOD);
963         torture_rpc_tcase_add_test(tcase, "NetShareEnum", test_NetShareEnumFull);
964         torture_rpc_tcase_add_test(tcase, "NetShareGetInfo", test_NetShareGetInfoAdminFull);
965         test = torture_rpc_tcase_add_test(tcase, "NetShareAddSetDel", 
966                                            test_NetShareAddSetDel);
967         test->dangerous = true;
968         torture_rpc_tcase_add_test(tcase, "NetNameValidate", test_NetNameValidate);
969         
970         tcase = torture_suite_add_anon_rpc_iface_tcase(suite, 
971                                                     "srvsvc anonymous access", 
972                                                     &ndr_table_srvsvc);
973
974         torture_rpc_tcase_add_test(tcase, "NetShareEnumAll", 
975                                    test_NetShareEnumAllAnon);
976         torture_rpc_tcase_add_test(tcase, "NetShareEnum", 
977                                    test_NetShareEnumAnon);
978         torture_rpc_tcase_add_test(tcase, "NetShareGetInfo", 
979                                    test_NetShareGetInfoAdminAnon);
980
981         return suite;
982 }