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