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