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