netapi: add skeleton for NetGroupEnum().
[mat/samba.git] / source3 / lib / netapi / group.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi Group 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 /****************************************************************
28 ****************************************************************/
29
30 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
31                      struct NetGroupAdd *r)
32 {
33         struct cli_state *cli = NULL;
34         struct rpc_pipe_client *pipe_cli = NULL;
35         NTSTATUS status;
36         WERROR werr;
37         POLICY_HND connect_handle, domain_handle, group_handle;
38         struct lsa_String lsa_group_name;
39         struct dom_sid2 *domain_sid = NULL;
40         uint32_t rid = 0;
41
42         struct GROUP_INFO_0 *info0 = NULL;
43         struct GROUP_INFO_1 *info1 = NULL;
44         struct GROUP_INFO_2 *info2 = NULL;
45         struct GROUP_INFO_3 *info3 = NULL;
46         union samr_GroupInfo info;
47
48         ZERO_STRUCT(connect_handle);
49         ZERO_STRUCT(domain_handle);
50         ZERO_STRUCT(group_handle);
51
52         if (!r->in.buf) {
53                 return WERR_INVALID_PARAM;
54         }
55
56         switch (r->in.level) {
57                 case 0:
58                         info0 = (struct GROUP_INFO_0 *)r->in.buf;
59                         break;
60                 case 1:
61                         info1 = (struct GROUP_INFO_1 *)r->in.buf;
62                         break;
63                 case 2:
64                         info2 = (struct GROUP_INFO_2 *)r->in.buf;
65                         break;
66                 case 3:
67                         info3 = (struct GROUP_INFO_3 *)r->in.buf;
68                         break;
69                 default:
70                         werr = WERR_UNKNOWN_LEVEL;
71                         goto done;
72         }
73
74         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
75         if (!W_ERROR_IS_OK(werr)) {
76                 goto done;
77         }
78
79         werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
80         if (!W_ERROR_IS_OK(werr)) {
81                 goto done;
82         }
83
84         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
85                                           SAMR_ACCESS_ENUM_DOMAINS |
86                                           SAMR_ACCESS_OPEN_DOMAIN,
87                                           SAMR_DOMAIN_ACCESS_CREATE_GROUP |
88                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
89                                           &connect_handle,
90                                           &domain_handle,
91                                           &domain_sid);
92         if (!W_ERROR_IS_OK(werr)) {
93                 goto done;
94         }
95
96         switch (r->in.level) {
97                 case 0:
98                         init_lsa_String(&lsa_group_name, info0->grpi0_name);
99                         break;
100                 case 1:
101                         init_lsa_String(&lsa_group_name, info1->grpi1_name);
102                         break;
103                 case 2:
104                         init_lsa_String(&lsa_group_name, info2->grpi2_name);
105                         break;
106                 case 3:
107                         init_lsa_String(&lsa_group_name, info3->grpi3_name);
108                         break;
109         }
110
111         status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
112                                                &domain_handle,
113                                                &lsa_group_name,
114                                                SEC_STD_DELETE |
115                                                SAMR_GROUP_ACCESS_SET_INFO,
116                                                &group_handle,
117                                                &rid);
118
119         if (!NT_STATUS_IS_OK(status)) {
120                 werr = ntstatus_to_werror(status);
121                 goto done;
122         }
123
124         switch (r->in.level) {
125                 case 1:
126                         if (info1->grpi1_comment) {
127                                 init_lsa_String(&info.description,
128                                                 info1->grpi1_comment);
129
130                                 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
131                                                                   &group_handle,
132                                                                   GROUPINFODESCRIPTION,
133                                                                   &info);
134                         }
135                         break;
136                 case 2:
137                         if (info2->grpi2_comment) {
138                                 init_lsa_String(&info.description,
139                                                 info2->grpi2_comment);
140
141                                 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
142                                                                   &group_handle,
143                                                                   GROUPINFODESCRIPTION,
144                                                                   &info);
145                                 if (!NT_STATUS_IS_OK(status)) {
146                                         werr = ntstatus_to_werror(status);
147                                         goto failed;
148                                 }
149                         }
150
151                         if (info2->grpi2_attributes != 0) {
152                                 info.attributes.attributes = info2->grpi2_attributes;
153                                 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
154                                                                   &group_handle,
155                                                                   GROUPINFOATTRIBUTES,
156                                                                   &info);
157
158                         }
159                         break;
160                 case 3:
161                         if (info3->grpi3_comment) {
162                                 init_lsa_String(&info.description,
163                                                 info3->grpi3_comment);
164
165                                 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
166                                                                   &group_handle,
167                                                                   GROUPINFODESCRIPTION,
168                                                                   &info);
169                                 if (!NT_STATUS_IS_OK(status)) {
170                                         werr = ntstatus_to_werror(status);
171                                         goto failed;
172                                 }
173                         }
174
175                         if (info3->grpi3_attributes != 0) {
176                                 info.attributes.attributes = info3->grpi3_attributes;
177                                 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
178                                                                   &group_handle,
179                                                                   GROUPINFOATTRIBUTES,
180                                                                   &info);
181                         }
182                         break;
183                 default:
184                         break;
185         }
186
187         if (!NT_STATUS_IS_OK(status)) {
188                 werr = ntstatus_to_werror(status);
189                 goto failed;
190         }
191
192         werr = WERR_OK;
193         goto done;
194
195  failed:
196         rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
197                                       &group_handle);
198
199  done:
200         if (!cli) {
201                 return werr;
202         }
203
204         if (is_valid_policy_hnd(&group_handle)) {
205                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
206         }
207         if (is_valid_policy_hnd(&domain_handle)) {
208                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
209         }
210         if (is_valid_policy_hnd(&connect_handle)) {
211                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
212         }
213
214         return werr;
215 }
216
217 /****************************************************************
218 ****************************************************************/
219
220 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
221                      struct NetGroupAdd *r)
222 {
223         return NetGroupAdd_r(ctx, r);
224 }
225
226 /****************************************************************
227 ****************************************************************/
228
229 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
230                      struct NetGroupDel *r)
231 {
232         struct cli_state *cli = NULL;
233         struct rpc_pipe_client *pipe_cli = NULL;
234         NTSTATUS status;
235         WERROR werr;
236         POLICY_HND connect_handle, domain_handle, group_handle;
237         struct lsa_String lsa_group_name;
238         struct dom_sid2 *domain_sid = NULL;
239         int i = 0;
240
241         struct samr_Ids rids;
242         struct samr_Ids types;
243         union samr_GroupInfo *info = NULL;
244         struct samr_RidTypeArray *rid_array = NULL;
245
246         ZERO_STRUCT(connect_handle);
247         ZERO_STRUCT(domain_handle);
248         ZERO_STRUCT(group_handle);
249
250         if (!r->in.group_name) {
251                 return WERR_INVALID_PARAM;
252         }
253
254         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
255         if (!W_ERROR_IS_OK(werr)) {
256                 goto done;
257         }
258
259         werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
260         if (!W_ERROR_IS_OK(werr)) {
261                 goto done;
262         }
263
264         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
265                                           SAMR_ACCESS_ENUM_DOMAINS |
266                                           SAMR_ACCESS_OPEN_DOMAIN,
267                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
268                                           &connect_handle,
269                                           &domain_handle,
270                                           &domain_sid);
271         if (!W_ERROR_IS_OK(werr)) {
272                 goto done;
273         }
274
275         init_lsa_String(&lsa_group_name, r->in.group_name);
276
277         status = rpccli_samr_LookupNames(pipe_cli, ctx,
278                                          &domain_handle,
279                                          1,
280                                          &lsa_group_name,
281                                          &rids,
282                                          &types);
283         if (!NT_STATUS_IS_OK(status)) {
284                 werr = ntstatus_to_werror(status);
285                 goto done;
286         }
287
288         if (types.ids[0] != SID_NAME_DOM_GRP) {
289                 werr = WERR_INVALID_DATATYPE;
290                 goto done;
291         }
292
293         status = rpccli_samr_OpenGroup(pipe_cli, ctx,
294                                        &domain_handle,
295                                        SEC_STD_DELETE |
296                                        SAMR_GROUP_ACCESS_GET_MEMBERS |
297                                        SAMR_GROUP_ACCESS_REMOVE_MEMBER |
298                                        SAMR_GROUP_ACCESS_ADD_MEMBER |
299                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
300                                        rids.ids[0],
301                                        &group_handle);
302         if (!NT_STATUS_IS_OK(status)) {
303                 werr = ntstatus_to_werror(status);
304                 goto done;
305         }
306
307         status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
308                                             &group_handle,
309                                             GROUPINFOATTRIBUTES,
310                                             &info);
311         if (!NT_STATUS_IS_OK(status)) {
312                 werr = ntstatus_to_werror(status);
313                 goto done;
314         }
315
316         if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
317                 werr = WERR_ACCESS_DENIED;
318                 goto done;
319         }
320
321         status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
322                                               &group_handle,
323                                               &rid_array);
324         if (!NT_STATUS_IS_OK(status)) {
325                 werr = ntstatus_to_werror(status);
326                 goto done;
327         }
328
329         {
330         struct lsa_Strings names;
331         struct samr_Ids member_types;
332
333         status = rpccli_samr_LookupRids(pipe_cli, ctx,
334                                         &domain_handle,
335                                         rid_array->count,
336                                         rid_array->rids,
337                                         &names,
338                                         &member_types);
339         if (!NT_STATUS_IS_OK(status)) {
340                 werr = ntstatus_to_werror(status);
341                 goto done;
342         }
343         }
344
345         for (i=0; i < rid_array->count; i++) {
346
347                 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
348                                                        &group_handle,
349                                                        rid_array->rids[i]);
350                 if (!NT_STATUS_IS_OK(status)) {
351                         werr = ntstatus_to_werror(status);
352                         goto done;
353                 }
354         }
355
356         status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
357                                                &group_handle);
358         if (!NT_STATUS_IS_OK(status)) {
359                 werr = ntstatus_to_werror(status);
360                 goto done;
361         }
362
363         ZERO_STRUCT(group_handle);
364
365         werr = WERR_OK;
366
367  done:
368         if (!cli) {
369                 return werr;
370         }
371
372         if (is_valid_policy_hnd(&group_handle)) {
373                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
374         }
375         if (is_valid_policy_hnd(&domain_handle)) {
376                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
377         }
378         if (is_valid_policy_hnd(&connect_handle)) {
379                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
380         }
381
382         return werr;
383 }
384
385 /****************************************************************
386 ****************************************************************/
387
388 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
389                      struct NetGroupDel *r)
390 {
391         return NetGroupDel_r(ctx, r);
392 }
393
394 /****************************************************************
395 ****************************************************************/
396
397 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
398                          struct NetGroupSetInfo *r)
399 {
400         struct cli_state *cli = NULL;
401         struct rpc_pipe_client *pipe_cli = NULL;
402         NTSTATUS status;
403         WERROR werr;
404         POLICY_HND connect_handle, domain_handle, group_handle;
405         struct lsa_String lsa_group_name;
406         struct dom_sid2 *domain_sid = NULL;
407
408         struct samr_Ids rids;
409         struct samr_Ids types;
410         union samr_GroupInfo info;
411         struct GROUP_INFO_0 *g0;
412         struct GROUP_INFO_1 *g1;
413         struct GROUP_INFO_2 *g2;
414         struct GROUP_INFO_3 *g3;
415         struct GROUP_INFO_1002 *g1002;
416         struct GROUP_INFO_1005 *g1005;
417
418         ZERO_STRUCT(connect_handle);
419         ZERO_STRUCT(domain_handle);
420         ZERO_STRUCT(group_handle);
421
422         if (!r->in.group_name) {
423                 return WERR_INVALID_PARAM;
424         }
425
426         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
427         if (!W_ERROR_IS_OK(werr)) {
428                 goto done;
429         }
430
431         werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
432         if (!W_ERROR_IS_OK(werr)) {
433                 goto done;
434         }
435
436         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
437                                           SAMR_ACCESS_ENUM_DOMAINS |
438                                           SAMR_ACCESS_OPEN_DOMAIN,
439                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
440                                           &connect_handle,
441                                           &domain_handle,
442                                           &domain_sid);
443         if (!W_ERROR_IS_OK(werr)) {
444                 goto done;
445         }
446
447         init_lsa_String(&lsa_group_name, r->in.group_name);
448
449         status = rpccli_samr_LookupNames(pipe_cli, ctx,
450                                          &domain_handle,
451                                          1,
452                                          &lsa_group_name,
453                                          &rids,
454                                          &types);
455         if (!NT_STATUS_IS_OK(status)) {
456                 werr = ntstatus_to_werror(status);
457                 goto done;
458         }
459
460         if (types.ids[0] != SID_NAME_DOM_GRP) {
461                 werr = WERR_INVALID_DATATYPE;
462                 goto done;
463         }
464
465         status = rpccli_samr_OpenGroup(pipe_cli, ctx,
466                                        &domain_handle,
467                                        SAMR_GROUP_ACCESS_SET_INFO |
468                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
469                                        rids.ids[0],
470                                        &group_handle);
471         if (!NT_STATUS_IS_OK(status)) {
472                 werr = ntstatus_to_werror(status);
473                 goto done;
474         }
475
476         switch (r->in.level) {
477                 case 0:
478                         g0 = (struct GROUP_INFO_0 *)r->in.buf;
479                         init_lsa_String(&info.name, g0->grpi0_name);
480                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
481                                                           &group_handle,
482                                                           GROUPINFONAME,
483                                                           &info);
484                         break;
485                 case 1:
486                         g1 = (struct GROUP_INFO_1 *)r->in.buf;
487                         init_lsa_String(&info.description, g1->grpi1_comment);
488                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
489                                                           &group_handle,
490                                                           GROUPINFODESCRIPTION,
491                                                           &info);
492                         break;
493                 case 2:
494                         g2 = (struct GROUP_INFO_2 *)r->in.buf;
495                         init_lsa_String(&info.description, g2->grpi2_comment);
496                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
497                                                           &group_handle,
498                                                           GROUPINFODESCRIPTION,
499                                                           &info);
500                         if (!NT_STATUS_IS_OK(status)) {
501                                 werr = ntstatus_to_werror(status);
502                                 goto done;
503                         }
504                         info.attributes.attributes = g2->grpi2_attributes;
505                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
506                                                           &group_handle,
507                                                           GROUPINFOATTRIBUTES,
508                                                           &info);
509                         break;
510                 case 3:
511                         g3 = (struct GROUP_INFO_3 *)r->in.buf;
512                         init_lsa_String(&info.description, g3->grpi3_comment);
513                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
514                                                           &group_handle,
515                                                           GROUPINFODESCRIPTION,
516                                                           &info);
517                         if (!NT_STATUS_IS_OK(status)) {
518                                 werr = ntstatus_to_werror(status);
519                                 goto done;
520                         }
521                         info.attributes.attributes = g3->grpi3_attributes;
522                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
523                                                           &group_handle,
524                                                           GROUPINFOATTRIBUTES,
525                                                           &info);
526                         break;
527                 case 1002:
528                         g1002 = (struct GROUP_INFO_1002 *)r->in.buf;
529                         init_lsa_String(&info.description, g1002->grpi1002_comment);
530                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
531                                                           &group_handle,
532                                                           GROUPINFODESCRIPTION,
533                                                           &info);
534                         break;
535                 case 1005:
536                         g1005 = (struct GROUP_INFO_1005 *)r->in.buf;
537                         info.attributes.attributes = g1005->grpi1005_attributes;
538                         status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
539                                                           &group_handle,
540                                                           GROUPINFOATTRIBUTES,
541                                                           &info);
542                         break;
543                 default:
544                         status = NT_STATUS_INVALID_LEVEL;
545                         break;
546         }
547
548         if (!NT_STATUS_IS_OK(status)) {
549                 werr = ntstatus_to_werror(status);
550                 goto done;
551         }
552
553         werr = WERR_OK;
554
555  done:
556         if (!cli) {
557                 return werr;
558         }
559
560         if (is_valid_policy_hnd(&group_handle)) {
561                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
562         }
563         if (is_valid_policy_hnd(&domain_handle)) {
564                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
565         }
566         if (is_valid_policy_hnd(&connect_handle)) {
567                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
568         }
569
570         return werr;
571 }
572
573 /****************************************************************
574 ****************************************************************/
575
576 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
577                          struct NetGroupSetInfo *r)
578 {
579         return NetGroupSetInfo_r(ctx, r);
580 }
581
582 /****************************************************************
583 ****************************************************************/
584
585 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
586                                        uint32_t level,
587                                        struct samr_GroupInfoAll *info,
588                                        struct dom_sid2 *domain_sid,
589                                        uint32_t rid,
590                                        uint8_t **buffer)
591 {
592         struct GROUP_INFO_0 info0;
593         struct GROUP_INFO_1 info1;
594         struct GROUP_INFO_2 info2;
595         struct GROUP_INFO_3 info3;
596
597         switch (level) {
598                 case 0:
599                         info0.grpi0_name        = info->name.string;
600
601                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
602
603                         break;
604                 case 1:
605                         info1.grpi1_name        = info->name.string;
606                         info1.grpi1_comment     = info->description.string;
607
608                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
609
610                         break;
611                 case 2:
612                         info2.grpi2_name        = info->name.string;
613                         info2.grpi2_comment     = info->description.string;
614                         info2.grpi2_group_id    = rid;
615                         info2.grpi2_attributes  = info->attributes;
616
617                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
618
619                         break;
620                 case 3:
621                         info3.grpi3_name        = info->name.string;
622                         info3.grpi3_comment     = info->description.string;
623                         info3.grpi3_attributes  = info->attributes;
624
625                         if (!sid_compose((struct dom_sid *)&info3.grpi3_group_sid, domain_sid, rid)) {
626                                 return WERR_NOMEM;
627                         }
628
629                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
630
631                         break;
632                 default:
633                         return WERR_UNKNOWN_LEVEL;
634         }
635
636         W_ERROR_HAVE_NO_MEMORY(*buffer);
637
638         return WERR_OK;
639 }
640
641 /****************************************************************
642 ****************************************************************/
643
644 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
645                          struct NetGroupGetInfo *r)
646 {
647         struct cli_state *cli = NULL;
648         struct rpc_pipe_client *pipe_cli = NULL;
649         NTSTATUS status;
650         WERROR werr;
651         POLICY_HND connect_handle, domain_handle, group_handle;
652         struct lsa_String lsa_group_name;
653         struct dom_sid2 *domain_sid = NULL;
654
655         struct samr_Ids rids;
656         struct samr_Ids types;
657         union samr_GroupInfo *info = NULL;
658
659         ZERO_STRUCT(connect_handle);
660         ZERO_STRUCT(domain_handle);
661         ZERO_STRUCT(group_handle);
662
663         if (!r->in.group_name) {
664                 return WERR_INVALID_PARAM;
665         }
666
667         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
668         if (!W_ERROR_IS_OK(werr)) {
669                 goto done;
670         }
671
672         werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
673         if (!W_ERROR_IS_OK(werr)) {
674                 goto done;
675         }
676
677         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
678                                           SAMR_ACCESS_ENUM_DOMAINS |
679                                           SAMR_ACCESS_OPEN_DOMAIN,
680                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
681                                           &connect_handle,
682                                           &domain_handle,
683                                           &domain_sid);
684         if (!W_ERROR_IS_OK(werr)) {
685                 goto done;
686         }
687
688         init_lsa_String(&lsa_group_name, r->in.group_name);
689
690         status = rpccli_samr_LookupNames(pipe_cli, ctx,
691                                          &domain_handle,
692                                          1,
693                                          &lsa_group_name,
694                                          &rids,
695                                          &types);
696         if (!NT_STATUS_IS_OK(status)) {
697                 werr = ntstatus_to_werror(status);
698                 goto done;
699         }
700
701         if (types.ids[0] != SID_NAME_DOM_GRP) {
702                 werr = WERR_INVALID_DATATYPE;
703                 goto done;
704         }
705
706         status = rpccli_samr_OpenGroup(pipe_cli, ctx,
707                                        &domain_handle,
708                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
709                                        rids.ids[0],
710                                        &group_handle);
711         if (!NT_STATUS_IS_OK(status)) {
712                 werr = ntstatus_to_werror(status);
713                 goto done;
714         }
715
716         status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
717                                             &group_handle,
718                                             GROUPINFOALL2,
719                                             &info);
720         if (!NT_STATUS_IS_OK(status)) {
721                 werr = ntstatus_to_werror(status);
722                 goto done;
723         }
724
725         werr = map_group_info_to_buffer(ctx, r->in.level,
726                                         &info->all2, domain_sid, rids.ids[0],
727                                         r->out.buf);
728         if (!W_ERROR_IS_OK(werr)) {
729                 goto done;
730         }
731  done:
732         if (!cli) {
733                 return werr;
734         }
735
736         if (is_valid_policy_hnd(&group_handle)) {
737                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
738         }
739         if (is_valid_policy_hnd(&domain_handle)) {
740                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
741         }
742         if (is_valid_policy_hnd(&connect_handle)) {
743                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
744         }
745
746         return werr;
747 }
748
749 /****************************************************************
750 ****************************************************************/
751
752 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
753                          struct NetGroupGetInfo *r)
754 {
755         return NetGroupGetInfo_r(ctx, r);
756 }
757
758 /****************************************************************
759 ****************************************************************/
760
761 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
762                          struct NetGroupAddUser *r)
763 {
764         struct cli_state *cli = NULL;
765         struct rpc_pipe_client *pipe_cli = NULL;
766         NTSTATUS status;
767         WERROR werr;
768         POLICY_HND connect_handle, domain_handle, group_handle;
769         struct lsa_String lsa_group_name, lsa_user_name;
770         struct dom_sid2 *domain_sid = NULL;
771
772         struct samr_Ids rids;
773         struct samr_Ids types;
774
775         ZERO_STRUCT(connect_handle);
776         ZERO_STRUCT(domain_handle);
777         ZERO_STRUCT(group_handle);
778
779         if (!r->in.group_name) {
780                 return WERR_INVALID_PARAM;
781         }
782
783         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
784         if (!W_ERROR_IS_OK(werr)) {
785                 goto done;
786         }
787
788         werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
789         if (!W_ERROR_IS_OK(werr)) {
790                 goto done;
791         }
792
793         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
794                                           SAMR_ACCESS_ENUM_DOMAINS |
795                                           SAMR_ACCESS_OPEN_DOMAIN,
796                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
797                                           &connect_handle,
798                                           &domain_handle,
799                                           &domain_sid);
800         if (!W_ERROR_IS_OK(werr)) {
801                 goto done;
802         }
803
804         init_lsa_String(&lsa_group_name, r->in.group_name);
805
806         status = rpccli_samr_LookupNames(pipe_cli, ctx,
807                                          &domain_handle,
808                                          1,
809                                          &lsa_group_name,
810                                          &rids,
811                                          &types);
812         if (!NT_STATUS_IS_OK(status)) {
813                 werr = WERR_GROUP_NOT_FOUND;
814                 goto done;
815         }
816
817         if (types.ids[0] != SID_NAME_DOM_GRP) {
818                 werr = WERR_GROUP_NOT_FOUND;
819                 goto done;
820         }
821
822         status = rpccli_samr_OpenGroup(pipe_cli, ctx,
823                                        &domain_handle,
824                                        SAMR_GROUP_ACCESS_ADD_MEMBER,
825                                        rids.ids[0],
826                                        &group_handle);
827         if (!NT_STATUS_IS_OK(status)) {
828                 werr = ntstatus_to_werror(status);
829                 goto done;
830         }
831
832         init_lsa_String(&lsa_user_name, r->in.user_name);
833
834         status = rpccli_samr_LookupNames(pipe_cli, ctx,
835                                          &domain_handle,
836                                          1,
837                                          &lsa_user_name,
838                                          &rids,
839                                          &types);
840         if (!NT_STATUS_IS_OK(status)) {
841                 werr = WERR_USER_NOT_FOUND;
842                 goto done;
843         }
844
845         if (types.ids[0] != SID_NAME_USER) {
846                 werr = WERR_USER_NOT_FOUND;
847                 goto done;
848         }
849
850         status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
851                                             &group_handle,
852                                             rids.ids[0],
853                                             7); /* why ? */
854         if (!NT_STATUS_IS_OK(status)) {
855                 werr = ntstatus_to_werror(status);
856                 goto done;
857         }
858
859         werr = WERR_OK;
860
861  done:
862         if (!cli) {
863                 return werr;
864         }
865
866         if (is_valid_policy_hnd(&group_handle)) {
867                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
868         }
869         if (is_valid_policy_hnd(&domain_handle)) {
870                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
871         }
872         if (is_valid_policy_hnd(&connect_handle)) {
873                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
874         }
875
876         return werr;
877 }
878
879 /****************************************************************
880 ****************************************************************/
881
882 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
883                          struct NetGroupAddUser *r)
884 {
885         return NetGroupAddUser_r(ctx, r);
886 }
887
888 /****************************************************************
889 ****************************************************************/
890
891 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
892                          struct NetGroupDelUser *r)
893 {
894         struct cli_state *cli = NULL;
895         struct rpc_pipe_client *pipe_cli = NULL;
896         NTSTATUS status;
897         WERROR werr;
898         POLICY_HND connect_handle, domain_handle, group_handle;
899         struct lsa_String lsa_group_name, lsa_user_name;
900         struct dom_sid2 *domain_sid = NULL;
901
902         struct samr_Ids rids;
903         struct samr_Ids types;
904
905         ZERO_STRUCT(connect_handle);
906         ZERO_STRUCT(domain_handle);
907         ZERO_STRUCT(group_handle);
908
909         if (!r->in.group_name) {
910                 return WERR_INVALID_PARAM;
911         }
912
913         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
914         if (!W_ERROR_IS_OK(werr)) {
915                 goto done;
916         }
917
918         werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
919         if (!W_ERROR_IS_OK(werr)) {
920                 goto done;
921         }
922
923         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
924                                           SAMR_ACCESS_ENUM_DOMAINS |
925                                           SAMR_ACCESS_OPEN_DOMAIN,
926                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
927                                           &connect_handle,
928                                           &domain_handle,
929                                           &domain_sid);
930         if (!W_ERROR_IS_OK(werr)) {
931                 goto done;
932         }
933
934         init_lsa_String(&lsa_group_name, r->in.group_name);
935
936         status = rpccli_samr_LookupNames(pipe_cli, ctx,
937                                          &domain_handle,
938                                          1,
939                                          &lsa_group_name,
940                                          &rids,
941                                          &types);
942         if (!NT_STATUS_IS_OK(status)) {
943                 werr = WERR_GROUP_NOT_FOUND;
944                 goto done;
945         }
946
947         if (types.ids[0] != SID_NAME_DOM_GRP) {
948                 werr = WERR_GROUP_NOT_FOUND;
949                 goto done;
950         }
951
952         status = rpccli_samr_OpenGroup(pipe_cli, ctx,
953                                        &domain_handle,
954                                        SAMR_GROUP_ACCESS_REMOVE_MEMBER,
955                                        rids.ids[0],
956                                        &group_handle);
957         if (!NT_STATUS_IS_OK(status)) {
958                 werr = ntstatus_to_werror(status);
959                 goto done;
960         }
961
962         init_lsa_String(&lsa_user_name, r->in.user_name);
963
964         status = rpccli_samr_LookupNames(pipe_cli, ctx,
965                                          &domain_handle,
966                                          1,
967                                          &lsa_user_name,
968                                          &rids,
969                                          &types);
970         if (!NT_STATUS_IS_OK(status)) {
971                 werr = WERR_USER_NOT_FOUND;
972                 goto done;
973         }
974
975         if (types.ids[0] != SID_NAME_USER) {
976                 werr = WERR_USER_NOT_FOUND;
977                 goto done;
978         }
979
980         status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
981                                                &group_handle,
982                                                rids.ids[0]);
983         if (!NT_STATUS_IS_OK(status)) {
984                 werr = ntstatus_to_werror(status);
985                 goto done;
986         }
987
988         werr = WERR_OK;
989
990  done:
991         if (!cli) {
992                 return werr;
993         }
994
995         if (is_valid_policy_hnd(&group_handle)) {
996                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
997         }
998         if (is_valid_policy_hnd(&domain_handle)) {
999                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
1000         }
1001         if (is_valid_policy_hnd(&connect_handle)) {
1002                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
1003         }
1004
1005         return werr;
1006 }
1007
1008 /****************************************************************
1009 ****************************************************************/
1010
1011 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1012                          struct NetGroupDelUser *r)
1013 {
1014         return NetGroupDelUser_r(ctx, r);
1015 }
1016
1017 /****************************************************************
1018 ****************************************************************/
1019
1020 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1021                       struct NetGroupEnum *r)
1022 {
1023         return WERR_NOT_SUPPORTED;
1024 }
1025
1026 /****************************************************************
1027 ****************************************************************/
1028
1029 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1030                       struct NetGroupEnum *r)
1031 {
1032         return WERR_NOT_SUPPORTED;
1033 }