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