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