1/* 2 * Unix SMB/CIFS implementation. 3 * NetApi Group Support 4 * Copyright (C) Guenther Deschner 2008 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#include "includes.h" 21 22#include "librpc/gen_ndr/libnetapi.h" 23#include "lib/netapi/netapi.h" 24#include "lib/netapi/netapi_private.h" 25#include "lib/netapi/libnetapi.h" 26#include "../librpc/gen_ndr/cli_samr.h" 27 28/**************************************************************** 29****************************************************************/ 30 31WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx, 32 struct NetGroupAdd *r) 33{ 34 struct rpc_pipe_client *pipe_cli = NULL; 35 NTSTATUS status; 36 WERROR werr; 37 struct policy_handle connect_handle, domain_handle, group_handle; 38 struct lsa_String lsa_group_name; 39 struct dom_sid2 *domain_sid = NULL; 40 uint32_t rid = 0; 41 42 struct GROUP_INFO_0 *info0 = NULL; 43 struct GROUP_INFO_1 *info1 = NULL; 44 struct GROUP_INFO_2 *info2 = NULL; 45 struct GROUP_INFO_3 *info3 = NULL; 46 union samr_GroupInfo info; 47 48 ZERO_STRUCT(connect_handle); 49 ZERO_STRUCT(domain_handle); 50 ZERO_STRUCT(group_handle); 51 52 if (!r->in.buffer) { 53 return WERR_INVALID_PARAM; 54 } 55 56 switch (r->in.level) { 57 case 0: 58 info0 = (struct GROUP_INFO_0 *)r->in.buffer; 59 break; 60 case 1: 61 info1 = (struct GROUP_INFO_1 *)r->in.buffer; 62 break; 63 case 2: 64 info2 = (struct GROUP_INFO_2 *)r->in.buffer; 65 break; 66 case 3: 67 info3 = (struct GROUP_INFO_3 *)r->in.buffer; 68 break; 69 default: 70 werr = WERR_UNKNOWN_LEVEL; 71 goto done; 72 } 73 74 werr = libnetapi_open_pipe(ctx, r->in.server_name, 75 &ndr_table_samr.syntax_id, 76 &pipe_cli); 77 if (!W_ERROR_IS_OK(werr)) { 78 goto done; 79 } 80 81 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 82 SAMR_ACCESS_ENUM_DOMAINS | 83 SAMR_ACCESS_LOOKUP_DOMAIN, 84 SAMR_DOMAIN_ACCESS_CREATE_GROUP | 85 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 86 &connect_handle, 87 &domain_handle, 88 &domain_sid); 89 if (!W_ERROR_IS_OK(werr)) { 90 goto done; 91 } 92 93 switch (r->in.level) { 94 case 0: 95 init_lsa_String(&lsa_group_name, info0->grpi0_name); 96 break; 97 case 1: 98 init_lsa_String(&lsa_group_name, info1->grpi1_name); 99 break; 100 case 2: 101 init_lsa_String(&lsa_group_name, info2->grpi2_name); 102 break; 103 case 3: 104 init_lsa_String(&lsa_group_name, info3->grpi3_name); 105 break; 106 } 107 108 status = rpccli_samr_CreateDomainGroup(pipe_cli, talloc_tos(), 109 &domain_handle, 110 &lsa_group_name, 111 SEC_STD_DELETE | 112 SAMR_GROUP_ACCESS_SET_INFO, 113 &group_handle, 114 &rid); 115 116 if (!NT_STATUS_IS_OK(status)) { 117 werr = ntstatus_to_werror(status); 118 goto done; 119 } 120 121 switch (r->in.level) { 122 case 1: 123 if (info1->grpi1_comment) { 124 init_lsa_String(&info.description, 125 info1->grpi1_comment); 126 127 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 128 &group_handle, 129 GROUPINFODESCRIPTION, 130 &info); 131 } 132 break; 133 case 2: 134 if (info2->grpi2_comment) { 135 init_lsa_String(&info.description, 136 info2->grpi2_comment); 137 138 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 139 &group_handle, 140 GROUPINFODESCRIPTION, 141 &info); 142 if (!NT_STATUS_IS_OK(status)) { 143 werr = ntstatus_to_werror(status); 144 goto failed; 145 } 146 } 147 148 if (info2->grpi2_attributes != 0) { 149 info.attributes.attributes = info2->grpi2_attributes; 150 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 151 &group_handle, 152 GROUPINFOATTRIBUTES, 153 &info); 154 155 } 156 break; 157 case 3: 158 if (info3->grpi3_comment) { 159 init_lsa_String(&info.description, 160 info3->grpi3_comment); 161 162 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 163 &group_handle, 164 GROUPINFODESCRIPTION, 165 &info); 166 if (!NT_STATUS_IS_OK(status)) { 167 werr = ntstatus_to_werror(status); 168 goto failed; 169 } 170 } 171 172 if (info3->grpi3_attributes != 0) { 173 info.attributes.attributes = info3->grpi3_attributes; 174 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 175 &group_handle, 176 GROUPINFOATTRIBUTES, 177 &info); 178 } 179 break; 180 default: 181 break; 182 } 183 184 if (!NT_STATUS_IS_OK(status)) { 185 werr = ntstatus_to_werror(status); 186 goto failed; 187 } 188 189 werr = WERR_OK; 190 goto done; 191 192 failed: 193 rpccli_samr_DeleteDomainGroup(pipe_cli, talloc_tos(), 194 &group_handle); 195 196 done: 197 if (is_valid_policy_hnd(&group_handle)) { 198 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 199 } 200 201 if (ctx->disable_policy_handle_cache) { 202 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 203 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 204 } 205 206 return werr; 207} 208 209/**************************************************************** 210****************************************************************/ 211 212WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx, 213 struct NetGroupAdd *r) 214{ 215 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd); 216} 217 218/**************************************************************** 219****************************************************************/ 220 221WERROR NetGroupDel_r(struct libnetapi_ctx *ctx, 222 struct NetGroupDel *r) 223{ 224 struct rpc_pipe_client *pipe_cli = NULL; 225 NTSTATUS status; 226 WERROR werr; 227 struct policy_handle connect_handle, domain_handle, group_handle; 228 struct lsa_String lsa_group_name; 229 struct dom_sid2 *domain_sid = NULL; 230 int i = 0; 231 232 struct samr_Ids rids; 233 struct samr_Ids types; 234 union samr_GroupInfo *info = NULL; 235 struct samr_RidTypeArray *rid_array = NULL; 236 237 ZERO_STRUCT(connect_handle); 238 ZERO_STRUCT(domain_handle); 239 ZERO_STRUCT(group_handle); 240 241 if (!r->in.group_name) { 242 return WERR_INVALID_PARAM; 243 } 244 245 werr = libnetapi_open_pipe(ctx, r->in.server_name, 246 &ndr_table_samr.syntax_id, 247 &pipe_cli); 248 if (!W_ERROR_IS_OK(werr)) { 249 goto done; 250 } 251 252 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 253 SAMR_ACCESS_ENUM_DOMAINS | 254 SAMR_ACCESS_LOOKUP_DOMAIN, 255 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 256 &connect_handle, 257 &domain_handle, 258 &domain_sid); 259 if (!W_ERROR_IS_OK(werr)) { 260 goto done; 261 } 262 263 init_lsa_String(&lsa_group_name, r->in.group_name); 264 265 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 266 &domain_handle, 267 1, 268 &lsa_group_name, 269 &rids, 270 &types); 271 if (!NT_STATUS_IS_OK(status)) { 272 werr = ntstatus_to_werror(status); 273 goto done; 274 } 275 276 if (types.ids[0] != SID_NAME_DOM_GRP) { 277 werr = WERR_INVALID_DATATYPE; 278 goto done; 279 } 280 281 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 282 &domain_handle, 283 SEC_STD_DELETE | 284 SAMR_GROUP_ACCESS_GET_MEMBERS | 285 SAMR_GROUP_ACCESS_REMOVE_MEMBER | 286 SAMR_GROUP_ACCESS_ADD_MEMBER | 287 SAMR_GROUP_ACCESS_LOOKUP_INFO, 288 rids.ids[0], 289 &group_handle); 290 if (!NT_STATUS_IS_OK(status)) { 291 werr = ntstatus_to_werror(status); 292 goto done; 293 } 294 295 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(), 296 &group_handle, 297 GROUPINFOATTRIBUTES, 298 &info); 299 if (!NT_STATUS_IS_OK(status)) { 300 werr = ntstatus_to_werror(status); 301 goto done; 302 } 303 304#if 0 305 /* breaks against NT4 */ 306 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) { 307 werr = WERR_ACCESS_DENIED; 308 goto done; 309 } 310#endif 311 status = rpccli_samr_QueryGroupMember(pipe_cli, talloc_tos(), 312 &group_handle, 313 &rid_array); 314 if (!NT_STATUS_IS_OK(status)) { 315 werr = ntstatus_to_werror(status); 316 goto done; 317 } 318 319 { 320 struct lsa_Strings names; 321 struct samr_Ids member_types; 322 323 status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(), 324 &domain_handle, 325 rid_array->count, 326 rid_array->rids, 327 &names, 328 &member_types); 329 if (!NT_STATUS_IS_OK(status)) { 330 werr = ntstatus_to_werror(status); 331 goto done; 332 } 333 } 334 335 for (i=0; i < rid_array->count; i++) { 336 337 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(), 338 &group_handle, 339 rid_array->rids[i]); 340 if (!NT_STATUS_IS_OK(status)) { 341 werr = ntstatus_to_werror(status); 342 goto done; 343 } 344 } 345 346 status = rpccli_samr_DeleteDomainGroup(pipe_cli, talloc_tos(), 347 &group_handle); 348 if (!NT_STATUS_IS_OK(status)) { 349 werr = ntstatus_to_werror(status); 350 goto done; 351 } 352 353 ZERO_STRUCT(group_handle); 354 355 werr = WERR_OK; 356 357 done: 358 if (is_valid_policy_hnd(&group_handle)) { 359 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 360 } 361 362 if (ctx->disable_policy_handle_cache) { 363 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 364 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 365 } 366 367 return werr; 368} 369 370/**************************************************************** 371****************************************************************/ 372 373WERROR NetGroupDel_l(struct libnetapi_ctx *ctx, 374 struct NetGroupDel *r) 375{ 376 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel); 377} 378 379/**************************************************************** 380****************************************************************/ 381 382WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx, 383 struct NetGroupSetInfo *r) 384{ 385 struct rpc_pipe_client *pipe_cli = NULL; 386 NTSTATUS status; 387 WERROR werr; 388 struct policy_handle connect_handle, domain_handle, group_handle; 389 struct lsa_String lsa_group_name; 390 struct dom_sid2 *domain_sid = NULL; 391 392 struct samr_Ids rids; 393 struct samr_Ids types; 394 union samr_GroupInfo info; 395 struct GROUP_INFO_0 *g0; 396 struct GROUP_INFO_1 *g1; 397 struct GROUP_INFO_2 *g2; 398 struct GROUP_INFO_3 *g3; 399 struct GROUP_INFO_1002 *g1002; 400 struct GROUP_INFO_1005 *g1005; 401 402 ZERO_STRUCT(connect_handle); 403 ZERO_STRUCT(domain_handle); 404 ZERO_STRUCT(group_handle); 405 406 if (!r->in.group_name) { 407 return WERR_INVALID_PARAM; 408 } 409 410 werr = libnetapi_open_pipe(ctx, r->in.server_name, 411 &ndr_table_samr.syntax_id, 412 &pipe_cli); 413 if (!W_ERROR_IS_OK(werr)) { 414 goto done; 415 } 416 417 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 418 SAMR_ACCESS_ENUM_DOMAINS | 419 SAMR_ACCESS_LOOKUP_DOMAIN, 420 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 421 &connect_handle, 422 &domain_handle, 423 &domain_sid); 424 if (!W_ERROR_IS_OK(werr)) { 425 goto done; 426 } 427 428 init_lsa_String(&lsa_group_name, r->in.group_name); 429 430 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 431 &domain_handle, 432 1, 433 &lsa_group_name, 434 &rids, 435 &types); 436 if (!NT_STATUS_IS_OK(status)) { 437 werr = ntstatus_to_werror(status); 438 goto done; 439 } 440 441 if (types.ids[0] != SID_NAME_DOM_GRP) { 442 werr = WERR_INVALID_DATATYPE; 443 goto done; 444 } 445 446 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 447 &domain_handle, 448 SAMR_GROUP_ACCESS_SET_INFO | 449 SAMR_GROUP_ACCESS_LOOKUP_INFO, 450 rids.ids[0], 451 &group_handle); 452 if (!NT_STATUS_IS_OK(status)) { 453 werr = ntstatus_to_werror(status); 454 goto done; 455 } 456 457 switch (r->in.level) { 458 case 0: 459 g0 = (struct GROUP_INFO_0 *)r->in.buffer; 460 init_lsa_String(&info.name, g0->grpi0_name); 461 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 462 &group_handle, 463 GROUPINFONAME, 464 &info); 465 break; 466 case 1: 467 g1 = (struct GROUP_INFO_1 *)r->in.buffer; 468 init_lsa_String(&info.description, g1->grpi1_comment); 469 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 470 &group_handle, 471 GROUPINFODESCRIPTION, 472 &info); 473 break; 474 case 2: 475 g2 = (struct GROUP_INFO_2 *)r->in.buffer; 476 init_lsa_String(&info.description, g2->grpi2_comment); 477 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 478 &group_handle, 479 GROUPINFODESCRIPTION, 480 &info); 481 if (!NT_STATUS_IS_OK(status)) { 482 werr = ntstatus_to_werror(status); 483 goto done; 484 } 485 info.attributes.attributes = g2->grpi2_attributes; 486 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 487 &group_handle, 488 GROUPINFOATTRIBUTES, 489 &info); 490 break; 491 case 3: 492 g3 = (struct GROUP_INFO_3 *)r->in.buffer; 493 init_lsa_String(&info.description, g3->grpi3_comment); 494 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 495 &group_handle, 496 GROUPINFODESCRIPTION, 497 &info); 498 if (!NT_STATUS_IS_OK(status)) { 499 werr = ntstatus_to_werror(status); 500 goto done; 501 } 502 info.attributes.attributes = g3->grpi3_attributes; 503 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 504 &group_handle, 505 GROUPINFOATTRIBUTES, 506 &info); 507 break; 508 case 1002: 509 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer; 510 init_lsa_String(&info.description, g1002->grpi1002_comment); 511 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 512 &group_handle, 513 GROUPINFODESCRIPTION, 514 &info); 515 break; 516 case 1005: 517 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer; 518 info.attributes.attributes = g1005->grpi1005_attributes; 519 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(), 520 &group_handle, 521 GROUPINFOATTRIBUTES, 522 &info); 523 break; 524 default: 525 status = NT_STATUS_INVALID_LEVEL; 526 break; 527 } 528 529 if (!NT_STATUS_IS_OK(status)) { 530 werr = ntstatus_to_werror(status); 531 goto done; 532 } 533 534 werr = WERR_OK; 535 536 done: 537 if (is_valid_policy_hnd(&group_handle)) { 538 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 539 } 540 541 if (ctx->disable_policy_handle_cache) { 542 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 543 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 544 } 545 546 return werr; 547} 548 549/**************************************************************** 550****************************************************************/ 551 552WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx, 553 struct NetGroupSetInfo *r) 554{ 555 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo); 556} 557 558/**************************************************************** 559****************************************************************/ 560 561static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx, 562 uint32_t level, 563 struct samr_GroupInfoAll *info, 564 struct dom_sid2 *domain_sid, 565 uint32_t rid, 566 uint8_t **buffer) 567{ 568 struct GROUP_INFO_0 info0; 569 struct GROUP_INFO_1 info1; 570 struct GROUP_INFO_2 info2; 571 struct GROUP_INFO_3 info3; 572 struct dom_sid sid; 573 574 switch (level) { 575 case 0: 576 info0.grpi0_name = info->name.string; 577 578 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0)); 579 580 break; 581 case 1: 582 info1.grpi1_name = info->name.string; 583 info1.grpi1_comment = info->description.string; 584 585 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1)); 586 587 break; 588 case 2: 589 info2.grpi2_name = info->name.string; 590 info2.grpi2_comment = info->description.string; 591 info2.grpi2_group_id = rid; 592 info2.grpi2_attributes = info->attributes; 593 594 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2)); 595 596 break; 597 case 3: 598 if (!sid_compose(&sid, domain_sid, rid)) { 599 return WERR_NOMEM; 600 } 601 602 info3.grpi3_name = info->name.string; 603 info3.grpi3_comment = info->description.string; 604 info3.grpi3_attributes = info->attributes; 605 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid); 606 607 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3)); 608 609 break; 610 default: 611 return WERR_UNKNOWN_LEVEL; 612 } 613 614 W_ERROR_HAVE_NO_MEMORY(*buffer); 615 616 return WERR_OK; 617} 618 619/**************************************************************** 620****************************************************************/ 621 622WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx, 623 struct NetGroupGetInfo *r) 624{ 625 struct rpc_pipe_client *pipe_cli = NULL; 626 NTSTATUS status; 627 WERROR werr; 628 struct policy_handle connect_handle, domain_handle, group_handle; 629 struct lsa_String lsa_group_name; 630 struct dom_sid2 *domain_sid = NULL; 631 632 struct samr_Ids rids; 633 struct samr_Ids types; 634 union samr_GroupInfo *info = NULL; 635 bool group_info_all = false; 636 637 ZERO_STRUCT(connect_handle); 638 ZERO_STRUCT(domain_handle); 639 ZERO_STRUCT(group_handle); 640 641 if (!r->in.group_name) { 642 return WERR_INVALID_PARAM; 643 } 644 645 werr = libnetapi_open_pipe(ctx, r->in.server_name, 646 &ndr_table_samr.syntax_id, 647 &pipe_cli); 648 if (!W_ERROR_IS_OK(werr)) { 649 goto done; 650 } 651 652 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 653 SAMR_ACCESS_ENUM_DOMAINS | 654 SAMR_ACCESS_LOOKUP_DOMAIN, 655 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 656 &connect_handle, 657 &domain_handle, 658 &domain_sid); 659 if (!W_ERROR_IS_OK(werr)) { 660 goto done; 661 } 662 663 init_lsa_String(&lsa_group_name, r->in.group_name); 664 665 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 666 &domain_handle, 667 1, 668 &lsa_group_name, 669 &rids, 670 &types); 671 if (!NT_STATUS_IS_OK(status)) { 672 werr = ntstatus_to_werror(status); 673 goto done; 674 } 675 676 if (types.ids[0] != SID_NAME_DOM_GRP) { 677 werr = WERR_INVALID_DATATYPE; 678 goto done; 679 } 680 681 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 682 &domain_handle, 683 SAMR_GROUP_ACCESS_LOOKUP_INFO, 684 rids.ids[0], 685 &group_handle); 686 if (!NT_STATUS_IS_OK(status)) { 687 werr = ntstatus_to_werror(status); 688 goto done; 689 } 690 691 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(), 692 &group_handle, 693 GROUPINFOALL2, 694 &info); 695 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { 696 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(), 697 &group_handle, 698 GROUPINFOALL, 699 &info); 700 group_info_all = true; 701 } 702 703 if (!NT_STATUS_IS_OK(status)) { 704 werr = ntstatus_to_werror(status); 705 goto done; 706 } 707 708 werr = map_group_info_to_buffer(ctx, r->in.level, 709 group_info_all ? &info->all : &info->all2, 710 domain_sid, rids.ids[0], 711 r->out.buffer); 712 if (!W_ERROR_IS_OK(werr)) { 713 goto done; 714 } 715 done: 716 if (is_valid_policy_hnd(&group_handle)) { 717 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 718 } 719 720 if (ctx->disable_policy_handle_cache) { 721 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 722 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 723 } 724 725 return werr; 726} 727 728/**************************************************************** 729****************************************************************/ 730 731WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx, 732 struct NetGroupGetInfo *r) 733{ 734 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo); 735} 736 737/**************************************************************** 738****************************************************************/ 739 740WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx, 741 struct NetGroupAddUser *r) 742{ 743 struct rpc_pipe_client *pipe_cli = NULL; 744 NTSTATUS status; 745 WERROR werr; 746 struct policy_handle connect_handle, domain_handle, group_handle; 747 struct lsa_String lsa_group_name, lsa_user_name; 748 struct dom_sid2 *domain_sid = NULL; 749 750 struct samr_Ids rids; 751 struct samr_Ids types; 752 753 ZERO_STRUCT(connect_handle); 754 ZERO_STRUCT(domain_handle); 755 ZERO_STRUCT(group_handle); 756 757 if (!r->in.group_name) { 758 return WERR_INVALID_PARAM; 759 } 760 761 werr = libnetapi_open_pipe(ctx, r->in.server_name, 762 &ndr_table_samr.syntax_id, 763 &pipe_cli); 764 if (!W_ERROR_IS_OK(werr)) { 765 goto done; 766 } 767 768 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 769 SAMR_ACCESS_ENUM_DOMAINS | 770 SAMR_ACCESS_LOOKUP_DOMAIN, 771 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 772 &connect_handle, 773 &domain_handle, 774 &domain_sid); 775 if (!W_ERROR_IS_OK(werr)) { 776 goto done; 777 } 778 779 init_lsa_String(&lsa_group_name, r->in.group_name); 780 781 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 782 &domain_handle, 783 1, 784 &lsa_group_name, 785 &rids, 786 &types); 787 if (!NT_STATUS_IS_OK(status)) { 788 werr = WERR_GROUPNOTFOUND; 789 goto done; 790 } 791 792 if (types.ids[0] != SID_NAME_DOM_GRP) { 793 werr = WERR_GROUPNOTFOUND; 794 goto done; 795 } 796 797 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 798 &domain_handle, 799 SAMR_GROUP_ACCESS_ADD_MEMBER, 800 rids.ids[0], 801 &group_handle); 802 if (!NT_STATUS_IS_OK(status)) { 803 werr = ntstatus_to_werror(status); 804 goto done; 805 } 806 807 init_lsa_String(&lsa_user_name, r->in.user_name); 808 809 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 810 &domain_handle, 811 1, 812 &lsa_user_name, 813 &rids, 814 &types); 815 if (!NT_STATUS_IS_OK(status)) { 816 werr = WERR_USER_NOT_FOUND; 817 goto done; 818 } 819 820 if (types.ids[0] != SID_NAME_USER) { 821 werr = WERR_USER_NOT_FOUND; 822 goto done; 823 } 824 825 status = rpccli_samr_AddGroupMember(pipe_cli, talloc_tos(), 826 &group_handle, 827 rids.ids[0], 828 7); /* why ? */ 829 if (!NT_STATUS_IS_OK(status)) { 830 werr = ntstatus_to_werror(status); 831 goto done; 832 } 833 834 werr = WERR_OK; 835 836 done: 837 if (is_valid_policy_hnd(&group_handle)) { 838 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 839 } 840 841 if (ctx->disable_policy_handle_cache) { 842 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 843 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 844 } 845 846 return werr; 847} 848 849/**************************************************************** 850****************************************************************/ 851 852WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx, 853 struct NetGroupAddUser *r) 854{ 855 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser); 856} 857 858/**************************************************************** 859****************************************************************/ 860 861WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx, 862 struct NetGroupDelUser *r) 863{ 864 struct rpc_pipe_client *pipe_cli = NULL; 865 NTSTATUS status; 866 WERROR werr; 867 struct policy_handle connect_handle, domain_handle, group_handle; 868 struct lsa_String lsa_group_name, lsa_user_name; 869 struct dom_sid2 *domain_sid = NULL; 870 871 struct samr_Ids rids; 872 struct samr_Ids types; 873 874 ZERO_STRUCT(connect_handle); 875 ZERO_STRUCT(domain_handle); 876 ZERO_STRUCT(group_handle); 877 878 if (!r->in.group_name) { 879 return WERR_INVALID_PARAM; 880 } 881 882 werr = libnetapi_open_pipe(ctx, r->in.server_name, 883 &ndr_table_samr.syntax_id, 884 &pipe_cli); 885 if (!W_ERROR_IS_OK(werr)) { 886 goto done; 887 } 888 889 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 890 SAMR_ACCESS_ENUM_DOMAINS | 891 SAMR_ACCESS_LOOKUP_DOMAIN, 892 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 893 &connect_handle, 894 &domain_handle, 895 &domain_sid); 896 if (!W_ERROR_IS_OK(werr)) { 897 goto done; 898 } 899 900 init_lsa_String(&lsa_group_name, r->in.group_name); 901 902 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 903 &domain_handle, 904 1, 905 &lsa_group_name, 906 &rids, 907 &types); 908 if (!NT_STATUS_IS_OK(status)) { 909 werr = WERR_GROUPNOTFOUND; 910 goto done; 911 } 912 913 if (types.ids[0] != SID_NAME_DOM_GRP) { 914 werr = WERR_GROUPNOTFOUND; 915 goto done; 916 } 917 918 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 919 &domain_handle, 920 SAMR_GROUP_ACCESS_REMOVE_MEMBER, 921 rids.ids[0], 922 &group_handle); 923 if (!NT_STATUS_IS_OK(status)) { 924 werr = ntstatus_to_werror(status); 925 goto done; 926 } 927 928 init_lsa_String(&lsa_user_name, r->in.user_name); 929 930 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 931 &domain_handle, 932 1, 933 &lsa_user_name, 934 &rids, 935 &types); 936 if (!NT_STATUS_IS_OK(status)) { 937 werr = WERR_USER_NOT_FOUND; 938 goto done; 939 } 940 941 if (types.ids[0] != SID_NAME_USER) { 942 werr = WERR_USER_NOT_FOUND; 943 goto done; 944 } 945 946 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(), 947 &group_handle, 948 rids.ids[0]); 949 if (!NT_STATUS_IS_OK(status)) { 950 werr = ntstatus_to_werror(status); 951 goto done; 952 } 953 954 werr = WERR_OK; 955 956 done: 957 if (is_valid_policy_hnd(&group_handle)) { 958 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 959 } 960 961 if (ctx->disable_policy_handle_cache) { 962 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 963 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 964 } 965 966 return werr; 967} 968 969/**************************************************************** 970****************************************************************/ 971 972WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx, 973 struct NetGroupDelUser *r) 974{ 975 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser); 976} 977 978/**************************************************************** 979****************************************************************/ 980 981static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx, 982 struct samr_DispInfoFullGroups *groups, 983 uint8_t **buffer) 984{ 985 struct GROUP_INFO_0 *g0; 986 int i; 987 988 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count); 989 W_ERROR_HAVE_NO_MEMORY(g0); 990 991 for (i=0; i<groups->count; i++) { 992 g0[i].grpi0_name = talloc_strdup(mem_ctx, 993 groups->entries[i].account_name.string); 994 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name); 995 } 996 997 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0, 998 sizeof(struct GROUP_INFO_0) * groups->count); 999 W_ERROR_HAVE_NO_MEMORY(*buffer); 1000 1001 return WERR_OK; 1002} 1003 1004/**************************************************************** 1005****************************************************************/ 1006 1007static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx, 1008 struct samr_DispInfoFullGroups *groups, 1009 uint8_t **buffer) 1010{ 1011 struct GROUP_INFO_1 *g1; 1012 int i; 1013 1014 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count); 1015 W_ERROR_HAVE_NO_MEMORY(g1); 1016 1017 for (i=0; i<groups->count; i++) { 1018 g1[i].grpi1_name = talloc_strdup(mem_ctx, 1019 groups->entries[i].account_name.string); 1020 g1[i].grpi1_comment = talloc_strdup(mem_ctx, 1021 groups->entries[i].description.string); 1022 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name); 1023 } 1024 1025 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1, 1026 sizeof(struct GROUP_INFO_1) * groups->count); 1027 W_ERROR_HAVE_NO_MEMORY(*buffer); 1028 1029 return WERR_OK; 1030} 1031 1032/**************************************************************** 1033****************************************************************/ 1034 1035static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx, 1036 struct samr_DispInfoFullGroups *groups, 1037 uint8_t **buffer) 1038{ 1039 struct GROUP_INFO_2 *g2; 1040 int i; 1041 1042 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count); 1043 W_ERROR_HAVE_NO_MEMORY(g2); 1044 1045 for (i=0; i<groups->count; i++) { 1046 g2[i].grpi2_name = talloc_strdup(mem_ctx, 1047 groups->entries[i].account_name.string); 1048 g2[i].grpi2_comment = talloc_strdup(mem_ctx, 1049 groups->entries[i].description.string); 1050 g2[i].grpi2_group_id = groups->entries[i].rid; 1051 g2[i].grpi2_attributes = groups->entries[i].acct_flags; 1052 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name); 1053 } 1054 1055 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2, 1056 sizeof(struct GROUP_INFO_2) * groups->count); 1057 W_ERROR_HAVE_NO_MEMORY(*buffer); 1058 1059 return WERR_OK; 1060} 1061 1062/**************************************************************** 1063****************************************************************/ 1064 1065static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx, 1066 struct samr_DispInfoFullGroups *groups, 1067 const struct dom_sid *domain_sid, 1068 uint8_t **buffer) 1069{ 1070 struct GROUP_INFO_3 *g3; 1071 int i; 1072 1073 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count); 1074 W_ERROR_HAVE_NO_MEMORY(g3); 1075 1076 for (i=0; i<groups->count; i++) { 1077 1078 struct dom_sid sid; 1079 1080 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) { 1081 return WERR_NOMEM; 1082 } 1083 1084 g3[i].grpi3_name = talloc_strdup(mem_ctx, 1085 groups->entries[i].account_name.string); 1086 g3[i].grpi3_comment = talloc_strdup(mem_ctx, 1087 groups->entries[i].description.string); 1088 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid); 1089 g3[i].grpi3_attributes = groups->entries[i].acct_flags; 1090 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name); 1091 } 1092 1093 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3, 1094 sizeof(struct GROUP_INFO_3) * groups->count); 1095 W_ERROR_HAVE_NO_MEMORY(*buffer); 1096 1097 return WERR_OK; 1098} 1099 1100/**************************************************************** 1101****************************************************************/ 1102 1103static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx, 1104 uint32_t level, 1105 struct samr_DispInfoFullGroups *groups, 1106 const struct dom_sid *domain_sid, 1107 uint32_t *entries_read, 1108 uint8_t **buffer) 1109{ 1110 if (entries_read) { 1111 *entries_read = groups->count; 1112 } 1113 1114 switch (level) { 1115 case 0: 1116 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer); 1117 case 1: 1118 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer); 1119 case 2: 1120 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer); 1121 case 3: 1122 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer); 1123 default: 1124 return WERR_UNKNOWN_LEVEL; 1125 } 1126} 1127 1128/**************************************************************** 1129****************************************************************/ 1130 1131WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx, 1132 struct NetGroupEnum *r) 1133{ 1134 struct rpc_pipe_client *pipe_cli = NULL; 1135 struct policy_handle connect_handle; 1136 struct dom_sid2 *domain_sid = NULL; 1137 struct policy_handle domain_handle; 1138 union samr_DispInfo info; 1139 union samr_DomainInfo *domain_info = NULL; 1140 1141 uint32_t total_size = 0; 1142 uint32_t returned_size = 0; 1143 1144 NTSTATUS status = NT_STATUS_OK; 1145 WERROR werr, tmp_werr; 1146 1147 ZERO_STRUCT(connect_handle); 1148 ZERO_STRUCT(domain_handle); 1149 1150 switch (r->in.level) { 1151 case 0: 1152 case 1: 1153 case 2: 1154 case 3: 1155 break; 1156 default: 1157 return WERR_UNKNOWN_LEVEL; 1158 } 1159 1160 werr = libnetapi_open_pipe(ctx, r->in.server_name, 1161 &ndr_table_samr.syntax_id, 1162 &pipe_cli); 1163 if (!W_ERROR_IS_OK(werr)) { 1164 goto done; 1165 } 1166 1167 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 1168 SAMR_ACCESS_ENUM_DOMAINS | 1169 SAMR_ACCESS_LOOKUP_DOMAIN, 1170 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 | 1171 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS | 1172 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 1173 &connect_handle, 1174 &domain_handle, 1175 &domain_sid); 1176 if (!W_ERROR_IS_OK(werr)) { 1177 goto done; 1178 } 1179 1180 status = rpccli_samr_QueryDomainInfo(pipe_cli, talloc_tos(), 1181 &domain_handle, 1182 2, 1183 &domain_info); 1184 if (!NT_STATUS_IS_OK(status)) { 1185 werr = ntstatus_to_werror(status); 1186 goto done; 1187 } 1188 1189 if (r->out.total_entries) { 1190 *r->out.total_entries = domain_info->general.num_groups; 1191 } 1192 1193 status = rpccli_samr_QueryDisplayInfo2(pipe_cli, 1194 ctx, 1195 &domain_handle, 1196 3, 1197 r->in.resume_handle ? 1198 *r->in.resume_handle : 0, 1199 (uint32_t)-1, 1200 r->in.prefmaxlen, 1201 &total_size, 1202 &returned_size, 1203 &info); 1204 werr = ntstatus_to_werror(status); 1205 if (NT_STATUS_IS_ERR(status)) { 1206 goto done; 1207 } 1208 1209 if (r->out.resume_handle && info.info3.count > 0) { 1210 *r->out.resume_handle = 1211 info.info3.entries[info.info3.count-1].idx; 1212 } 1213 1214 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx, 1215 r->in.level, 1216 &info.info3, 1217 domain_sid, 1218 r->out.entries_read, 1219 r->out.buffer); 1220 if (!W_ERROR_IS_OK(tmp_werr)) { 1221 werr = tmp_werr; 1222 goto done; 1223 } 1224 1225 done: 1226 /* if last query */ 1227 if (NT_STATUS_IS_OK(status) || 1228 NT_STATUS_IS_ERR(status)) { 1229 1230 if (ctx->disable_policy_handle_cache) { 1231 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 1232 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 1233 } 1234 } 1235 1236 return werr; 1237} 1238 1239/**************************************************************** 1240****************************************************************/ 1241 1242WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx, 1243 struct NetGroupEnum *r) 1244{ 1245 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum); 1246} 1247 1248/**************************************************************** 1249****************************************************************/ 1250 1251WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx, 1252 struct NetGroupGetUsers *r) 1253{ 1254 /* FIXME: this call needs to cope with large replies */ 1255 1256 struct rpc_pipe_client *pipe_cli = NULL; 1257 struct policy_handle connect_handle, domain_handle, group_handle; 1258 struct lsa_String lsa_account_name; 1259 struct dom_sid2 *domain_sid = NULL; 1260 struct samr_Ids group_rids, name_types; 1261 struct samr_RidTypeArray *rid_array = NULL; 1262 struct lsa_Strings names; 1263 struct samr_Ids member_types; 1264 1265 int i; 1266 uint32_t entries_read = 0; 1267 1268 NTSTATUS status = NT_STATUS_OK; 1269 WERROR werr; 1270 1271 ZERO_STRUCT(connect_handle); 1272 ZERO_STRUCT(domain_handle); 1273 1274 if (!r->out.buffer) { 1275 return WERR_INVALID_PARAM; 1276 } 1277 1278 *r->out.buffer = NULL; 1279 *r->out.entries_read = 0; 1280 *r->out.total_entries = 0; 1281 1282 switch (r->in.level) { 1283 case 0: 1284 case 1: 1285 break; 1286 default: 1287 return WERR_UNKNOWN_LEVEL; 1288 } 1289 1290 1291 werr = libnetapi_open_pipe(ctx, r->in.server_name, 1292 &ndr_table_samr.syntax_id, 1293 &pipe_cli); 1294 if (!W_ERROR_IS_OK(werr)) { 1295 goto done; 1296 } 1297 1298 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 1299 SAMR_ACCESS_ENUM_DOMAINS | 1300 SAMR_ACCESS_LOOKUP_DOMAIN, 1301 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 1302 &connect_handle, 1303 &domain_handle, 1304 &domain_sid); 1305 if (!W_ERROR_IS_OK(werr)) { 1306 goto done; 1307 } 1308 1309 init_lsa_String(&lsa_account_name, r->in.group_name); 1310 1311 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 1312 &domain_handle, 1313 1, 1314 &lsa_account_name, 1315 &group_rids, 1316 &name_types); 1317 if (!NT_STATUS_IS_OK(status)) { 1318 werr = ntstatus_to_werror(status); 1319 goto done; 1320 } 1321 1322 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 1323 &domain_handle, 1324 SAMR_GROUP_ACCESS_GET_MEMBERS, 1325 group_rids.ids[0], 1326 &group_handle); 1327 if (!NT_STATUS_IS_OK(status)) { 1328 werr = ntstatus_to_werror(status); 1329 goto done; 1330 } 1331 1332 status = rpccli_samr_QueryGroupMember(pipe_cli, talloc_tos(), 1333 &group_handle, 1334 &rid_array); 1335 if (!NT_STATUS_IS_OK(status)) { 1336 werr = ntstatus_to_werror(status); 1337 goto done; 1338 } 1339 1340 status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(), 1341 &domain_handle, 1342 rid_array->count, 1343 rid_array->rids, 1344 &names, 1345 &member_types); 1346 if (!NT_STATUS_IS_OK(status)) { 1347 werr = ntstatus_to_werror(status); 1348 goto done; 1349 } 1350 1351 for (i=0; i < names.count; i++) { 1352 1353 if (member_types.ids[i] != SID_NAME_USER) { 1354 continue; 1355 } 1356 1357 status = add_GROUP_USERS_INFO_X_buffer(ctx, 1358 r->in.level, 1359 names.names[i].string, 1360 7, 1361 r->out.buffer, 1362 &entries_read); 1363 if (!NT_STATUS_IS_OK(status)) { 1364 werr = ntstatus_to_werror(status); 1365 goto done; 1366 } 1367 } 1368 1369 *r->out.entries_read = entries_read; 1370 *r->out.total_entries = entries_read; 1371 1372 werr = WERR_OK; 1373 1374 done: 1375 if (is_valid_policy_hnd(&group_handle)) { 1376 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 1377 } 1378 1379 if (ctx->disable_policy_handle_cache) { 1380 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 1381 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 1382 } 1383 1384 return werr; 1385} 1386 1387/**************************************************************** 1388****************************************************************/ 1389 1390WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx, 1391 struct NetGroupGetUsers *r) 1392{ 1393 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers); 1394} 1395 1396/**************************************************************** 1397****************************************************************/ 1398 1399WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx, 1400 struct NetGroupSetUsers *r) 1401{ 1402 struct rpc_pipe_client *pipe_cli = NULL; 1403 struct policy_handle connect_handle, domain_handle, group_handle; 1404 struct lsa_String lsa_account_name; 1405 struct dom_sid2 *domain_sid = NULL; 1406 union samr_GroupInfo *group_info = NULL; 1407 struct samr_Ids user_rids, name_types; 1408 struct samr_Ids group_rids, group_types; 1409 struct samr_RidTypeArray *rid_array = NULL; 1410 struct lsa_String *lsa_names = NULL; 1411 1412 uint32_t *add_rids = NULL; 1413 uint32_t *del_rids = NULL; 1414 size_t num_add_rids = 0; 1415 size_t num_del_rids = 0; 1416 1417 uint32_t *member_rids = NULL; 1418 size_t num_member_rids = 0; 1419 1420 struct GROUP_USERS_INFO_0 *i0 = NULL; 1421 struct GROUP_USERS_INFO_1 *i1 = NULL; 1422 1423 int i, k; 1424 1425 NTSTATUS status = NT_STATUS_OK; 1426 WERROR werr; 1427 1428 ZERO_STRUCT(connect_handle); 1429 ZERO_STRUCT(domain_handle); 1430 1431 if (!r->in.buffer) { 1432 return WERR_INVALID_PARAM; 1433 } 1434 1435 switch (r->in.level) { 1436 case 0: 1437 case 1: 1438 break; 1439 default: 1440 return WERR_UNKNOWN_LEVEL; 1441 } 1442 1443 werr = libnetapi_open_pipe(ctx, r->in.server_name, 1444 &ndr_table_samr.syntax_id, 1445 &pipe_cli); 1446 if (!W_ERROR_IS_OK(werr)) { 1447 goto done; 1448 } 1449 1450 werr = libnetapi_samr_open_domain(ctx, pipe_cli, 1451 SAMR_ACCESS_ENUM_DOMAINS | 1452 SAMR_ACCESS_LOOKUP_DOMAIN, 1453 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 1454 &connect_handle, 1455 &domain_handle, 1456 &domain_sid); 1457 if (!W_ERROR_IS_OK(werr)) { 1458 goto done; 1459 } 1460 1461 init_lsa_String(&lsa_account_name, r->in.group_name); 1462 1463 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 1464 &domain_handle, 1465 1, 1466 &lsa_account_name, 1467 &group_rids, 1468 &group_types); 1469 if (!NT_STATUS_IS_OK(status)) { 1470 werr = ntstatus_to_werror(status); 1471 goto done; 1472 } 1473 1474 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(), 1475 &domain_handle, 1476 SAMR_GROUP_ACCESS_GET_MEMBERS | 1477 SAMR_GROUP_ACCESS_ADD_MEMBER | 1478 SAMR_GROUP_ACCESS_REMOVE_MEMBER | 1479 SAMR_GROUP_ACCESS_LOOKUP_INFO, 1480 group_rids.ids[0], 1481 &group_handle); 1482 if (!NT_STATUS_IS_OK(status)) { 1483 werr = ntstatus_to_werror(status); 1484 goto done; 1485 } 1486 1487 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(), 1488 &group_handle, 1489 GROUPINFOATTRIBUTES, 1490 &group_info); 1491 if (!NT_STATUS_IS_OK(status)) { 1492 werr = ntstatus_to_werror(status); 1493 goto done; 1494 } 1495 1496 switch (r->in.level) { 1497 case 0: 1498 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer; 1499 break; 1500 case 1: 1501 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer; 1502 break; 1503 } 1504 1505 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries); 1506 if (!lsa_names) { 1507 werr = WERR_NOMEM; 1508 goto done; 1509 } 1510 1511 for (i=0; i < r->in.num_entries; i++) { 1512 1513 switch (r->in.level) { 1514 case 0: 1515 init_lsa_String(&lsa_names[i], i0->grui0_name); 1516 i0++; 1517 break; 1518 case 1: 1519 init_lsa_String(&lsa_names[i], i1->grui1_name); 1520 i1++; 1521 break; 1522 } 1523 } 1524 1525 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(), 1526 &domain_handle, 1527 r->in.num_entries, 1528 lsa_names, 1529 &user_rids, 1530 &name_types); 1531 if (!NT_STATUS_IS_OK(status)) { 1532 werr = ntstatus_to_werror(status); 1533 goto done; 1534 } 1535 1536 member_rids = user_rids.ids; 1537 num_member_rids = user_rids.count; 1538 1539 status = rpccli_samr_QueryGroupMember(pipe_cli, talloc_tos(), 1540 &group_handle, 1541 &rid_array); 1542 if (!NT_STATUS_IS_OK(status)) { 1543 werr = ntstatus_to_werror(status); 1544 goto done; 1545 } 1546 1547 /* add list */ 1548 1549 for (i=0; i < r->in.num_entries; i++) { 1550 bool already_member = false; 1551 for (k=0; k < rid_array->count; k++) { 1552 if (member_rids[i] == rid_array->rids[k]) { 1553 already_member = true; 1554 break; 1555 } 1556 } 1557 if (!already_member) { 1558 if (!add_rid_to_array_unique(ctx, 1559 member_rids[i], 1560 &add_rids, &num_add_rids)) { 1561 werr = WERR_GENERAL_FAILURE; 1562 goto done; 1563 } 1564 } 1565 } 1566 1567 /* del list */ 1568 1569 for (k=0; k < rid_array->count; k++) { 1570 bool keep_member = false; 1571 for (i=0; i < r->in.num_entries; i++) { 1572 if (member_rids[i] == rid_array->rids[k]) { 1573 keep_member = true; 1574 break; 1575 } 1576 } 1577 if (!keep_member) { 1578 if (!add_rid_to_array_unique(ctx, 1579 rid_array->rids[k], 1580 &del_rids, &num_del_rids)) { 1581 werr = WERR_GENERAL_FAILURE; 1582 goto done; 1583 } 1584 } 1585 } 1586 1587 /* add list */ 1588 1589 for (i=0; i < num_add_rids; i++) { 1590 status = rpccli_samr_AddGroupMember(pipe_cli, talloc_tos(), 1591 &group_handle, 1592 add_rids[i], 1593 7 /* ? */); 1594 if (!NT_STATUS_IS_OK(status)) { 1595 werr = ntstatus_to_werror(status); 1596 goto done; 1597 } 1598 } 1599 1600 /* del list */ 1601 1602 for (i=0; i < num_del_rids; i++) { 1603 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(), 1604 &group_handle, 1605 del_rids[i]); 1606 if (!NT_STATUS_IS_OK(status)) { 1607 werr = ntstatus_to_werror(status); 1608 goto done; 1609 } 1610 } 1611 1612 werr = WERR_OK; 1613 1614 done: 1615 if (is_valid_policy_hnd(&group_handle)) { 1616 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle); 1617 } 1618 1619 if (ctx->disable_policy_handle_cache) { 1620 libnetapi_samr_close_domain_handle(ctx, &domain_handle); 1621 libnetapi_samr_close_connect_handle(ctx, &connect_handle); 1622 } 1623 1624 return werr; 1625} 1626 1627/**************************************************************** 1628****************************************************************/ 1629 1630WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx, 1631 struct NetGroupSetUsers *r) 1632{ 1633 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers); 1634} 1635