root/source3/lib/netapi/localgroup.c

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

DEFINITIONS

This source file includes following definitions.
  1. libnetapi_samr_lookup_and_open_alias
  2. libnetapi_samr_open_alias_queryinfo
  3. NetLocalGroupAdd_r
  4. NetLocalGroupAdd_l
  5. NetLocalGroupDel_r
  6. NetLocalGroupDel_l
  7. map_alias_info_to_buffer
  8. NetLocalGroupGetInfo_r
  9. NetLocalGroupGetInfo_l
  10. map_buffer_to_alias_info
  11. NetLocalGroupSetInfo_r
  12. NetLocalGroupSetInfo_l
  13. NetLocalGroupEnum_r
  14. NetLocalGroupEnum_l
  15. libnetapi_lsa_lookup_names3
  16. NetLocalGroupModifyMembers_r
  17. NetLocalGroupAddMembers_r
  18. NetLocalGroupAddMembers_l
  19. NetLocalGroupDelMembers_r
  20. NetLocalGroupDelMembers_l
  21. NetLocalGroupGetMembers_r
  22. NetLocalGroupGetMembers_l
  23. NetLocalGroupSetMembers_r
  24. NetLocalGroupSetMembers_l

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  NetApi LocalGroup 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 static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  28                                                      struct rpc_pipe_client *pipe_cli,
  29                                                      struct policy_handle *domain_handle,
  30                                                      const char *group_name,
  31                                                      uint32_t access_rights,
  32                                                      struct policy_handle *alias_handle)
  33 {
  34         NTSTATUS status;
  35 
  36         struct lsa_String lsa_account_name;
  37         struct samr_Ids user_rids, name_types;
  38 
  39         init_lsa_String(&lsa_account_name, group_name);
  40 
  41         status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
  42                                          domain_handle,
  43                                          1,
  44                                          &lsa_account_name,
  45                                          &user_rids,
  46                                          &name_types);
  47         if (!NT_STATUS_IS_OK(status)) {
  48                 return status;
  49         }
  50 
  51         switch (name_types.ids[0]) {
  52                 case SID_NAME_ALIAS:
  53                 case SID_NAME_WKN_GRP:
  54                         break;
  55                 default:
  56                         return NT_STATUS_INVALID_SID;
  57         }
  58 
  59         return rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
  60                                      domain_handle,
  61                                      access_rights,
  62                                      user_rids.ids[0],
  63                                      alias_handle);
  64 }
  65 
  66 /****************************************************************
  67 ****************************************************************/
  68 
  69 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  70                                                     struct rpc_pipe_client *pipe_cli,
  71                                                     struct policy_handle *handle,
  72                                                     uint32_t rid,
  73                                                     uint32_t access_rights,
  74                                                     enum samr_AliasInfoEnum level,
  75                                                     union samr_AliasInfo **alias_info)
  76 {
  77         NTSTATUS status;
  78         struct policy_handle alias_handle;
  79         union samr_AliasInfo *_alias_info = NULL;
  80 
  81         ZERO_STRUCT(alias_handle);
  82 
  83         status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
  84                                        handle,
  85                                        access_rights,
  86                                        rid,
  87                                        &alias_handle);
  88         if (!NT_STATUS_IS_OK(status)) {
  89                 goto done;
  90         }
  91 
  92         status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
  93                                             &alias_handle,
  94                                             level,
  95                                             &_alias_info);
  96         if (!NT_STATUS_IS_OK(status)) {
  97                 goto done;
  98         }
  99 
 100         *alias_info = _alias_info;
 101 
 102  done:
 103         if (is_valid_policy_hnd(&alias_handle)) {
 104                 rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
 105         }
 106 
 107         return status;
 108 }
 109 
 110 /****************************************************************
 111 ****************************************************************/
 112 
 113 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 114                           struct NetLocalGroupAdd *r)
 115 {
 116         struct rpc_pipe_client *pipe_cli = NULL;
 117         NTSTATUS status;
 118         WERROR werr;
 119         struct lsa_String lsa_account_name;
 120         struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
 121         struct dom_sid2 *domain_sid = NULL;
 122         uint32_t rid;
 123 
 124         struct LOCALGROUP_INFO_0 *info0 = NULL;
 125         struct LOCALGROUP_INFO_1 *info1 = NULL;
 126 
 127         const char *alias_name = NULL;
 128 
 129         if (!r->in.buffer) {
 130                 return WERR_INVALID_PARAM;
 131         }
 132 
 133         switch (r->in.level) {
 134                 case 0:
 135                         info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
 136                         alias_name = info0->lgrpi0_name;
 137                         break;
 138                 case 1:
 139                         info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
 140                         alias_name = info1->lgrpi1_name;
 141                         break;
 142                 default:
 143                         werr = WERR_UNKNOWN_LEVEL;
 144                         goto done;
 145         }
 146 
 147         ZERO_STRUCT(connect_handle);
 148         ZERO_STRUCT(builtin_handle);
 149         ZERO_STRUCT(domain_handle);
 150         ZERO_STRUCT(alias_handle);
 151 
 152         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 153                                    &ndr_table_samr.syntax_id,
 154                                    &pipe_cli);
 155         if (!W_ERROR_IS_OK(werr)) {
 156                 goto done;
 157         }
 158 
 159         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
 160                                                   SAMR_ACCESS_LOOKUP_DOMAIN |
 161                                                   SAMR_ACCESS_ENUM_DOMAINS,
 162                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 163                                                   &connect_handle,
 164                                                   &builtin_handle);
 165         if (!W_ERROR_IS_OK(werr)) {
 166                 goto done;
 167         }
 168 
 169         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 170                                                       &builtin_handle,
 171                                                       alias_name,
 172                                                       SAMR_ALIAS_ACCESS_LOOKUP_INFO,
 173                                                       &alias_handle);
 174         if (ctx->disable_policy_handle_cache) {
 175                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 176         }
 177 
 178         if (NT_STATUS_IS_OK(status)) {
 179                 werr = WERR_ALIAS_EXISTS;
 180                 goto done;
 181         }
 182 
 183         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
 184                                           SAMR_ACCESS_ENUM_DOMAINS |
 185                                           SAMR_ACCESS_LOOKUP_DOMAIN,
 186                                           SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
 187                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 188                                           &connect_handle,
 189                                           &domain_handle,
 190                                           &domain_sid);
 191         if (!W_ERROR_IS_OK(werr)) {
 192                 goto done;
 193         }
 194 
 195         init_lsa_String(&lsa_account_name, alias_name);
 196 
 197         status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
 198                                             &domain_handle,
 199                                             &lsa_account_name,
 200                                             SEC_STD_DELETE |
 201                                             SAMR_ALIAS_ACCESS_SET_INFO,
 202                                             &alias_handle,
 203                                             &rid);
 204         if (!NT_STATUS_IS_OK(status)) {
 205                 werr = ntstatus_to_werror(status);
 206                 goto done;
 207         }
 208 
 209         if (r->in.level == 1 && info1->lgrpi1_comment) {
 210 
 211                 union samr_AliasInfo alias_info;
 212 
 213                 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
 214 
 215                 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
 216                                                   &alias_handle,
 217                                                   ALIASINFODESCRIPTION,
 218                                                   &alias_info);
 219                 if (!NT_STATUS_IS_OK(status)) {
 220                         werr = ntstatus_to_werror(status);
 221                         goto done;
 222                 }
 223         }
 224 
 225         werr = WERR_OK;
 226 
 227  done:
 228         if (is_valid_policy_hnd(&alias_handle)) {
 229                 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
 230         }
 231 
 232         if (ctx->disable_policy_handle_cache) {
 233                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 234                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 235                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
 236         }
 237 
 238         return werr;
 239 }
 240 
 241 /****************************************************************
 242 ****************************************************************/
 243 
 244 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 245                           struct NetLocalGroupAdd *r)
 246 {
 247         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
 248 }
 249 
 250 /****************************************************************
 251 ****************************************************************/
 252 
 253 
 254 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 255                           struct NetLocalGroupDel *r)
 256 {
 257         struct rpc_pipe_client *pipe_cli = NULL;
 258         NTSTATUS status;
 259         WERROR werr;
 260         struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
 261         struct dom_sid2 *domain_sid = NULL;
 262 
 263         if (!r->in.group_name) {
 264                 return WERR_INVALID_PARAM;
 265         }
 266 
 267         ZERO_STRUCT(connect_handle);
 268         ZERO_STRUCT(builtin_handle);
 269         ZERO_STRUCT(domain_handle);
 270         ZERO_STRUCT(alias_handle);
 271 
 272         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 273                                    &ndr_table_samr.syntax_id,
 274                                    &pipe_cli);
 275         if (!W_ERROR_IS_OK(werr)) {
 276                 goto done;
 277         }
 278 
 279         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
 280                                                   SAMR_ACCESS_LOOKUP_DOMAIN |
 281                                                   SAMR_ACCESS_ENUM_DOMAINS,
 282                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 283                                                   &connect_handle,
 284                                                   &builtin_handle);
 285         if (!W_ERROR_IS_OK(werr)) {
 286                 goto done;
 287         }
 288 
 289         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 290                                                       &builtin_handle,
 291                                                       r->in.group_name,
 292                                                       SEC_STD_DELETE,
 293                                                       &alias_handle);
 294 
 295         if (ctx->disable_policy_handle_cache) {
 296                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 297         }
 298 
 299         if (NT_STATUS_IS_OK(status)) {
 300                 goto delete_alias;
 301         }
 302 
 303         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
 304                                           SAMR_ACCESS_ENUM_DOMAINS |
 305                                           SAMR_ACCESS_LOOKUP_DOMAIN,
 306                                           SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
 307                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 308                                           &connect_handle,
 309                                           &domain_handle,
 310                                           &domain_sid);
 311         if (!W_ERROR_IS_OK(werr)) {
 312                 goto done;
 313         }
 314 
 315         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 316                                                       &domain_handle,
 317                                                       r->in.group_name,
 318                                                       SEC_STD_DELETE,
 319                                                       &alias_handle);
 320 
 321         if (ctx->disable_policy_handle_cache) {
 322                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 323         }
 324 
 325         if (!NT_STATUS_IS_OK(status)) {
 326                 werr = ntstatus_to_werror(status);
 327                 goto done;
 328         }
 329 
 330 
 331  delete_alias:
 332         status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
 333                                             &alias_handle);
 334         if (!NT_STATUS_IS_OK(status)) {
 335                 werr = ntstatus_to_werror(status);
 336                 goto done;
 337         }
 338 
 339         ZERO_STRUCT(alias_handle);
 340 
 341         werr = WERR_OK;
 342 
 343  done:
 344         if (is_valid_policy_hnd(&alias_handle)) {
 345                 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
 346         }
 347 
 348         if (ctx->disable_policy_handle_cache) {
 349                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 350                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 351                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
 352         }
 353 
 354         return werr;
 355 }
 356 
 357 /****************************************************************
 358 ****************************************************************/
 359 
 360 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 361                           struct NetLocalGroupDel *r)
 362 {
 363         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
 364 }
 365 
 366 /****************************************************************
 367 ****************************************************************/
 368 
 369 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 370                                        const char *alias_name,
 371                                        struct samr_AliasInfoAll *info,
 372                                        uint32_t level,
 373                                        uint32_t *entries_read,
 374                                        uint8_t **buffer)
 375 {
 376         struct LOCALGROUP_INFO_0 g0;
 377         struct LOCALGROUP_INFO_1 g1;
 378         struct LOCALGROUP_INFO_1002 g1002;
 379 
 380         switch (level) {
 381                 case 0:
 382                         g0.lgrpi0_name          = talloc_strdup(mem_ctx, alias_name);
 383                         W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
 384 
 385                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
 386                                      (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
 387 
 388                         break;
 389                 case 1:
 390                         g1.lgrpi1_name          = talloc_strdup(mem_ctx, alias_name);
 391                         g1.lgrpi1_comment       = talloc_strdup(mem_ctx, info->description.string);
 392                         W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
 393 
 394                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
 395                                      (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
 396 
 397                         break;
 398                 case 1002:
 399                         g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
 400 
 401                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
 402                                      (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
 403 
 404                         break;
 405                 default:
 406                         return WERR_UNKNOWN_LEVEL;
 407         }
 408 
 409         return WERR_OK;
 410 }
 411 
 412 /****************************************************************
 413 ****************************************************************/
 414 
 415 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 416                               struct NetLocalGroupGetInfo *r)
 417 {
 418         struct rpc_pipe_client *pipe_cli = NULL;
 419         NTSTATUS status;
 420         WERROR werr;
 421         struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
 422         struct dom_sid2 *domain_sid = NULL;
 423         union samr_AliasInfo *alias_info = NULL;
 424         uint32_t entries_read = 0;
 425 
 426         if (!r->in.group_name) {
 427                 return WERR_INVALID_PARAM;
 428         }
 429 
 430         switch (r->in.level) {
 431                 case 0:
 432                 case 1:
 433                 case 1002:
 434                         break;
 435                 default:
 436                         return WERR_UNKNOWN_LEVEL;
 437         }
 438 
 439         ZERO_STRUCT(connect_handle);
 440         ZERO_STRUCT(builtin_handle);
 441         ZERO_STRUCT(domain_handle);
 442         ZERO_STRUCT(alias_handle);
 443 
 444         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 445                                    &ndr_table_samr.syntax_id,
 446                                    &pipe_cli);
 447         if (!W_ERROR_IS_OK(werr)) {
 448                 goto done;
 449         }
 450 
 451         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
 452                                                   SAMR_ACCESS_LOOKUP_DOMAIN |
 453                                                   SAMR_ACCESS_ENUM_DOMAINS,
 454                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 455                                                   &connect_handle,
 456                                                   &builtin_handle);
 457         if (!W_ERROR_IS_OK(werr)) {
 458                 goto done;
 459         }
 460 
 461         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 462                                                       &builtin_handle,
 463                                                       r->in.group_name,
 464                                                       SAMR_ALIAS_ACCESS_LOOKUP_INFO,
 465                                                       &alias_handle);
 466 
 467         if (ctx->disable_policy_handle_cache) {
 468                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 469         }
 470 
 471         if (NT_STATUS_IS_OK(status)) {
 472                 goto query_alias;
 473         }
 474 
 475         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
 476                                           SAMR_ACCESS_ENUM_DOMAINS |
 477                                           SAMR_ACCESS_LOOKUP_DOMAIN,
 478                                           SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
 479                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 480                                           &connect_handle,
 481                                           &domain_handle,
 482                                           &domain_sid);
 483         if (!W_ERROR_IS_OK(werr)) {
 484                 goto done;
 485         }
 486 
 487         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 488                                                       &domain_handle,
 489                                                       r->in.group_name,
 490                                                       SAMR_ALIAS_ACCESS_LOOKUP_INFO,
 491                                                       &alias_handle);
 492 
 493         if (ctx->disable_policy_handle_cache) {
 494                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 495         }
 496 
 497         if (!NT_STATUS_IS_OK(status)) {
 498                 werr = ntstatus_to_werror(status);
 499                 goto done;
 500         }
 501 
 502  query_alias:
 503         status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
 504                                             &alias_handle,
 505                                             ALIASINFOALL,
 506                                             &alias_info);
 507         if (!NT_STATUS_IS_OK(status)) {
 508                 werr = ntstatus_to_werror(status);
 509                 goto done;
 510         }
 511 
 512         werr = map_alias_info_to_buffer(ctx,
 513                                         r->in.group_name,
 514                                         &alias_info->all,
 515                                         r->in.level, &entries_read,
 516                                         r->out.buffer);
 517 
 518  done:
 519         if (is_valid_policy_hnd(&alias_handle)) {
 520                 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
 521         }
 522 
 523         if (ctx->disable_policy_handle_cache) {
 524                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 525                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 526                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
 527         }
 528 
 529         return werr;
 530 }
 531 
 532 /****************************************************************
 533 ****************************************************************/
 534 
 535 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 536                               struct NetLocalGroupGetInfo *r)
 537 {
 538         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
 539 }
 540 
 541 /****************************************************************
 542 ****************************************************************/
 543 
 544 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 545                                        uint32_t level,
 546                                        uint8_t *buffer,
 547                                        enum samr_AliasInfoEnum *alias_level,
 548                                        union samr_AliasInfo **alias_info)
 549 {
 550         struct LOCALGROUP_INFO_0 *info0;
 551         struct LOCALGROUP_INFO_1 *info1;
 552         struct LOCALGROUP_INFO_1002 *info1002;
 553         union samr_AliasInfo *info = NULL;
 554 
 555         info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
 556         W_ERROR_HAVE_NO_MEMORY(info);
 557 
 558         switch (level) {
 559                 case 0:
 560                         info0 = (struct LOCALGROUP_INFO_0 *)buffer;
 561                         init_lsa_String(&info->name, info0->lgrpi0_name);
 562                         *alias_level = ALIASINFONAME;
 563                         break;
 564                 case 1:
 565                         info1 = (struct LOCALGROUP_INFO_1 *)buffer;
 566                         /* group name will be ignored */
 567                         init_lsa_String(&info->description, info1->lgrpi1_comment);
 568                         *alias_level = ALIASINFODESCRIPTION;
 569                         break;
 570                 case 1002:
 571                         info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
 572                         init_lsa_String(&info->description, info1002->lgrpi1002_comment);
 573                         *alias_level = ALIASINFODESCRIPTION;
 574                         break;
 575         }
 576 
 577         *alias_info = info;
 578 
 579         return WERR_OK;
 580 }
 581 
 582 /****************************************************************
 583 ****************************************************************/
 584 
 585 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 586                               struct NetLocalGroupSetInfo *r)
 587 {
 588         struct rpc_pipe_client *pipe_cli = NULL;
 589         NTSTATUS status;
 590         WERROR werr;
 591         struct lsa_String lsa_account_name;
 592         struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
 593         struct dom_sid2 *domain_sid = NULL;
 594         enum samr_AliasInfoEnum alias_level = 0;
 595         union samr_AliasInfo *alias_info = NULL;
 596 
 597         if (!r->in.group_name) {
 598                 return WERR_INVALID_PARAM;
 599         }
 600 
 601         switch (r->in.level) {
 602                 case 0:
 603                 case 1:
 604                 case 1002:
 605                         break;
 606                 default:
 607                         return WERR_UNKNOWN_LEVEL;
 608         }
 609 
 610         ZERO_STRUCT(connect_handle);
 611         ZERO_STRUCT(builtin_handle);
 612         ZERO_STRUCT(domain_handle);
 613         ZERO_STRUCT(alias_handle);
 614 
 615         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 616                                    &ndr_table_samr.syntax_id,
 617                                    &pipe_cli);
 618         if (!W_ERROR_IS_OK(werr)) {
 619                 goto done;
 620         }
 621 
 622         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
 623                                                   SAMR_ACCESS_LOOKUP_DOMAIN |
 624                                                   SAMR_ACCESS_ENUM_DOMAINS,
 625                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 626                                                   &connect_handle,
 627                                                   &builtin_handle);
 628         if (!W_ERROR_IS_OK(werr)) {
 629                 goto done;
 630         }
 631 
 632         init_lsa_String(&lsa_account_name, r->in.group_name);
 633 
 634         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 635                                                       &builtin_handle,
 636                                                       r->in.group_name,
 637                                                       SAMR_ALIAS_ACCESS_SET_INFO,
 638                                                       &alias_handle);
 639 
 640         if (ctx->disable_policy_handle_cache) {
 641                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 642         }
 643 
 644         if (NT_STATUS_IS_OK(status)) {
 645                 goto set_alias;
 646         }
 647 
 648         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
 649                                           SAMR_ACCESS_ENUM_DOMAINS |
 650                                           SAMR_ACCESS_LOOKUP_DOMAIN,
 651                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 652                                           &connect_handle,
 653                                           &domain_handle,
 654                                           &domain_sid);
 655         if (!W_ERROR_IS_OK(werr)) {
 656                 goto done;
 657         }
 658 
 659         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
 660                                                       &domain_handle,
 661                                                       r->in.group_name,
 662                                                       SAMR_ALIAS_ACCESS_SET_INFO,
 663                                                       &alias_handle);
 664         if (!NT_STATUS_IS_OK(status)) {
 665                 werr = ntstatus_to_werror(status);
 666                 goto done;
 667         }
 668 
 669         if (ctx->disable_policy_handle_cache) {
 670                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 671         }
 672 
 673  set_alias:
 674 
 675         werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
 676                                         &alias_level, &alias_info);
 677         if (!W_ERROR_IS_OK(werr)) {
 678                 goto done;
 679         }
 680 
 681         status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
 682                                           &alias_handle,
 683                                           alias_level,
 684                                           alias_info);
 685         if (!NT_STATUS_IS_OK(status)) {
 686                 werr = ntstatus_to_werror(status);
 687                 goto done;
 688         }
 689 
 690         werr = WERR_OK;
 691 
 692  done:
 693         if (is_valid_policy_hnd(&alias_handle)) {
 694                 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
 695         }
 696 
 697         if (ctx->disable_policy_handle_cache) {
 698                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 699                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 700                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
 701         }
 702 
 703         return werr;
 704 }
 705 
 706 /****************************************************************
 707 ****************************************************************/
 708 
 709 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 710                               struct NetLocalGroupSetInfo *r)
 711 {
 712         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
 713 }
 714 
 715 /****************************************************************
 716 ****************************************************************/
 717 
 718 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 719                            struct NetLocalGroupEnum *r)
 720 {
 721         struct rpc_pipe_client *pipe_cli = NULL;
 722         NTSTATUS status;
 723         WERROR werr;
 724         struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
 725         struct dom_sid2 *domain_sid = NULL;
 726         uint32_t entries_read = 0;
 727         union samr_DomainInfo *domain_info = NULL;
 728         union samr_DomainInfo *builtin_info = NULL;
 729         struct samr_SamArray *domain_sam_array = NULL;
 730         struct samr_SamArray *builtin_sam_array = NULL;
 731         int i;
 732 
 733         if (!r->out.buffer) {
 734                 return WERR_INVALID_PARAM;
 735         }
 736 
 737         switch (r->in.level) {
 738                 case 0:
 739                 case 1:
 740                         break;
 741                 default:
 742                         return WERR_UNKNOWN_LEVEL;
 743         }
 744 
 745         if (r->out.total_entries) {
 746                 *r->out.total_entries = 0;
 747         }
 748         if (r->out.entries_read) {
 749                 *r->out.entries_read = 0;
 750         }
 751 
 752         ZERO_STRUCT(connect_handle);
 753         ZERO_STRUCT(builtin_handle);
 754         ZERO_STRUCT(domain_handle);
 755         ZERO_STRUCT(alias_handle);
 756 
 757         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 758                                    &ndr_table_samr.syntax_id,
 759                                    &pipe_cli);
 760         if (!W_ERROR_IS_OK(werr)) {
 761                 goto done;
 762         }
 763 
 764         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
 765                                                   SAMR_ACCESS_LOOKUP_DOMAIN |
 766                                                   SAMR_ACCESS_ENUM_DOMAINS,
 767                                                   SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
 768                                                   SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
 769                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 770                                                   &connect_handle,
 771                                                   &builtin_handle);
 772         if (!W_ERROR_IS_OK(werr)) {
 773                 goto done;
 774         }
 775 
 776         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
 777                                           SAMR_ACCESS_LOOKUP_DOMAIN |
 778                                           SAMR_ACCESS_ENUM_DOMAINS,
 779                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
 780                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
 781                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
 782                                           &connect_handle,
 783                                           &domain_handle,
 784                                           &domain_sid);
 785         if (!W_ERROR_IS_OK(werr)) {
 786                 goto done;
 787         }
 788 
 789         status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
 790                                              &builtin_handle,
 791                                              2,
 792                                              &builtin_info);
 793         if (!NT_STATUS_IS_OK(status)) {
 794                 werr = ntstatus_to_werror(status);
 795                 goto done;
 796         }
 797 
 798         if (r->out.total_entries) {
 799                 *r->out.total_entries += builtin_info->general.num_aliases;
 800         }
 801 
 802         status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
 803                                              &domain_handle,
 804                                              2,
 805                                              &domain_info);
 806         if (!NT_STATUS_IS_OK(status)) {
 807                 werr = ntstatus_to_werror(status);
 808                 goto done;
 809         }
 810 
 811         if (r->out.total_entries) {
 812                 *r->out.total_entries += domain_info->general.num_aliases;
 813         }
 814 
 815         status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
 816                                                &builtin_handle,
 817                                                r->in.resume_handle,
 818                                                &builtin_sam_array,
 819                                                r->in.prefmaxlen,
 820                                                &entries_read);
 821         if (!NT_STATUS_IS_OK(status)) {
 822                 werr = ntstatus_to_werror(status);
 823                 goto done;
 824         }
 825 
 826         for (i=0; i<builtin_sam_array->count; i++) {
 827                 union samr_AliasInfo *alias_info = NULL;
 828 
 829                 if (r->in.level == 1) {
 830 
 831                         status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
 832                                                                      &builtin_handle,
 833                                                                      builtin_sam_array->entries[i].idx,
 834                                                                      SAMR_ALIAS_ACCESS_LOOKUP_INFO,
 835                                                                      ALIASINFOALL,
 836                                                                      &alias_info);
 837                         if (!NT_STATUS_IS_OK(status)) {
 838                                 werr = ntstatus_to_werror(status);
 839                                 goto done;
 840                         }
 841                 }
 842 
 843                 werr = map_alias_info_to_buffer(ctx,
 844                                                 builtin_sam_array->entries[i].name.string,
 845                                                 alias_info ? &alias_info->all : NULL,
 846                                                 r->in.level,
 847                                                 r->out.entries_read,
 848                                                 r->out.buffer);
 849         }
 850 
 851         status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
 852                                                &domain_handle,
 853                                                r->in.resume_handle,
 854                                                &domain_sam_array,
 855                                                r->in.prefmaxlen,
 856                                                &entries_read);
 857         if (!NT_STATUS_IS_OK(status)) {
 858                 werr = ntstatus_to_werror(status);
 859                 goto done;
 860         }
 861 
 862         for (i=0; i<domain_sam_array->count; i++) {
 863 
 864                 union samr_AliasInfo *alias_info = NULL;
 865 
 866                 if (r->in.level == 1) {
 867                         status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
 868                                                                      &domain_handle,
 869                                                                      domain_sam_array->entries[i].idx,
 870                                                                      SAMR_ALIAS_ACCESS_LOOKUP_INFO,
 871                                                                      ALIASINFOALL,
 872                                                                      &alias_info);
 873                         if (!NT_STATUS_IS_OK(status)) {
 874                                 werr = ntstatus_to_werror(status);
 875                                 goto done;
 876                         }
 877                 }
 878 
 879                 werr = map_alias_info_to_buffer(ctx,
 880                                                 domain_sam_array->entries[i].name.string,
 881                                                 alias_info ? &alias_info->all : NULL,
 882                                                 r->in.level,
 883                                                 r->out.entries_read,
 884                                                 r->out.buffer);
 885         }
 886 
 887  done:
 888         if (ctx->disable_policy_handle_cache) {
 889                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
 890                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
 891                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
 892         }
 893 
 894         return werr;
 895 }
 896 
 897 /****************************************************************
 898 ****************************************************************/
 899 
 900 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 901                            struct NetLocalGroupEnum *r)
 902 {
 903         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
 904 }
 905 
 906 /****************************************************************
 907 ****************************************************************/
 908 
 909 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 910                                             struct rpc_pipe_client *lsa_pipe,
 911                                             const char *name,
 912                                             struct dom_sid *sid)
 913 {
 914         NTSTATUS status;
 915         struct policy_handle lsa_handle;
 916 
 917         struct lsa_RefDomainList *domains = NULL;
 918         struct lsa_TransSidArray3 sids;
 919         uint32_t count = 0;
 920 
 921         struct lsa_String names;
 922         uint32_t num_names = 1;
 923 
 924         if (!sid || !name) {
 925                 return NT_STATUS_INVALID_PARAMETER;
 926         }
 927 
 928         ZERO_STRUCT(sids);
 929 
 930         init_lsa_String(&names, name);
 931 
 932         status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
 933                                          false,
 934                                          STD_RIGHT_READ_CONTROL_ACCESS |
 935                                          LSA_POLICY_VIEW_LOCAL_INFORMATION |
 936                                          LSA_POLICY_LOOKUP_NAMES,
 937                                          &lsa_handle);
 938         NT_STATUS_NOT_OK_RETURN(status);
 939 
 940         status = rpccli_lsa_LookupNames3(lsa_pipe, mem_ctx,
 941                                          &lsa_handle,
 942                                          num_names,
 943                                          &names,
 944                                          &domains,
 945                                          &sids,
 946                                          LSA_LOOKUP_NAMES_ALL, /* sure ? */
 947                                          &count,
 948                                          0, 0);
 949         NT_STATUS_NOT_OK_RETURN(status);
 950 
 951         if (count != 1 || sids.count != 1) {
 952                 return NT_STATUS_NONE_MAPPED;
 953         }
 954 
 955         sid_copy(sid, sids.sids[0].sid);
 956 
 957         return NT_STATUS_OK;
 958 }
 959 
 960 /****************************************************************
 961 ****************************************************************/
 962 
 963 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 964                                            struct NetLocalGroupAddMembers *add,
 965                                            struct NetLocalGroupDelMembers *del,
 966                                            struct NetLocalGroupSetMembers *set)
 967 {
 968         struct NetLocalGroupAddMembers *r = NULL;
 969 
 970         struct rpc_pipe_client *pipe_cli = NULL;
 971         struct rpc_pipe_client *lsa_pipe = NULL;
 972         NTSTATUS status;
 973         WERROR werr;
 974         struct lsa_String lsa_account_name;
 975         struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
 976         struct dom_sid2 *domain_sid = NULL;
 977         struct dom_sid *member_sids = NULL;
 978         int i = 0, k = 0;
 979 
 980         struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
 981         struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
 982 
 983         struct dom_sid *add_sids = NULL;
 984         struct dom_sid *del_sids = NULL;
 985         size_t num_add_sids = 0;
 986         size_t num_del_sids = 0;
 987 
 988         if ((!add && !del && !set) || (add && del && set)) {
 989                 return WERR_INVALID_PARAM;
 990         }
 991 
 992         if (add) {
 993                 r = add;
 994         }
 995 
 996         if (del) {
 997                 r = (struct NetLocalGroupAddMembers *)del;
 998         }
 999 
1000         if (set) {
1001                 r = (struct NetLocalGroupAddMembers *)set;
1002         }
1003 
1004         if (!r->in.group_name) {
1005                 return WERR_INVALID_PARAM;
1006         }
1007 
1008         switch (r->in.level) {
1009                 case 0:
1010                 case 3:
1011                         break;
1012                 default:
1013                         return WERR_UNKNOWN_LEVEL;
1014         }
1015 
1016         if (r->in.total_entries == 0 || !r->in.buffer) {
1017                 return WERR_INVALID_PARAM;
1018         }
1019 
1020         ZERO_STRUCT(connect_handle);
1021         ZERO_STRUCT(builtin_handle);
1022         ZERO_STRUCT(domain_handle);
1023         ZERO_STRUCT(alias_handle);
1024 
1025         member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
1026                                         r->in.total_entries);
1027         W_ERROR_HAVE_NO_MEMORY(member_sids);
1028 
1029         switch (r->in.level) {
1030                 case 0:
1031                         info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1032                         for (i=0; i < r->in.total_entries; i++) {
1033                                 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1034                         }
1035                         break;
1036                 case 3:
1037                         info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1038                         break;
1039                 default:
1040                         break;
1041         }
1042 
1043         if (r->in.level == 3) {
1044                 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1045                                            &ndr_table_lsarpc.syntax_id,
1046                                            &lsa_pipe);
1047                 if (!W_ERROR_IS_OK(werr)) {
1048                         goto done;
1049                 }
1050 
1051                 for (i=0; i < r->in.total_entries; i++) {
1052                         status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1053                                                              info3[i].lgrmi3_domainandname,
1054                                                              &member_sids[i]);
1055                         if (!NT_STATUS_IS_OK(status)) {
1056                                 werr = ntstatus_to_werror(status);
1057                                 goto done;
1058                         }
1059                 }
1060                 TALLOC_FREE(lsa_pipe);
1061         }
1062 
1063         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1064                                    &ndr_table_samr.syntax_id,
1065                                    &pipe_cli);
1066         if (!W_ERROR_IS_OK(werr)) {
1067                 goto done;
1068         }
1069 
1070         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1071                                                   SAMR_ACCESS_LOOKUP_DOMAIN |
1072                                                   SAMR_ACCESS_ENUM_DOMAINS,
1073                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1074                                                   &connect_handle,
1075                                                   &builtin_handle);
1076         if (!W_ERROR_IS_OK(werr)) {
1077                 goto done;
1078         }
1079 
1080         init_lsa_String(&lsa_account_name, r->in.group_name);
1081 
1082         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1083                                                       &builtin_handle,
1084                                                       r->in.group_name,
1085                                                       SAMR_ALIAS_ACCESS_ADD_MEMBER |
1086                                                       SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1087                                                       SAMR_ALIAS_ACCESS_GET_MEMBERS |
1088                                                       SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1089                                                       &alias_handle);
1090 
1091         if (ctx->disable_policy_handle_cache) {
1092                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1093         }
1094 
1095         if (NT_STATUS_IS_OK(status)) {
1096                 goto modify_membership;
1097         }
1098 
1099         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1100                                           SAMR_ACCESS_ENUM_DOMAINS |
1101                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1102                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1103                                           &connect_handle,
1104                                           &domain_handle,
1105                                           &domain_sid);
1106         if (!W_ERROR_IS_OK(werr)) {
1107                 goto done;
1108         }
1109 
1110         status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1111                                                       &domain_handle,
1112                                                       r->in.group_name,
1113                                                       SAMR_ALIAS_ACCESS_ADD_MEMBER |
1114                                                       SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1115                                                       SAMR_ALIAS_ACCESS_GET_MEMBERS |
1116                                                       SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1117                                                       &alias_handle);
1118         if (!NT_STATUS_IS_OK(status)) {
1119                 werr = ntstatus_to_werror(status);
1120                 goto done;
1121         }
1122 
1123         if (ctx->disable_policy_handle_cache) {
1124                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1125         }
1126 
1127  modify_membership:
1128 
1129         if (add) {
1130                 for (i=0; i < r->in.total_entries; i++) {
1131                         status = add_sid_to_array_unique(ctx, &member_sids[i],
1132                                                          &add_sids,
1133                                                          &num_add_sids);
1134                         if (!NT_STATUS_IS_OK(status)) {
1135                                 werr = ntstatus_to_werror(status);
1136                                 goto done;
1137                         }
1138                 }
1139         }
1140 
1141         if (del) {
1142                 for (i=0; i < r->in.total_entries; i++) {
1143                         status = add_sid_to_array_unique(ctx, &member_sids[i],
1144                                                          &del_sids,
1145                                                          &num_del_sids);
1146                         if (!NT_STATUS_IS_OK(status)) {
1147                                 werr = ntstatus_to_werror(status);
1148                                 goto done;
1149                         }
1150                 }
1151         }
1152 
1153         if (set) {
1154 
1155                 struct lsa_SidArray current_sids;
1156 
1157                 status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx,
1158                                                        &alias_handle,
1159                                                        &current_sids);
1160                 if (!NT_STATUS_IS_OK(status)) {
1161                         werr = ntstatus_to_werror(status);
1162                         goto done;
1163                 }
1164 
1165                 /* add list */
1166 
1167                 for (i=0; i < r->in.total_entries; i++) {
1168                         bool already_member = false;
1169                         for (k=0; k < current_sids.num_sids; k++) {
1170                                 if (sid_equal(&member_sids[i],
1171                                               current_sids.sids[k].sid)) {
1172                                         already_member = true;
1173                                         break;
1174                                 }
1175                         }
1176                         if (!already_member) {
1177                                 status = add_sid_to_array_unique(ctx,
1178                                         &member_sids[i],
1179                                         &add_sids, &num_add_sids);
1180                                 if (!NT_STATUS_IS_OK(status)) {
1181                                         werr = ntstatus_to_werror(status);
1182                                         goto done;
1183                                 }
1184                         }
1185                 }
1186 
1187                 /* del list */
1188 
1189                 for (k=0; k < current_sids.num_sids; k++) {
1190                         bool keep_member = false;
1191                         for (i=0; i < r->in.total_entries; i++) {
1192                                 if (sid_equal(&member_sids[i],
1193                                               current_sids.sids[k].sid)) {
1194                                         keep_member = true;
1195                                         break;
1196                                 }
1197                         }
1198                         if (!keep_member) {
1199                                 status = add_sid_to_array_unique(ctx,
1200                                                 current_sids.sids[k].sid,
1201                                                 &del_sids, &num_del_sids);
1202                                 if (!NT_STATUS_IS_OK(status)) {
1203                                         werr = ntstatus_to_werror(status);
1204                                         goto done;
1205                                 }
1206                         }
1207                 }
1208         }
1209 
1210         /* add list */
1211 
1212         for (i=0; i < num_add_sids; i++) {
1213                 status = rpccli_samr_AddAliasMember(pipe_cli, ctx,
1214                                                     &alias_handle,
1215                                                     &add_sids[i]);
1216                 if (!NT_STATUS_IS_OK(status)) {
1217                         werr = ntstatus_to_werror(status);
1218                         goto done;
1219                 }
1220         }
1221 
1222         /* del list */
1223 
1224         for (i=0; i < num_del_sids; i++) {
1225                 status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx,
1226                                                        &alias_handle,
1227                                                        &del_sids[i]);
1228                 if (!NT_STATUS_IS_OK(status)) {
1229                         werr = ntstatus_to_werror(status);
1230                         goto done;
1231                 }
1232         }
1233 
1234         werr = WERR_OK;
1235 
1236  done:
1237         if (is_valid_policy_hnd(&alias_handle)) {
1238                 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
1239         }
1240 
1241         if (ctx->disable_policy_handle_cache) {
1242                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1243                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1244                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1245         }
1246 
1247         return werr;
1248 }
1249 
1250 /****************************************************************
1251 ****************************************************************/
1252 
1253 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1254                                  struct NetLocalGroupAddMembers *r)
1255 {
1256         return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1257 }
1258 
1259 /****************************************************************
1260 ****************************************************************/
1261 
1262 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1263                                  struct NetLocalGroupAddMembers *r)
1264 {
1265         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1266 }
1267 
1268 /****************************************************************
1269 ****************************************************************/
1270 
1271 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1272                                  struct NetLocalGroupDelMembers *r)
1273 {
1274         return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1275 }
1276 
1277 /****************************************************************
1278 ****************************************************************/
1279 
1280 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1281                                  struct NetLocalGroupDelMembers *r)
1282 {
1283         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1284 }
1285 
1286 /****************************************************************
1287 ****************************************************************/
1288 
1289 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1290                                  struct NetLocalGroupGetMembers *r)
1291 {
1292         return WERR_NOT_SUPPORTED;
1293 }
1294 
1295 /****************************************************************
1296 ****************************************************************/
1297 
1298 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1299                                  struct NetLocalGroupGetMembers *r)
1300 {
1301         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1302 }
1303 
1304 /****************************************************************
1305 ****************************************************************/
1306 
1307 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1308                                  struct NetLocalGroupSetMembers *r)
1309 {
1310         return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1311 }
1312 
1313 /****************************************************************
1314 ****************************************************************/
1315 
1316 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1317                                  struct NetLocalGroupSetMembers *r)
1318 {
1319         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);
1320 }

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