r24557: rename 'dcerpc_table_' -> 'ndr_table_'
[ira/wip.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 dcerpc_pipe *p, 
97                            TALLOC_CTX *mem_ctx)
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(mem_ctx,"\\\\%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, mem_ctx, &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, mem_ctx, device)) {
137                                         ret = False;
138                                 }
139                                 if (!test_NetCharDevControl(p, mem_ctx, 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 dcerpc_pipe *p, 
243                            TALLOC_CTX *mem_ctx)
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(mem_ctx,"\\\\%s",dcerpc_server_name(p));
253         r.in.user = talloc_asprintf(mem_ctx,"%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, mem_ctx, &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, mem_ctx, 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 dcerpc_pipe *p, 
296                            TALLOC_CTX *mem_ctx)
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(mem_ctx,"\\\\%s",dcerpc_server_name(p));
306         r.in.path = talloc_asprintf(mem_ctx,"%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, mem_ctx, &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 dcerpc_pipe *p, 
336                            TALLOC_CTX *mem_ctx)
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(mem_ctx,"\\\\%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, mem_ctx, &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 dcerpc_pipe *p, 
377                            TALLOC_CTX *mem_ctx)
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(mem_ctx,"\\\\%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, mem_ctx, &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 dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
444                                  const char *sharename, BOOL admin)
445 {
446         NTSTATUS status;
447         struct srvsvc_NetShareGetInfo r;
448         struct {
449                 uint32_t level;
450                 WERROR anon_status;
451                 WERROR admin_status;
452         } levels[] = {
453                  { 0,           WERR_OK,                WERR_OK },
454                  { 1,           WERR_OK,                WERR_OK },
455                  { 2,           WERR_ACCESS_DENIED,     WERR_OK },
456                  { 501,         WERR_OK,                WERR_OK },
457                  { 502,         WERR_ACCESS_DENIED,     WERR_OK },
458                  { 1005,        WERR_OK,                WERR_OK },
459         };
460         int i;
461         BOOL ret = True;
462
463         r.in.server_unc = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
464         r.in.share_name = sharename;
465
466         for (i=0;i<ARRAY_SIZE(levels);i++) {
467                 WERROR expected;
468
469                 r.in.level = levels[i].level;
470                 expected = levels[i].anon_status;
471                 if (admin) expected = levels[i].admin_status;
472                 ZERO_STRUCT(r.out);
473
474                 d_printf("testing NetShareGetInfo level %u on share '%s'\n", 
475                        r.in.level, r.in.share_name);
476
477                 status = dcerpc_srvsvc_NetShareGetInfo(p, mem_ctx, &r);
478                 if (!NT_STATUS_IS_OK(status)) {
479                         d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
480                                 r.in.level, r.in.share_name, nt_errstr(status));
481                         ret = False;
482                         continue;
483                 }
484                 if (!W_ERROR_EQUAL(r.out.result, expected)) {
485                         d_printf("NetShareGetInfo level %u on share '%s' failed - %s (expected %s)\n",
486                                 r.in.level, r.in.share_name, win_errstr(r.out.result),
487                                 win_errstr(expected));
488                         ret = False;
489                         continue;
490                 }
491
492                 if (r.in.level != 2) continue;
493                 if (!r.out.info.info2 || !r.out.info.info2->path) continue;
494                 if (!test_NetShareCheck(p, mem_ctx, r.out.info.info2->path)) {
495                         ret = False;
496                 }
497         }
498
499         return ret;
500 }
501
502 static BOOL test_NetShareAddSetDel(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
503 {
504         NTSTATUS status;
505         struct srvsvc_NetShareAdd a;
506         struct srvsvc_NetShareSetInfo r;
507         struct srvsvc_NetShareGetInfo q;
508         struct srvsvc_NetShareDel d;
509         struct {
510                 uint32_t level;
511                 WERROR expected;
512         } levels[] = {
513                  { 0,           WERR_UNKNOWN_LEVEL },
514                  { 1,           WERR_OK },
515                  { 2,           WERR_OK },
516                  { 501,         WERR_UNKNOWN_LEVEL },
517                  { 502,         WERR_OK },
518                  { 1004,        WERR_OK },
519                  { 1005,        WERR_OK },
520                  { 1006,        WERR_OK },
521 /*               { 1007,        WERR_OK }, */
522                  { 1501,        WERR_OK },
523         };
524         int i;
525         BOOL ret = True;
526
527         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
528                 d_printf("NetShareAddSetDel disabled - enable dangerous tests to use\n");
529                 return True;
530         }
531
532         a.in.server_unc = r.in.server_unc = q.in.server_unc = d.in.server_unc =
533                 talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
534         r.in.share_name = talloc_strdup(mem_ctx, "testshare");
535
536         a.in.level = 2;
537         a.in.info.info2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2);
538         a.in.info.info2->name = r.in.share_name;
539         a.in.info.info2->type = STYPE_DISKTREE;
540         a.in.info.info2->comment = talloc_strdup(mem_ctx, "test comment");
541         a.in.info.info2->permissions = 123434566;
542         a.in.info.info2->max_users = -1;
543         a.in.info.info2->current_users = 0;
544         a.in.info.info2->path = talloc_strdup(mem_ctx, "C:\\");
545         a.in.info.info2->password = NULL;
546
547         a.in.parm_error = NULL;
548
549         status = dcerpc_srvsvc_NetShareAdd(p, mem_ctx, &a);
550         if (!NT_STATUS_IS_OK(status)) {
551                 d_printf("NetShareAdd level 2 on share 'testshare' failed - %s\n",
552                          nt_errstr(status));
553                 return False;
554         } else if (!W_ERROR_EQUAL(a.out.result, WERR_OK)) {
555                 d_printf("NetShareAdd level 2 on share 'testshare' failed - %s\n",
556                          win_errstr(a.out.result));
557                 return False;
558         }
559
560         r.in.parm_error = NULL;
561
562         q.in.level = 502;
563
564         for (i = 0; i < ARRAY_SIZE(levels); i++) {
565
566                 r.in.level = levels[i].level;
567                 ZERO_STRUCT(r.out);
568
569                 d_printf("testing NetShareSetInfo level %u on share '%s'\n", 
570                        r.in.level, r.in.share_name);
571
572                 switch (levels[i].level) {
573                 case 0:
574                         r.in.info.info0 = talloc(mem_ctx, struct srvsvc_NetShareInfo0);
575                         r.in.info.info0->name = r.in.share_name;
576                         break;
577                 case 1:
578                         r.in.info.info1 = talloc(mem_ctx, struct srvsvc_NetShareInfo1);
579                         r.in.info.info1->name = r.in.share_name;
580                         r.in.info.info1->type = STYPE_DISKTREE;
581                         r.in.info.info1->comment = talloc_strdup(mem_ctx, "test comment 1");
582                         break;
583                 case 2: 
584                         r.in.info.info2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2);
585                         r.in.info.info2->name = r.in.share_name;
586                         r.in.info.info2->type = STYPE_DISKTREE;
587                         r.in.info.info2->comment = talloc_strdup(mem_ctx, "test comment 2");
588                         r.in.info.info2->permissions = 0;
589                         r.in.info.info2->max_users = 2;
590                         r.in.info.info2->current_users = 1;
591                         r.in.info.info2->path = talloc_strdup(mem_ctx, "::BLaH::"); /* "C:\\"); */
592                         r.in.info.info2->password = NULL;
593                         break;
594                 case 501:
595                         r.in.info.info501 = talloc(mem_ctx, struct srvsvc_NetShareInfo501);
596                         r.in.info.info501->name = r.in.share_name;
597                         r.in.info.info501->type = STYPE_DISKTREE;
598                         r.in.info.info501->comment = talloc_strdup(mem_ctx, "test comment 501");
599                         r.in.info.info501->csc_policy = 0;
600                         break;
601                 case 502:
602                         r.in.info.info502 = talloc(mem_ctx, struct srvsvc_NetShareInfo502);
603                         r.in.info.info502->name = r.in.share_name;
604                         r.in.info.info502->type = STYPE_DISKTREE;
605                         r.in.info.info502->comment = talloc_strdup(mem_ctx, "test comment 502");
606                         r.in.info.info502->permissions = 0;
607                         r.in.info.info502->max_users = 502;
608                         r.in.info.info502->current_users = 1;
609                         r.in.info.info502->path = talloc_strdup(mem_ctx, "C:\\");
610                         r.in.info.info502->password = NULL;
611                         r.in.info.info502->unknown = 0;
612                         r.in.info.info502->sd = NULL;
613                         break;
614                 case 1004:
615                         r.in.info.info1004 = talloc(mem_ctx, struct srvsvc_NetShareInfo1004);
616                         r.in.info.info1004->comment = talloc_strdup(mem_ctx, "test comment 1004");
617                         break;
618                 case 1005:
619                         r.in.info.info1005 = talloc(mem_ctx, struct srvsvc_NetShareInfo1005);
620                         r.in.info.info1005->dfs_flags = 0;
621                         break;
622                 case 1006:
623                         r.in.info.info1006 = talloc(mem_ctx, struct srvsvc_NetShareInfo1006);
624                         r.in.info.info1006->max_users = 1006;
625                         break;
626 /*              case 1007:
627                         r.in.info.info1007 = talloc(mem_ctx, struct srvsvc_NetShareInfo1007);
628                         r.in.info.info1007->flags = 0;
629                         r.in.info.info1007->alternate_directory_name = talloc_strdup(mem_ctx, "test");
630                         break;
631 */
632                 case 1501:
633                         r.in.info.info1501 = talloc_zero(mem_ctx, struct sec_desc_buf);
634                         break;
635                 }
636                 
637                 status = dcerpc_srvsvc_NetShareSetInfo(p, mem_ctx, &r);
638                 if (!NT_STATUS_IS_OK(status)) {
639                         d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
640                                 r.in.level, r.in.share_name, nt_errstr(status));
641                         ret = False;
642                         continue;
643                 } else if (!W_ERROR_EQUAL(r.out.result, levels[i].expected)) {
644                         d_printf("NetShareSetInfo level %u on share '%s' failed - %s (expected %s)\n",
645                                 r.in.level, r.in.share_name, win_errstr(r.out.result),
646                                 win_errstr(levels[i].expected));
647                         ret = False;
648                         continue;
649                 }
650                 
651                 q.in.share_name = r.in.share_name;
652
653                 status = dcerpc_srvsvc_NetShareGetInfo(p, mem_ctx, &q);
654                 if (!NT_STATUS_IS_OK(status)) {
655                         d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
656                                 q.in.level, q.in.share_name, nt_errstr(status));
657                         ret = False;
658                         continue;
659                 } else if (!W_ERROR_EQUAL(q.out.result, WERR_OK)) {
660                         d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
661                                 q.in.level, q.in.share_name, win_errstr(q.out.result));
662                         ret = False;
663                         continue;
664                 }
665
666                 if (strcmp(q.out.info.info502->name, r.in.share_name) != 0) {
667                         ret = False;
668                 }
669                 switch (levels[i].level) {
670                 case 0:
671                         break;
672                 case 1:
673                         if (strcmp(q.out.info.info502->comment, "test comment 1") != 0)
674                                 ret = False;
675                         break;
676                 case 2:
677                         if (strcmp(q.out.info.info502->comment, "test comment 2") != 0)
678                                 ret = False;
679                         if (q.out.info.info2->max_users != 2)
680                                 ret = False;
681                         if (strcmp(q.out.info.info2->path, "C:\\") != 0)
682                                 ret = False;
683                         break;
684                 case 501:
685                         if (strcmp(q.out.info.info501->comment, "test comment 501") != 0)
686                                 ret = False;
687                         break;
688                 case 502:
689                         if (strcmp(q.out.info.info502->comment, "test comment 502") != 0)
690                                 ret = False;
691                         if (q.out.info.info2->max_users != 502)
692                                 ret = False;
693                         if (strcmp(q.out.info.info2->path, "C:\\") != 0)
694                                 ret = False;
695                         break;
696                 case 1004:
697                         if (strcmp(q.out.info.info502->comment, "test comment 1004") != 0)
698                                 ret = False;
699                         break;
700                 case 1005:
701                         break;
702                 case 1006:
703                         if (q.out.info.info2->max_users != 1006)
704                                 ret = False;
705                         break;
706 /*              case 1007:
707                         break;
708 */
709                 case 1501:
710                         break;
711                 }
712         }
713
714         d.in.share_name = r.in.share_name;
715         d.in.reserved = 0;
716
717         status = dcerpc_srvsvc_NetShareDel(p, mem_ctx, &d);
718         if (!NT_STATUS_IS_OK(status)) {
719                 d_printf("NetShareDel on share 'testshare502' failed - %s\n",
720                          nt_errstr(status));
721                 ret = False;
722         } else if (!W_ERROR_EQUAL(a.out.result, WERR_OK)) {
723                 d_printf("NetShareDel on share 'testshare502' failed - %s\n",
724                          win_errstr(d.out.result));
725                 ret = False;
726         }
727
728         return ret;
729 }
730
731 /**************************/
732 /* srvsvc_NetShare        */
733 /**************************/
734 static BOOL test_NetShareEnumAll(struct dcerpc_pipe *p, 
735                                  TALLOC_CTX *mem_ctx, BOOL admin)
736 {
737         NTSTATUS status;
738         struct srvsvc_NetShareEnumAll r;
739         struct srvsvc_NetShareCtr0 c0;
740         struct {
741                 uint32_t level;
742                 WERROR anon_status;
743                 WERROR admin_status;
744         } levels[] = {
745                  { 0,   WERR_OK,                WERR_OK },
746                  { 1,   WERR_OK,                WERR_OK },
747                  { 2,   WERR_ACCESS_DENIED,     WERR_OK },
748                  { 501, WERR_ACCESS_DENIED,     WERR_OK },
749                  { 502, WERR_ACCESS_DENIED,     WERR_OK },
750         };
751         int i;
752         BOOL ret = True;
753         uint32_t resume_handle;
754
755         ZERO_STRUCT(c0);
756
757         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
758         r.in.ctr.ctr0 = &c0;
759         r.in.max_buffer = (uint32_t)-1;
760         r.in.resume_handle = &resume_handle;
761         r.out.resume_handle = &resume_handle;
762
763         for (i=0;i<ARRAY_SIZE(levels);i++) {
764                 int j;
765                 WERROR expected;
766
767                 r.in.level = levels[i].level;
768                 expected = levels[i].anon_status;
769                 if (admin) expected = levels[i].admin_status;
770
771                 ZERO_STRUCT(r.out);
772                 resume_handle = 0;
773
774                 d_printf("testing NetShareEnumAll level %u\n", r.in.level);
775                 status = dcerpc_srvsvc_NetShareEnumAll(p, mem_ctx, &r);
776                 if (!NT_STATUS_IS_OK(status)) {
777                         d_printf("NetShareEnumAll level %u failed - %s\n", r.in.level, nt_errstr(status));
778                         ret = False;
779                         continue;
780                 }
781                 if (!W_ERROR_EQUAL(r.out.result, expected)) {
782                         d_printf("NetShareEnumAll level %u failed - %s (expected %s)\n",
783                                 r.in.level, win_errstr(r.out.result),
784                                 win_errstr(expected));
785                         continue;
786                 }
787
788                 /* call srvsvc_NetShareGetInfo for each returned share */
789                 if (r.in.level == 2 && r.out.ctr.ctr2) {
790                         for (j=0;j<r.out.ctr.ctr2->count;j++) {
791                                 const char *name;
792                                 name = r.out.ctr.ctr2->array[j].name;
793                                 if (!test_NetShareGetInfo(p, mem_ctx, name, admin)) {
794                                         ret = False;
795                                 }
796                         }
797                 }
798         }
799
800         return ret;
801 }
802
803 static BOOL test_NetShareEnum(struct dcerpc_pipe *p, 
804                               TALLOC_CTX *mem_ctx, BOOL admin)
805 {
806         NTSTATUS status;
807         struct srvsvc_NetShareEnum r;
808         struct srvsvc_NetShareCtr0 c0;
809         struct {
810                 uint32_t level;
811                 WERROR anon_status;
812                 WERROR admin_status;
813         } levels[] = {
814                  { 0,   WERR_OK,                WERR_OK },
815                  { 1,   WERR_OK,                WERR_OK },
816                  { 2,   WERR_ACCESS_DENIED,     WERR_OK },
817                  { 501, WERR_UNKNOWN_LEVEL,     WERR_UNKNOWN_LEVEL },
818                  { 502, WERR_ACCESS_DENIED,     WERR_OK },
819         };
820         int i;
821         BOOL ret = True;
822
823         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
824         r.in.ctr.ctr0 = &c0;
825         r.in.ctr.ctr0->count = 0;
826         r.in.ctr.ctr0->array = NULL;
827         r.in.max_buffer = (uint32_t)-1;
828         r.in.resume_handle = NULL;
829
830         for (i=0;i<ARRAY_SIZE(levels);i++) {
831                 WERROR expected;
832
833                 r.in.level = levels[i].level;
834                 expected = levels[i].anon_status;
835                 if (admin) expected = levels[i].admin_status;
836
837                 ZERO_STRUCT(r.out);
838
839                 d_printf("testing NetShareEnum level %u\n", r.in.level);
840                 status = dcerpc_srvsvc_NetShareEnum(p, mem_ctx, &r);
841                 if (!NT_STATUS_IS_OK(status)) {
842                         d_printf("NetShareEnum level %u failed - %s\n", r.in.level, nt_errstr(status));
843                         ret = False;
844                         continue;
845                 }
846                 if (!W_ERROR_EQUAL(r.out.result, expected)) {
847                         d_printf("NetShareEnum level %u failed - %s (expected %s)\n",
848                                 r.in.level, win_errstr(r.out.result),
849                                 win_errstr(expected));
850                         continue;
851                 }
852         }
853
854         return ret;
855 }
856
857 /**************************/
858 /* srvsvc_NetSrv          */
859 /**************************/
860 static BOOL test_NetSrvGetInfo(struct dcerpc_pipe *p, 
861                                  TALLOC_CTX *mem_ctx)
862 {
863         NTSTATUS status;
864         struct srvsvc_NetSrvGetInfo r;
865         struct srvsvc_NetSrvInfo503 i503;
866         uint32_t levels[] = {100, 101, 102, 502, 503};
867         int i;
868         BOOL ret = True;
869         uint32_t resume_handle;
870
871         ZERO_STRUCT(i503);
872
873         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
874
875         for (i=0;i<ARRAY_SIZE(levels);i++) {
876                 ZERO_STRUCT(r.out);
877                 resume_handle = 0;
878                 r.in.level = levels[i];
879                 d_printf("testing NetSrvGetInfo level %u\n", r.in.level);
880                 status = dcerpc_srvsvc_NetSrvGetInfo(p, mem_ctx, &r);
881                 if (!NT_STATUS_IS_OK(status)) {
882                         d_printf("NetSrvGetInfo level %u failed - %s\n", r.in.level, nt_errstr(status));
883                         ret = False;
884                         continue;
885                 }
886                 if (!W_ERROR_IS_OK(r.out.result)) {
887                         d_printf("NetSrvGetInfo level %u failed - %s\n", r.in.level, win_errstr(r.out.result));
888                         continue;
889                 }
890         }
891
892         return ret;
893 }
894
895 /**************************/
896 /* srvsvc_NetDisk         */
897 /**************************/
898 static BOOL test_NetDiskEnum(struct dcerpc_pipe *p, 
899                            TALLOC_CTX *mem_ctx)
900 {
901         NTSTATUS status;
902         struct srvsvc_NetDiskEnum r;
903         uint32_t levels[] = {0};
904         int i;
905         BOOL ret = True;
906         uint32_t resume_handle=0;
907
908         ZERO_STRUCT(r.in);
909         r.in.server_unc = NULL;
910         r.in.resume_handle = &resume_handle;
911
912         for (i=0;i<ARRAY_SIZE(levels);i++) {
913                 ZERO_STRUCT(r.out);
914                 r.in.level = levels[i];
915                 d_printf("testing NetDiskEnum level %u\n", r.in.level);
916                 status = dcerpc_srvsvc_NetDiskEnum(p, mem_ctx, &r);
917                 if (!NT_STATUS_IS_OK(status)) {
918                         NDR_PRINT_OUT_DEBUG(srvsvc_NetDiskEnum, &r);
919                         d_printf("NetDiskEnum level %u failed - %s\n", r.in.level, nt_errstr(status));
920                         ret = False;
921                         continue;
922                 }
923                 if (!W_ERROR_IS_OK(r.out.result)) {
924                         d_printf("NetDiskEnum level %u failed - %s\n", r.in.level, win_errstr(r.out.result));
925                         continue;
926                 }
927         }
928
929         return ret;
930 }
931
932 /**************************/
933 /* srvsvc_NetTransport    */
934 /**************************/
935 static BOOL test_NetTransportEnum(struct dcerpc_pipe *p, 
936                            TALLOC_CTX *mem_ctx)
937 {
938         NTSTATUS status;
939         struct srvsvc_NetTransportEnum r;
940         struct srvsvc_NetTransportCtr0 c0;
941         uint32_t levels[] = {0, 1};
942         int i;
943         BOOL ret = True;
944
945         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
946         r.in.transports.ctr0 = &c0;
947         r.in.transports.ctr0->count = 0;
948         r.in.transports.ctr0->array = NULL;
949         r.in.max_buffer = (uint32_t)-1;
950         r.in.resume_handle = NULL;
951
952         for (i=0;i<ARRAY_SIZE(levels);i++) {
953                 ZERO_STRUCT(r.out);
954                 r.in.level = levels[i];
955                 d_printf("testing NetTransportEnum level %u\n", r.in.level);
956                 status = dcerpc_srvsvc_NetTransportEnum(p, mem_ctx, &r);
957                 if (!NT_STATUS_IS_OK(status)) {
958                         d_printf("NetTransportEnum level %u failed - %s\n", r.in.level, nt_errstr(status));
959                         ret = False;
960                         continue;
961                 }
962                 if (!W_ERROR_IS_OK(r.out.result)) {
963                         d_printf("NetTransportEnum level %u failed - %s\n", r.in.level, win_errstr(r.out.result));
964                         continue;
965                 }
966         }
967
968         return ret;
969 }
970
971 /**************************/
972 /* srvsvc_NetRemoteTOD    */
973 /**************************/
974 static BOOL test_NetRemoteTOD(struct dcerpc_pipe *p, 
975                            TALLOC_CTX *mem_ctx)
976 {
977         NTSTATUS status;
978         struct srvsvc_NetRemoteTOD r;
979         BOOL ret = True;
980
981         r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
982
983         ZERO_STRUCT(r.out);
984         d_printf("testing NetRemoteTOD\n");
985         status = dcerpc_srvsvc_NetRemoteTOD(p, mem_ctx, &r);
986         if (!NT_STATUS_IS_OK(status)) {
987                 d_printf("NetRemoteTOD failed - %s\n", nt_errstr(status));
988                 ret = False;
989         }
990         if (!W_ERROR_IS_OK(r.out.result)) {
991                 d_printf("NetRemoteTOD failed - %s\n", win_errstr(r.out.result));
992         }
993
994         return ret;
995 }
996
997 /**************************/
998 /* srvsvc_NetName         */
999 /**************************/
1000
1001 static BOOL test_NetNameValidate(struct dcerpc_pipe *p,
1002                                  TALLOC_CTX *mem_ctx)
1003 {
1004         NTSTATUS status;
1005         struct srvsvc_NetNameValidate r;
1006         char *invalidc;
1007         char *name;
1008         int i, n, min, max;
1009
1010         r.in.server_unc = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1011         r.in.flags = 0x0;
1012
1013         d_printf("testing NetNameValidate\n");
1014
1015         /* valid path types only between 1 and 13 */
1016         for (i = 1; i < 14; i++) {
1017
1018 again:
1019                 /* let's limit ourselves to a maximum of 4096 bytes */
1020                 r.in.name = name = talloc_array(mem_ctx, char, 4097);
1021                 max = 4096;
1022                 min = 0;
1023                 n = max;
1024
1025                 while (1) {
1026
1027                         /* Find maximum length accepted by this type */
1028                         ZERO_STRUCT(r.out);
1029                         r.in.name_type = i;
1030                         memset(name, 'A', n);
1031                         name[n] = '\0';
1032
1033                         status = dcerpc_srvsvc_NetNameValidate(p, mem_ctx, &r);
1034                         if (!NT_STATUS_IS_OK(status)) {
1035                                 d_printf("NetNameValidate failed while checking maximum size (%s)\n",
1036                                                 nt_errstr(status));
1037                                 break;
1038                         }
1039
1040                         if (W_ERROR_IS_OK(r.out.result)) {
1041                                 min = n;
1042                                 n += (max - min + 1)/2;
1043                                 continue;
1044                                 
1045                         } else {
1046                                 if ((min + 1) >= max) break; /* found it */
1047                                 
1048                                 max = n;
1049                                 n -= (max - min)/2;
1050                                 continue;
1051                         }
1052                 }
1053
1054                 talloc_free(name);
1055
1056                 d_printf("Maximum length for type %2d, flags %08x: %d\n", i, r.in.flags, max);
1057
1058                 /* find invalid chars for this type check only ASCII between 0x20 and 0x7e */
1059
1060                 invalidc = talloc_strdup(mem_ctx, "");
1061
1062                 for (n = 0x20; n < 0x7e; n++) {
1063                         r.in.name = name = talloc_asprintf(mem_ctx, "%c", (char)n);
1064
1065                         status = dcerpc_srvsvc_NetNameValidate(p, mem_ctx, &r);
1066                         if (!NT_STATUS_IS_OK(status)) {
1067                                 d_printf("NetNameValidate failed while checking valid chars (%s)\n",
1068                                                 nt_errstr(status));
1069                                 break;
1070                         }
1071
1072                         if (!W_ERROR_IS_OK(r.out.result)) {
1073                                 invalidc = talloc_asprintf_append(invalidc, "%c", (char)n);
1074                         }
1075
1076                         talloc_free(name);
1077                 }
1078
1079                 d_printf(" Invalid chars for type %2d, flags %08x: \"%s\"\n", i, r.in.flags, invalidc);
1080
1081                 /* only two values are accepted for flags: 0x0 and 0x80000000 */
1082                 if (r.in.flags == 0x0) {
1083                         r.in.flags = 0x80000000;
1084                         goto again;
1085                 }
1086
1087                 r.in.flags = 0x0;
1088         }
1089
1090         return True;
1091 }
1092
1093 BOOL torture_rpc_srvsvc(struct torture_context *torture)
1094 {
1095         NTSTATUS status;
1096         struct dcerpc_pipe *p;
1097         TALLOC_CTX *mem_ctx;
1098         BOOL ret = True;
1099         const char *binding = torture_setting_string(torture, "binding", NULL);
1100         struct cli_credentials *anon_credentials;
1101
1102         mem_ctx = talloc_init("torture_rpc_srvsvc");
1103
1104         status = torture_rpc_connection(mem_ctx, &p, &ndr_table_srvsvc);
1105         if (!NT_STATUS_IS_OK(status)) {
1106                 talloc_free(mem_ctx);
1107                 return False;
1108         }
1109
1110         ret &= test_NetCharDevEnum(p, mem_ctx);
1111         ret &= test_NetCharDevQEnum(p, mem_ctx);
1112         ret &= test_NetConnEnum(p, mem_ctx);
1113         ret &= test_NetFileEnum(p, mem_ctx);
1114         ret &= test_NetSessEnum(p, mem_ctx);
1115         ret &= test_NetShareEnumAll(p, mem_ctx, True);
1116         ret &= test_NetSrvGetInfo(p, mem_ctx);
1117         ret &= test_NetDiskEnum(p, mem_ctx);
1118         ret &= test_NetTransportEnum(p, mem_ctx);
1119         ret &= test_NetRemoteTOD(p, mem_ctx);
1120         ret &= test_NetShareEnum(p, mem_ctx, True);
1121         ret &= test_NetShareGetInfo(p, mem_ctx, "ADMIN$", True);
1122         ret &= test_NetShareAddSetDel(p, mem_ctx);
1123         ret &= test_NetNameValidate(p, mem_ctx);
1124         
1125         status = torture_rpc_connection(mem_ctx, &p, &ndr_table_srvsvc);
1126
1127         if (!binding) {
1128                 d_printf("You must specify a ncacn binding string\n");
1129                 return False;
1130         }
1131
1132         anon_credentials = cli_credentials_init_anon(mem_ctx);
1133
1134         status = dcerpc_pipe_connect(mem_ctx, 
1135                                      &p, binding, &ndr_table_srvsvc,
1136                                      anon_credentials, NULL);
1137         if (!NT_STATUS_IS_OK(status)) {
1138                 talloc_free(mem_ctx);
1139                 return False;
1140         }
1141
1142         ret &= test_NetShareEnumAll(p, mem_ctx, False);
1143         ret &= test_NetShareEnum(p, mem_ctx, False);
1144         ret &= test_NetShareGetInfo(p, mem_ctx, "ADMIN$", False);
1145
1146         talloc_free(mem_ctx);
1147
1148         return ret;
1149 }