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