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