root/source3/lib/netapi/group.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. NetGroupAdd_r
  2. NetGroupAdd_l
  3. NetGroupDel_r
  4. NetGroupDel_l
  5. NetGroupSetInfo_r
  6. NetGroupSetInfo_l
  7. map_group_info_to_buffer
  8. NetGroupGetInfo_r
  9. NetGroupGetInfo_l
  10. NetGroupAddUser_r
  11. NetGroupAddUser_l
  12. NetGroupDelUser_r
  13. NetGroupDelUser_l
  14. convert_samr_disp_groups_to_GROUP_INFO_0_buffer
  15. convert_samr_disp_groups_to_GROUP_INFO_1_buffer
  16. convert_samr_disp_groups_to_GROUP_INFO_2_buffer
  17. convert_samr_disp_groups_to_GROUP_INFO_3_buffer
  18. convert_samr_disp_groups_to_GROUP_INFO_buffer
  19. NetGroupEnum_r
  20. NetGroupEnum_l
  21. NetGroupGetUsers_r
  22. NetGroupGetUsers_l
  23. NetGroupSetUsers_r
  24. NetGroupSetUsers_l

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

/* [<][>][^][v][top][bottom][index][help] */