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