s4-srvsvc: merge srvsvc_NetShareCheck 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         struct {
388                 uint32_t level;
389                 WERROR anon_status;
390                 WERROR admin_status;
391         } levels[] = {
392                  { 0,           WERR_OK,                WERR_OK },
393                  { 1,           WERR_OK,                WERR_OK },
394                  { 2,           WERR_ACCESS_DENIED,     WERR_OK },
395                  { 501,         WERR_OK,                WERR_OK },
396                  { 502,         WERR_ACCESS_DENIED,     WERR_OK },
397                  { 1005,        WERR_OK,                WERR_OK },
398         };
399         int i;
400
401         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
402         r.in.share_name = sharename;
403
404         for (i=0;i<ARRAY_SIZE(levels);i++) {
405                 WERROR expected;
406
407                 r.in.level = levels[i].level;
408                 expected = levels[i].anon_status;
409                 if (admin) expected = levels[i].admin_status;
410                 ZERO_STRUCT(r.out);
411
412                 torture_comment(tctx, "testing NetShareGetInfo level %u on share '%s'\n", 
413                        r.in.level, r.in.share_name);
414
415                 status = dcerpc_srvsvc_NetShareGetInfo(p, tctx, &r);
416                 torture_assert_ntstatus_ok(tctx, status, "NetShareGetInfo failed");
417                 torture_assert_werr_equal(tctx, r.out.result, expected, "NetShareGetInfo failed");
418
419                 if (r.in.level != 2) continue;
420                 if (!r.out.info.info2 || !r.out.info.info2->path) continue;
421                 if (!test_NetShareCheck(p, tctx, r.out.info.info2->path)) {
422                         return false;
423                 }
424         }
425
426         return true;
427 }
428
429 static bool test_NetShareGetInfoAdminFull(struct torture_context *tctx, 
430                                           struct dcerpc_pipe *p)
431 {
432         return test_NetShareGetInfo(tctx, p, "ADMIN$", true);
433 }
434
435 static bool test_NetShareGetInfoAdminAnon(struct torture_context *tctx, 
436                                           struct dcerpc_pipe *p)
437 {
438         return test_NetShareGetInfo(tctx, p, "ADMIN$", false);
439 }
440
441 static bool test_NetShareAddSetDel(struct torture_context *tctx, 
442                                    struct dcerpc_pipe *p)
443 {
444         NTSTATUS status;
445         struct srvsvc_NetShareAdd a;
446         struct srvsvc_NetShareSetInfo r;
447         struct srvsvc_NetShareGetInfo q;
448         struct srvsvc_NetShareDel d;
449         struct sec_desc_buf sd_buf;
450         struct {
451                 uint32_t level;
452                 WERROR expected;
453         } levels[] = {
454                  { 0,           WERR_UNKNOWN_LEVEL },
455                  { 1,           WERR_OK },
456                  { 2,           WERR_OK },
457                  { 501,         WERR_UNKNOWN_LEVEL },
458                  { 502,         WERR_OK },
459                  { 1004,        WERR_OK },
460                  { 1005,        WERR_OK },
461                  { 1006,        WERR_OK },
462 /*               { 1007,        WERR_OK }, */
463                  { 1501,        WERR_OK },
464         };
465         int i;
466
467         a.in.server_unc = r.in.server_unc = q.in.server_unc = d.in.server_unc =
468                 talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
469         r.in.share_name = talloc_strdup(tctx, "testshare");
470
471         a.in.level = 2;
472         a.in.info.info2 = talloc(tctx, struct srvsvc_NetShareInfo2);
473         a.in.info.info2->name = r.in.share_name;
474         a.in.info.info2->type = STYPE_DISKTREE;
475         a.in.info.info2->comment = talloc_strdup(tctx, "test comment");
476         a.in.info.info2->permissions = 123434566;
477         a.in.info.info2->max_users = -1;
478         a.in.info.info2->current_users = 0;
479         a.in.info.info2->path = talloc_strdup(tctx, "C:\\");
480         a.in.info.info2->password = NULL;
481
482         a.in.parm_error = NULL;
483
484         status = dcerpc_srvsvc_NetShareAdd(p, tctx, &a);
485         torture_assert_ntstatus_ok(tctx, status, "NetShareAdd level 2 on share 'testshare' failed");
486         torture_assert_werr_ok(tctx, a.out.result, "NetShareAdd level 2 on share 'testshare' failed");
487
488         r.in.parm_error = NULL;
489
490         q.in.level = 502;
491
492         for (i = 0; i < ARRAY_SIZE(levels); i++) {
493
494                 r.in.level = levels[i].level;
495                 ZERO_STRUCT(r.out);
496
497                 torture_comment(tctx, "testing NetShareSetInfo level %u on share '%s'\n", 
498                        r.in.level, r.in.share_name);
499
500                 switch (levels[i].level) {
501                 case 0:
502                         r.in.info.info0 = talloc(tctx, struct srvsvc_NetShareInfo0);
503                         r.in.info.info0->name = r.in.share_name;
504                         break;
505                 case 1:
506                         r.in.info.info1 = talloc(tctx, struct srvsvc_NetShareInfo1);
507                         r.in.info.info1->name = r.in.share_name;
508                         r.in.info.info1->type = STYPE_DISKTREE;
509                         r.in.info.info1->comment = talloc_strdup(tctx, "test comment 1");
510                         break;
511                 case 2: 
512                         r.in.info.info2 = talloc(tctx, struct srvsvc_NetShareInfo2);
513                         r.in.info.info2->name = r.in.share_name;
514                         r.in.info.info2->type = STYPE_DISKTREE;
515                         r.in.info.info2->comment = talloc_strdup(tctx, "test comment 2");
516                         r.in.info.info2->permissions = 0;
517                         r.in.info.info2->max_users = 2;
518                         r.in.info.info2->current_users = 1;
519                         r.in.info.info2->path = talloc_strdup(tctx, "::BLaH::"); /* "C:\\"); */
520                         r.in.info.info2->password = NULL;
521                         break;
522                 case 501:
523                         r.in.info.info501 = talloc(tctx, struct srvsvc_NetShareInfo501);
524                         r.in.info.info501->name = r.in.share_name;
525                         r.in.info.info501->type = STYPE_DISKTREE;
526                         r.in.info.info501->comment = talloc_strdup(tctx, "test comment 501");
527                         r.in.info.info501->csc_policy = 0;
528                         break;
529                 case 502:
530                         ZERO_STRUCT(sd_buf);
531                         r.in.info.info502 = talloc(tctx, struct srvsvc_NetShareInfo502);
532                         r.in.info.info502->name = r.in.share_name;
533                         r.in.info.info502->type = STYPE_DISKTREE;
534                         r.in.info.info502->comment = talloc_strdup(tctx, "test comment 502");
535                         r.in.info.info502->permissions = 0;
536                         r.in.info.info502->max_users = 502;
537                         r.in.info.info502->current_users = 1;
538                         r.in.info.info502->path = talloc_strdup(tctx, "C:\\");
539                         r.in.info.info502->password = NULL;
540                         r.in.info.info502->sd_buf = sd_buf;
541                         break;
542                 case 1004:
543                         r.in.info.info1004 = talloc(tctx, struct srvsvc_NetShareInfo1004);
544                         r.in.info.info1004->comment = talloc_strdup(tctx, "test comment 1004");
545                         break;
546                 case 1005:
547                         r.in.info.info1005 = talloc(tctx, struct srvsvc_NetShareInfo1005);
548                         r.in.info.info1005->dfs_flags = 0;
549                         break;
550                 case 1006:
551                         r.in.info.info1006 = talloc(tctx, struct srvsvc_NetShareInfo1006);
552                         r.in.info.info1006->max_users = 1006;
553                         break;
554 /*              case 1007:
555                         r.in.info.info1007 = talloc(tctx, struct srvsvc_NetShareInfo1007);
556                         r.in.info.info1007->flags = 0;
557                         r.in.info.info1007->alternate_directory_name = talloc_strdup(tctx, "test");
558                         break;
559 */
560                 case 1501:
561                         r.in.info.info1501 = talloc_zero(tctx, struct sec_desc_buf);
562                         break;
563                 }
564                 
565                 status = dcerpc_srvsvc_NetShareSetInfo(p, tctx, &r);
566                 torture_assert_ntstatus_ok(tctx, status, "NetShareGetInfo failed");
567                 torture_assert_werr_equal(tctx, r.out.result, levels[i].expected, "NetShareSetInfo failed");
568                 
569                 q.in.share_name = r.in.share_name;
570
571                 status = dcerpc_srvsvc_NetShareGetInfo(p, tctx, &q);
572                 torture_assert_ntstatus_ok(tctx, status, "NetShareGetInfo failed");
573                 torture_assert_werr_ok(tctx, q.out.result, "NetShareGetInfo failed");
574
575                 torture_assert_str_equal(tctx, q.out.info.info502->name, r.in.share_name, 
576                                          "share name invalid");
577
578                 switch (levels[i].level) {
579                 case 0:
580                         break;
581                 case 1:
582                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 1", "comment");
583                         break;
584                 case 2:
585                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 2", "comment");
586                         torture_assert_int_equal(tctx, q.out.info.info2->max_users, 2, "max users");
587                         torture_assert_str_equal(tctx, q.out.info.info2->path, "C:\\", "path");
588                         break;
589                 case 501:
590                         torture_assert_str_equal(tctx, q.out.info.info501->comment, "test comment 501", "comment");
591                         break;
592                 case 502:
593                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 502", "comment");
594                         torture_assert_int_equal(tctx, q.out.info.info2->max_users, 502, "max users");
595                         torture_assert_str_equal(tctx, q.out.info.info2->path, "C:\\", "path");
596                         break;
597                 case 1004:
598                         torture_assert_str_equal(tctx, q.out.info.info502->comment, "test comment 1004", 
599                                                  "comment");
600                         break;
601                 case 1005:
602                         break;
603                 case 1006:
604                         torture_assert_int_equal(tctx, q.out.info.info2->max_users, 1006, "Max users");
605                         break;
606 /*              case 1007:
607                         break;
608 */
609                 case 1501:
610                         break;
611                 }
612         }
613
614         d.in.share_name = r.in.share_name;
615         d.in.reserved = 0;
616
617         status = dcerpc_srvsvc_NetShareDel(p, tctx, &d);
618         torture_assert_ntstatus_ok(tctx, status, "NetShareDel on share 'testshare502' failed");
619         torture_assert_werr_ok(tctx, a.out.result, "NetShareDel on share 'testshare502' failed");
620
621         return true;
622 }
623
624 /**************************/
625 /* srvsvc_NetShare        */
626 /**************************/
627 static bool test_NetShareEnumAll(struct torture_context *tctx, 
628                                  struct dcerpc_pipe *p, 
629                                  bool admin)
630 {
631         NTSTATUS status;
632         struct srvsvc_NetShareEnumAll r;
633         struct srvsvc_NetShareCtr0 c0;
634         struct {
635                 uint32_t level;
636                 WERROR anon_status;
637                 WERROR admin_status;
638         } levels[] = {
639                  { 0,   WERR_OK,                WERR_OK },
640                  { 1,   WERR_OK,                WERR_OK },
641                  { 2,   WERR_ACCESS_DENIED,     WERR_OK },
642                  { 501, WERR_ACCESS_DENIED,     WERR_OK },
643                  { 502, WERR_ACCESS_DENIED,     WERR_OK },
644         };
645         int i;
646         uint32_t resume_handle;
647
648         ZERO_STRUCT(c0);
649
650         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
651         r.in.ctr.ctr0 = &c0;
652         r.in.max_buffer = (uint32_t)-1;
653         r.in.resume_handle = &resume_handle;
654         r.out.resume_handle = &resume_handle;
655
656         for (i=0;i<ARRAY_SIZE(levels);i++) {
657                 int j;
658                 WERROR expected;
659
660                 r.in.level = levels[i].level;
661                 expected = levels[i].anon_status;
662                 if (admin) expected = levels[i].admin_status;
663
664                 ZERO_STRUCT(r.out);
665                 resume_handle = 0;
666
667                 torture_comment(tctx, "testing NetShareEnumAll level %u\n", r.in.level);
668                 status = dcerpc_srvsvc_NetShareEnumAll(p, tctx, &r);
669                 torture_assert_ntstatus_ok(tctx, status, "NetShareEnumAll failed");
670                 torture_assert_werr_equal(tctx, r.out.result, expected, "NetShareEnumAll failed");
671
672                 /* call srvsvc_NetShareGetInfo for each returned share */
673                 if (r.in.level == 2 && r.out.ctr.ctr2) {
674                         for (j=0;j<r.out.ctr.ctr2->count;j++) {
675                                 const char *name;
676                                 name = r.out.ctr.ctr2->array[j].name;
677                                 if (!test_NetShareGetInfo(tctx, p, name, admin)) {
678                                         return false;
679                                 }
680                         }
681                 }
682         }
683
684         return true;
685 }
686
687 static bool test_NetShareEnumAllFull(struct torture_context *tctx,
688                               struct dcerpc_pipe *p)
689 {
690         return test_NetShareEnumAll(tctx, p, true);
691 }
692
693 static bool test_NetShareEnumAllAnon(struct torture_context *tctx,
694                               struct dcerpc_pipe *p)
695 {
696         return test_NetShareEnumAll(tctx, p, false);
697 }
698
699 static bool test_NetShareEnum(struct torture_context *tctx,
700                               struct dcerpc_pipe *p, bool admin)
701 {
702         NTSTATUS status;
703         struct srvsvc_NetShareEnum r;
704         struct srvsvc_NetShareCtr0 c0;
705         struct {
706                 uint32_t level;
707                 WERROR anon_status;
708                 WERROR admin_status;
709         } levels[] = {
710                  { 0,   WERR_OK,                WERR_OK },
711                  { 1,   WERR_OK,                WERR_OK },
712                  { 2,   WERR_ACCESS_DENIED,     WERR_OK },
713                  { 501, WERR_UNKNOWN_LEVEL,     WERR_UNKNOWN_LEVEL },
714                  { 502, WERR_ACCESS_DENIED,     WERR_OK },
715         };
716         int i;
717
718         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
719         r.in.ctr.ctr0 = &c0;
720         r.in.ctr.ctr0->count = 0;
721         r.in.ctr.ctr0->array = NULL;
722         r.in.max_buffer = (uint32_t)-1;
723         r.in.resume_handle = NULL;
724
725         for (i=0;i<ARRAY_SIZE(levels);i++) {
726                 WERROR expected;
727
728                 r.in.level = levels[i].level;
729                 expected = levels[i].anon_status;
730                 if (admin) expected = levels[i].admin_status;
731
732                 ZERO_STRUCT(r.out);
733
734                 torture_comment(tctx, "testing NetShareEnum level %u\n", r.in.level);
735                 status = dcerpc_srvsvc_NetShareEnum(p, tctx, &r);
736                 torture_assert_ntstatus_ok(tctx, status, "NetShareEnum failed");
737                 torture_assert_werr_equal(tctx, r.out.result, expected, "NetShareEnum failed");
738         }
739
740         return true;
741 }
742
743 static bool test_NetShareEnumFull(struct torture_context *tctx,
744                                   struct dcerpc_pipe *p)
745 {
746         return test_NetShareEnum(tctx, p, true);
747 }
748
749 static bool test_NetShareEnumAnon(struct torture_context *tctx,
750                                   struct dcerpc_pipe *p)
751 {
752         return test_NetShareEnum(tctx, p, false);
753 }
754
755 /**************************/
756 /* srvsvc_NetSrv          */
757 /**************************/
758 static bool test_NetSrvGetInfo(struct torture_context *tctx, 
759                                struct dcerpc_pipe *p)
760 {
761         NTSTATUS status;
762         struct srvsvc_NetSrvGetInfo r;
763         struct srvsvc_NetSrvInfo503 i503;
764         uint32_t levels[] = {100, 101, 102, 502, 503};
765         int i;
766         uint32_t resume_handle;
767
768         ZERO_STRUCT(i503);
769
770         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
771
772         for (i=0;i<ARRAY_SIZE(levels);i++) {
773                 ZERO_STRUCT(r.out);
774                 resume_handle = 0;
775                 r.in.level = levels[i];
776                 torture_comment(tctx, "testing NetSrvGetInfo level %u\n", r.in.level);
777                 status = dcerpc_srvsvc_NetSrvGetInfo(p, tctx, &r);
778                 torture_assert_ntstatus_ok(tctx, status, "NetSrvGetInfo failed");
779                 if (!W_ERROR_IS_OK(r.out.result)) {
780                         torture_comment(tctx, "NetSrvGetInfo failed: %s\n", win_errstr(r.out.result));
781                 }
782         }
783
784         return true;
785 }
786
787 /**************************/
788 /* srvsvc_NetDisk         */
789 /**************************/
790 static bool test_NetDiskEnum(struct torture_context *tctx, 
791                              struct dcerpc_pipe *p)
792 {
793         NTSTATUS status;
794         struct srvsvc_NetDiskEnum r;
795         uint32_t levels[] = {0};
796         int i;
797         uint32_t resume_handle=0;
798
799         ZERO_STRUCT(r.in);
800         r.in.server_unc = NULL;
801         r.in.resume_handle = &resume_handle;
802
803         for (i=0;i<ARRAY_SIZE(levels);i++) {
804                 ZERO_STRUCT(r.out);
805                 r.in.level = levels[i];
806                 torture_comment(tctx, "testing NetDiskEnum level %u\n", r.in.level);
807                 status = dcerpc_srvsvc_NetDiskEnum(p, tctx, &r);
808                 torture_assert_ntstatus_ok(tctx, status, "NetDiskEnum failed");
809                 torture_assert_werr_ok(tctx, r.out.result, "NetDiskEnum failed");
810         }
811
812         return true;
813 }
814
815 /**************************/
816 /* srvsvc_NetTransport    */
817 /**************************/
818 static bool test_NetTransportEnum(struct torture_context *tctx, 
819                                   struct dcerpc_pipe *p)
820 {
821         NTSTATUS status;
822         struct srvsvc_NetTransportEnum r;
823         struct srvsvc_NetTransportCtr0 c0;
824         uint32_t levels[] = {0, 1};
825         int i;
826
827         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s", dcerpc_server_name(p));
828         r.in.transports.ctr0 = &c0;
829         r.in.transports.ctr0->count = 0;
830         r.in.transports.ctr0->array = NULL;
831         r.in.max_buffer = (uint32_t)-1;
832         r.in.resume_handle = NULL;
833
834         for (i=0;i<ARRAY_SIZE(levels);i++) {
835                 ZERO_STRUCT(r.out);
836                 r.in.level = levels[i];
837                 torture_comment(tctx, "testing NetTransportEnum level %u\n", r.in.level);
838                 status = dcerpc_srvsvc_NetTransportEnum(p, tctx, &r);
839                 torture_assert_ntstatus_ok(tctx, status, "NetTransportEnum failed");
840                 if (!W_ERROR_IS_OK(r.out.result)) {
841                         torture_comment(tctx, "unexpected result: %s\n", win_errstr(r.out.result));
842                 }
843         }
844
845         return true;
846 }
847
848 /**************************/
849 /* srvsvc_NetRemoteTOD    */
850 /**************************/
851 static bool test_NetRemoteTOD(struct torture_context *tctx, 
852                               struct dcerpc_pipe *p)
853 {
854         NTSTATUS status;
855         struct srvsvc_NetRemoteTOD r;
856         struct srvsvc_NetRemoteTODInfo *info = NULL;
857
858         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
859         r.out.info = &info;
860
861         torture_comment(tctx, "testing NetRemoteTOD\n");
862         status = dcerpc_srvsvc_NetRemoteTOD(p, tctx, &r);
863         torture_assert_ntstatus_ok(tctx, status, "NetRemoteTOD failed");
864         torture_assert_werr_ok(tctx, r.out.result, "NetRemoteTOD failed");
865
866         return true;
867 }
868
869 /**************************/
870 /* srvsvc_NetName         */
871 /**************************/
872
873 static bool test_NetNameValidate(struct torture_context *tctx, 
874                                                                  struct dcerpc_pipe *p)
875 {
876         NTSTATUS status;
877         struct srvsvc_NetNameValidate r;
878         char *invalidc;
879         char *name;
880         int i, n, min, max;
881
882         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
883         r.in.flags = 0x0;
884
885         d_printf("testing NetNameValidate\n");
886
887         /* valid path types only between 1 and 13 */
888         for (i = 1; i < 14; i++) {
889
890 again:
891                 /* let's limit ourselves to a maximum of 4096 bytes */
892                 r.in.name = name = talloc_array(tctx, char, 4097);
893                 max = 4096;
894                 min = 0;
895                 n = max;
896
897                 while (1) {
898
899                         /* Find maximum length accepted by this type */
900                         ZERO_STRUCT(r.out);
901                         r.in.name_type = i;
902                         memset(name, 'A', n);
903                         name[n] = '\0';
904
905                         status = dcerpc_srvsvc_NetNameValidate(p, tctx, &r);
906                         if (!NT_STATUS_IS_OK(status)) {
907                                 d_printf("NetNameValidate failed while checking maximum size (%s)\n",
908                                                 nt_errstr(status));
909                                 break;
910                         }
911
912                         if (W_ERROR_IS_OK(r.out.result)) {
913                                 min = n;
914                                 n += (max - min + 1)/2;
915                                 continue;
916                                 
917                         } else {
918                                 if ((min + 1) >= max) break; /* found it */
919                                 
920                                 max = n;
921                                 n -= (max - min)/2;
922                                 continue;
923                         }
924                 }
925
926                 talloc_free(name);
927
928                 d_printf("Maximum length for type %2d, flags %08x: %d\n", i, r.in.flags, max);
929
930                 /* find invalid chars for this type check only ASCII between 0x20 and 0x7e */
931
932                 invalidc = talloc_strdup(tctx, "");
933
934                 for (n = 0x20; n < 0x7e; n++) {
935                         r.in.name = name = talloc_asprintf(tctx, "%c", (char)n);
936
937                         status = dcerpc_srvsvc_NetNameValidate(p, tctx, &r);
938                         if (!NT_STATUS_IS_OK(status)) {
939                                 d_printf("NetNameValidate failed while checking valid chars (%s)\n",
940                                                 nt_errstr(status));
941                                 break;
942                         }
943
944                         if (!W_ERROR_IS_OK(r.out.result)) {
945                                 invalidc = talloc_asprintf_append_buffer(invalidc, "%c", (char)n);
946                         }
947
948                         talloc_free(name);
949                 }
950
951                 d_printf(" Invalid chars for type %2d, flags %08x: \"%s\"\n", i, r.in.flags, invalidc);
952
953                 /* only two values are accepted for flags: 0x0 and 0x80000000 */
954                 if (r.in.flags == 0x0) {
955                         r.in.flags = 0x80000000;
956                         goto again;
957                 }
958
959                 r.in.flags = 0x0;
960         }
961
962         return true;
963 }
964
965 struct torture_suite *torture_rpc_srvsvc(TALLOC_CTX *mem_ctx)
966 {
967         struct torture_suite *suite = torture_suite_create(mem_ctx, "SRVSVC");
968         struct torture_rpc_tcase *tcase;
969         struct torture_test *test;
970
971         tcase = torture_suite_add_rpc_iface_tcase(suite, "srvsvc (admin access)", &ndr_table_srvsvc);
972
973         torture_rpc_tcase_add_test(tcase, "NetCharDevEnum", test_NetCharDevEnum);
974         torture_rpc_tcase_add_test(tcase, "NetCharDevQEnum", test_NetCharDevQEnum);
975         torture_rpc_tcase_add_test(tcase, "NetConnEnum", test_NetConnEnum);
976         torture_rpc_tcase_add_test(tcase, "NetFileEnum", test_NetFileEnum);
977         torture_rpc_tcase_add_test(tcase, "NetSessEnum", test_NetSessEnum);
978         torture_rpc_tcase_add_test(tcase, "NetShareEnumAll", test_NetShareEnumAllFull);
979         torture_rpc_tcase_add_test(tcase, "NetSrvGetInfo", test_NetSrvGetInfo);
980         torture_rpc_tcase_add_test(tcase, "NetDiskEnum", test_NetDiskEnum);
981         torture_rpc_tcase_add_test(tcase, "NetTransportEnum", test_NetTransportEnum);
982         torture_rpc_tcase_add_test(tcase, "NetRemoteTOD", test_NetRemoteTOD);
983         torture_rpc_tcase_add_test(tcase, "NetShareEnum", test_NetShareEnumFull);
984         torture_rpc_tcase_add_test(tcase, "NetShareGetInfo", test_NetShareGetInfoAdminFull);
985         test = torture_rpc_tcase_add_test(tcase, "NetShareAddSetDel", 
986                                            test_NetShareAddSetDel);
987         test->dangerous = true;
988         torture_rpc_tcase_add_test(tcase, "NetNameValidate", test_NetNameValidate);
989         
990         tcase = torture_suite_add_anon_rpc_iface_tcase(suite, 
991                                                     "srvsvc anonymous access", 
992                                                     &ndr_table_srvsvc);
993
994         torture_rpc_tcase_add_test(tcase, "NetShareEnumAll", 
995                                    test_NetShareEnumAllAnon);
996         torture_rpc_tcase_add_test(tcase, "NetShareEnum", 
997                                    test_NetShareEnumAnon);
998         torture_rpc_tcase_add_test(tcase, "NetShareGetInfo", 
999                                    test_NetShareGetInfoAdminAnon);
1000
1001         return suite;
1002 }