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