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