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