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