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