werror: replace WERR_GROUPNOTFOUND with WERR_NERR_GROUPNOTFOUND in source3/lib/netapi...
[metze/samba/wip.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 #include "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
30
31 /****************************************************************
32 ****************************************************************/
33
34 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
35                      struct NetGroupAdd *r)
36 {
37         struct rpc_pipe_client *pipe_cli = NULL;
38         NTSTATUS status, result;
39         WERROR werr;
40         struct policy_handle connect_handle, domain_handle, group_handle;
41         struct lsa_String lsa_group_name;
42         struct dom_sid2 *domain_sid = NULL;
43         uint32_t rid = 0;
44         struct dcerpc_binding_handle *b = NULL;
45
46         struct GROUP_INFO_0 *info0 = NULL;
47         struct GROUP_INFO_1 *info1 = NULL;
48         struct GROUP_INFO_2 *info2 = NULL;
49         struct GROUP_INFO_3 *info3 = NULL;
50         union samr_GroupInfo info;
51
52         ZERO_STRUCT(connect_handle);
53         ZERO_STRUCT(domain_handle);
54         ZERO_STRUCT(group_handle);
55
56         if (!r->in.buffer) {
57                 return WERR_INVALID_PARAMETER;
58         }
59
60         switch (r->in.level) {
61                 case 0:
62                         info0 = (struct GROUP_INFO_0 *)r->in.buffer;
63                         break;
64                 case 1:
65                         info1 = (struct GROUP_INFO_1 *)r->in.buffer;
66                         break;
67                 case 2:
68                         info2 = (struct GROUP_INFO_2 *)r->in.buffer;
69                         break;
70                 case 3:
71                         info3 = (struct GROUP_INFO_3 *)r->in.buffer;
72                         break;
73                 default:
74                         werr = WERR_UNKNOWN_LEVEL;
75                         goto done;
76         }
77
78         werr = libnetapi_open_pipe(ctx, r->in.server_name,
79                                    &ndr_table_samr,
80                                    &pipe_cli);
81         if (!W_ERROR_IS_OK(werr)) {
82                 goto done;
83         }
84
85         b = pipe_cli->binding_handle;
86
87         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
88                                           SAMR_ACCESS_ENUM_DOMAINS |
89                                           SAMR_ACCESS_LOOKUP_DOMAIN,
90                                           SAMR_DOMAIN_ACCESS_CREATE_GROUP |
91                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
92                                           &connect_handle,
93                                           &domain_handle,
94                                           &domain_sid);
95         if (!W_ERROR_IS_OK(werr)) {
96                 goto done;
97         }
98
99         switch (r->in.level) {
100                 case 0:
101                         init_lsa_String(&lsa_group_name, info0->grpi0_name);
102                         break;
103                 case 1:
104                         init_lsa_String(&lsa_group_name, info1->grpi1_name);
105                         break;
106                 case 2:
107                         init_lsa_String(&lsa_group_name, info2->grpi2_name);
108                         break;
109                 case 3:
110                         init_lsa_String(&lsa_group_name, info3->grpi3_name);
111                         break;
112         }
113
114         status = dcerpc_samr_CreateDomainGroup(b, talloc_tos(),
115                                                &domain_handle,
116                                                &lsa_group_name,
117                                                SEC_STD_DELETE |
118                                                SAMR_GROUP_ACCESS_SET_INFO,
119                                                &group_handle,
120                                                &rid,
121                                                &result);
122
123         if (!NT_STATUS_IS_OK(status)) {
124                 werr = ntstatus_to_werror(status);
125                 goto done;
126         }
127         if (!NT_STATUS_IS_OK(result)) {
128                 werr = ntstatus_to_werror(result);
129                 goto done;
130         }
131
132         switch (r->in.level) {
133                 case 1:
134                         if (info1->grpi1_comment) {
135                                 init_lsa_String(&info.description,
136                                                 info1->grpi1_comment);
137
138                                 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
139                                                                   &group_handle,
140                                                                   GROUPINFODESCRIPTION,
141                                                                   &info,
142                                                                   &result);
143                         }
144                         break;
145                 case 2:
146                         if (info2->grpi2_comment) {
147                                 init_lsa_String(&info.description,
148                                                 info2->grpi2_comment);
149
150                                 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
151                                                                   &group_handle,
152                                                                   GROUPINFODESCRIPTION,
153                                                                   &info,
154                                                                   &result);
155                                 if (!NT_STATUS_IS_OK(status)) {
156                                         werr = ntstatus_to_werror(status);
157                                         goto failed;
158                                 }
159                                 if (!NT_STATUS_IS_OK(result)) {
160                                         werr = ntstatus_to_werror(result);
161                                         goto failed;
162                                 }
163                         }
164
165                         if (info2->grpi2_attributes != 0) {
166                                 info.attributes.attributes = info2->grpi2_attributes;
167                                 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
168                                                                   &group_handle,
169                                                                   GROUPINFOATTRIBUTES,
170                                                                   &info,
171                                                                   &result);
172
173                         }
174                         break;
175                 case 3:
176                         if (info3->grpi3_comment) {
177                                 init_lsa_String(&info.description,
178                                                 info3->grpi3_comment);
179
180                                 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
181                                                                   &group_handle,
182                                                                   GROUPINFODESCRIPTION,
183                                                                   &info,
184                                                                   &result);
185                                 if (!NT_STATUS_IS_OK(status)) {
186                                         werr = ntstatus_to_werror(status);
187                                         goto failed;
188                                 }
189                                 if (!NT_STATUS_IS_OK(result)) {
190                                         werr = ntstatus_to_werror(result);
191                                         goto failed;
192                                 }
193                         }
194
195                         if (info3->grpi3_attributes != 0) {
196                                 info.attributes.attributes = info3->grpi3_attributes;
197                                 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
198                                                                   &group_handle,
199                                                                   GROUPINFOATTRIBUTES,
200                                                                   &info,
201                                                                   &result);
202                         }
203                         break;
204                 default:
205                         break;
206         }
207
208         if (!NT_STATUS_IS_OK(status)) {
209                 werr = ntstatus_to_werror(status);
210                 goto failed;
211         }
212         if (!NT_STATUS_IS_OK(result)) {
213                 werr = ntstatus_to_werror(result);
214                 goto failed;
215         }
216
217         werr = WERR_OK;
218         goto done;
219
220  failed:
221         dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
222                                       &group_handle, &result);
223
224  done:
225         if (is_valid_policy_hnd(&group_handle)) {
226                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
227         }
228
229         if (ctx->disable_policy_handle_cache) {
230                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
231                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
232         }
233
234         return werr;
235 }
236
237 /****************************************************************
238 ****************************************************************/
239
240 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
241                      struct NetGroupAdd *r)
242 {
243         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
244 }
245
246 /****************************************************************
247 ****************************************************************/
248
249 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
250                      struct NetGroupDel *r)
251 {
252         struct rpc_pipe_client *pipe_cli = NULL;
253         NTSTATUS status, result;
254         WERROR werr;
255         struct policy_handle connect_handle, domain_handle, group_handle;
256         struct lsa_String lsa_group_name;
257         struct dom_sid2 *domain_sid = NULL;
258         int i = 0;
259         struct dcerpc_binding_handle *b = NULL;
260
261         struct samr_Ids rids;
262         struct samr_Ids types;
263         union samr_GroupInfo *info = NULL;
264         struct samr_RidAttrArray *rid_array = NULL;
265
266         ZERO_STRUCT(connect_handle);
267         ZERO_STRUCT(domain_handle);
268         ZERO_STRUCT(group_handle);
269
270         if (!r->in.group_name) {
271                 return WERR_INVALID_PARAMETER;
272         }
273
274         werr = libnetapi_open_pipe(ctx, r->in.server_name,
275                                    &ndr_table_samr,
276                                    &pipe_cli);
277         if (!W_ERROR_IS_OK(werr)) {
278                 goto done;
279         }
280
281         b = pipe_cli->binding_handle;
282
283         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
284                                           SAMR_ACCESS_ENUM_DOMAINS |
285                                           SAMR_ACCESS_LOOKUP_DOMAIN,
286                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
287                                           &connect_handle,
288                                           &domain_handle,
289                                           &domain_sid);
290         if (!W_ERROR_IS_OK(werr)) {
291                 goto done;
292         }
293
294         init_lsa_String(&lsa_group_name, r->in.group_name);
295
296         status = dcerpc_samr_LookupNames(b, talloc_tos(),
297                                          &domain_handle,
298                                          1,
299                                          &lsa_group_name,
300                                          &rids,
301                                          &types,
302                                          &result);
303         if (!NT_STATUS_IS_OK(status)) {
304                 werr = ntstatus_to_werror(status);
305                 goto done;
306         }
307         if (!NT_STATUS_IS_OK(result)) {
308                 werr = ntstatus_to_werror(result);
309                 goto done;
310         }
311
312         if (rids.count != 1) {
313                 werr = WERR_BAD_NET_RESP;
314                 goto done;
315         }
316         if (types.count != 1) {
317                 werr = WERR_BAD_NET_RESP;
318                 goto done;
319         }
320
321         if (types.ids[0] != SID_NAME_DOM_GRP) {
322                 werr = WERR_INVALID_DATATYPE;
323                 goto done;
324         }
325
326         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
327                                        &domain_handle,
328                                        SEC_STD_DELETE |
329                                        SAMR_GROUP_ACCESS_GET_MEMBERS |
330                                        SAMR_GROUP_ACCESS_REMOVE_MEMBER |
331                                        SAMR_GROUP_ACCESS_ADD_MEMBER |
332                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
333                                        rids.ids[0],
334                                        &group_handle,
335                                        &result);
336         if (!NT_STATUS_IS_OK(status)) {
337                 werr = ntstatus_to_werror(status);
338                 goto done;
339         }
340         if (!NT_STATUS_IS_OK(result)) {
341                 werr = ntstatus_to_werror(result);
342                 goto done;
343         }
344
345         status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
346                                             &group_handle,
347                                             GROUPINFOATTRIBUTES,
348                                             &info,
349                                             &result);
350         if (!NT_STATUS_IS_OK(status)) {
351                 werr = ntstatus_to_werror(status);
352                 goto done;
353         }
354         if (!NT_STATUS_IS_OK(result)) {
355                 werr = ntstatus_to_werror(result);
356                 goto done;
357         }
358
359 #if 0
360         /* breaks against NT4 */
361         if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
362                 werr = WERR_ACCESS_DENIED;
363                 goto done;
364         }
365 #endif
366         status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
367                                               &group_handle,
368                                               &rid_array,
369                                               &result);
370         if (!NT_STATUS_IS_OK(status)) {
371                 werr = ntstatus_to_werror(status);
372                 goto done;
373         }
374         if (!NT_STATUS_IS_OK(result)) {
375                 werr = ntstatus_to_werror(result);
376                 goto done;
377         }
378
379         {
380         struct lsa_Strings names;
381         struct samr_Ids member_types;
382
383         status = dcerpc_samr_LookupRids(b, talloc_tos(),
384                                         &domain_handle,
385                                         rid_array->count,
386                                         rid_array->rids,
387                                         &names,
388                                         &member_types,
389                                         &result);
390         if (!NT_STATUS_IS_OK(status)) {
391                 werr = ntstatus_to_werror(status);
392                 goto done;
393         }
394         if (!NT_STATUS_IS_OK(result)) {
395                 werr = ntstatus_to_werror(result);
396                 goto done;
397         }
398         if (names.count != rid_array->count) {
399                 werr = WERR_BAD_NET_RESP;
400                 goto done;
401         }
402         if (member_types.count != rid_array->count) {
403                 werr = WERR_BAD_NET_RESP;
404                 goto done;
405         }
406         }
407
408         for (i=0; i < rid_array->count; i++) {
409
410                 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
411                                                        &group_handle,
412                                                        rid_array->rids[i],
413                                                        &result);
414                 if (!NT_STATUS_IS_OK(status)) {
415                         werr = ntstatus_to_werror(status);
416                         goto done;
417                 }
418                 if (!NT_STATUS_IS_OK(result)) {
419                         werr = ntstatus_to_werror(result);
420                         goto done;
421                 }
422         }
423
424         status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
425                                                &group_handle,
426                                                &result);
427         if (!NT_STATUS_IS_OK(status)) {
428                 werr = ntstatus_to_werror(status);
429                 goto done;
430         }
431         if (!NT_STATUS_IS_OK(result)) {
432                 werr = ntstatus_to_werror(result);
433                 goto done;
434         }
435
436         ZERO_STRUCT(group_handle);
437
438         werr = WERR_OK;
439
440  done:
441         if (is_valid_policy_hnd(&group_handle)) {
442                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
443         }
444
445         if (ctx->disable_policy_handle_cache) {
446                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
447                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
448         }
449
450         return werr;
451 }
452
453 /****************************************************************
454 ****************************************************************/
455
456 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
457                      struct NetGroupDel *r)
458 {
459         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
460 }
461
462 /****************************************************************
463 ****************************************************************/
464
465 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
466                          struct NetGroupSetInfo *r)
467 {
468         struct rpc_pipe_client *pipe_cli = NULL;
469         NTSTATUS status, result;
470         WERROR werr;
471         struct policy_handle connect_handle, domain_handle, group_handle;
472         struct lsa_String lsa_group_name;
473         struct dom_sid2 *domain_sid = NULL;
474         struct dcerpc_binding_handle *b = NULL;
475
476         struct samr_Ids rids;
477         struct samr_Ids types;
478         union samr_GroupInfo info;
479         struct GROUP_INFO_0 *g0;
480         struct GROUP_INFO_1 *g1;
481         struct GROUP_INFO_2 *g2;
482         struct GROUP_INFO_3 *g3;
483         struct GROUP_INFO_1002 *g1002;
484         struct GROUP_INFO_1005 *g1005;
485
486         ZERO_STRUCT(connect_handle);
487         ZERO_STRUCT(domain_handle);
488         ZERO_STRUCT(group_handle);
489
490         if (!r->in.group_name) {
491                 return WERR_INVALID_PARAMETER;
492         }
493
494         werr = libnetapi_open_pipe(ctx, r->in.server_name,
495                                    &ndr_table_samr,
496                                    &pipe_cli);
497         if (!W_ERROR_IS_OK(werr)) {
498                 goto done;
499         }
500
501         b = pipe_cli->binding_handle;
502
503         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
504                                           SAMR_ACCESS_ENUM_DOMAINS |
505                                           SAMR_ACCESS_LOOKUP_DOMAIN,
506                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
507                                           &connect_handle,
508                                           &domain_handle,
509                                           &domain_sid);
510         if (!W_ERROR_IS_OK(werr)) {
511                 goto done;
512         }
513
514         init_lsa_String(&lsa_group_name, r->in.group_name);
515
516         status = dcerpc_samr_LookupNames(b, talloc_tos(),
517                                          &domain_handle,
518                                          1,
519                                          &lsa_group_name,
520                                          &rids,
521                                          &types,
522                                          &result);
523         if (!NT_STATUS_IS_OK(status)) {
524                 werr = ntstatus_to_werror(status);
525                 goto done;
526         }
527         if (!NT_STATUS_IS_OK(result)) {
528                 werr = ntstatus_to_werror(result);
529                 goto done;
530         }
531         if (rids.count != 1) {
532                 werr = WERR_BAD_NET_RESP;
533                 goto done;
534         }
535         if (types.count != 1) {
536                 werr = WERR_BAD_NET_RESP;
537                 goto done;
538         }
539
540         if (types.ids[0] != SID_NAME_DOM_GRP) {
541                 werr = WERR_INVALID_DATATYPE;
542                 goto done;
543         }
544
545         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
546                                        &domain_handle,
547                                        SAMR_GROUP_ACCESS_SET_INFO |
548                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
549                                        rids.ids[0],
550                                        &group_handle,
551                                        &result);
552         if (!NT_STATUS_IS_OK(status)) {
553                 werr = ntstatus_to_werror(status);
554                 goto done;
555         }
556         if (!NT_STATUS_IS_OK(result)) {
557                 werr = ntstatus_to_werror(result);
558                 goto done;
559         }
560
561         switch (r->in.level) {
562                 case 0:
563                         g0 = (struct GROUP_INFO_0 *)r->in.buffer;
564                         init_lsa_String(&info.name, g0->grpi0_name);
565                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
566                                                           &group_handle,
567                                                           GROUPINFONAME,
568                                                           &info,
569                                                           &result);
570                         break;
571                 case 1:
572                         g1 = (struct GROUP_INFO_1 *)r->in.buffer;
573                         init_lsa_String(&info.description, g1->grpi1_comment);
574                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
575                                                           &group_handle,
576                                                           GROUPINFODESCRIPTION,
577                                                           &info,
578                                                           &result);
579                         break;
580                 case 2:
581                         g2 = (struct GROUP_INFO_2 *)r->in.buffer;
582                         init_lsa_String(&info.description, g2->grpi2_comment);
583                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
584                                                           &group_handle,
585                                                           GROUPINFODESCRIPTION,
586                                                           &info,
587                                                           &result);
588                         if (!NT_STATUS_IS_OK(status)) {
589                                 werr = ntstatus_to_werror(status);
590                                 goto done;
591                         }
592                         if (!NT_STATUS_IS_OK(result)) {
593                                 werr = ntstatus_to_werror(result);
594                                 goto done;
595                         }
596
597                         info.attributes.attributes = g2->grpi2_attributes;
598                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
599                                                           &group_handle,
600                                                           GROUPINFOATTRIBUTES,
601                                                           &info,
602                                                           &result);
603                         break;
604                 case 3:
605                         g3 = (struct GROUP_INFO_3 *)r->in.buffer;
606                         init_lsa_String(&info.description, g3->grpi3_comment);
607                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
608                                                           &group_handle,
609                                                           GROUPINFODESCRIPTION,
610                                                           &info,
611                                                           &result);
612                         if (!NT_STATUS_IS_OK(status)) {
613                                 werr = ntstatus_to_werror(status);
614                                 goto done;
615                         }
616                         if (!NT_STATUS_IS_OK(result)) {
617                                 werr = ntstatus_to_werror(result);
618                                 goto done;
619                         }
620
621                         info.attributes.attributes = g3->grpi3_attributes;
622                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
623                                                           &group_handle,
624                                                           GROUPINFOATTRIBUTES,
625                                                           &info,
626                                                           &result);
627                         break;
628                 case 1002:
629                         g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
630                         init_lsa_String(&info.description, g1002->grpi1002_comment);
631                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
632                                                           &group_handle,
633                                                           GROUPINFODESCRIPTION,
634                                                           &info,
635                                                           &result);
636                         break;
637                 case 1005:
638                         g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
639                         info.attributes.attributes = g1005->grpi1005_attributes;
640                         status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
641                                                           &group_handle,
642                                                           GROUPINFOATTRIBUTES,
643                                                           &info,
644                                                           &result);
645                         break;
646                 default:
647                         status = NT_STATUS_INVALID_LEVEL;
648                         break;
649         }
650
651         if (!NT_STATUS_IS_OK(status)) {
652                 werr = ntstatus_to_werror(status);
653                 goto done;
654         }
655         if (!NT_STATUS_IS_OK(result)) {
656                 werr = ntstatus_to_werror(result);
657                 goto done;
658         }
659
660         werr = WERR_OK;
661
662  done:
663         if (is_valid_policy_hnd(&group_handle)) {
664                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
665         }
666
667         if (ctx->disable_policy_handle_cache) {
668                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
669                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
670         }
671
672         return werr;
673 }
674
675 /****************************************************************
676 ****************************************************************/
677
678 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
679                          struct NetGroupSetInfo *r)
680 {
681         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
682 }
683
684 /****************************************************************
685 ****************************************************************/
686
687 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
688                                        uint32_t level,
689                                        struct samr_GroupInfoAll *info,
690                                        struct dom_sid2 *domain_sid,
691                                        uint32_t rid,
692                                        uint8_t **buffer)
693 {
694         struct GROUP_INFO_0 info0;
695         struct GROUP_INFO_1 info1;
696         struct GROUP_INFO_2 info2;
697         struct GROUP_INFO_3 info3;
698         struct dom_sid sid;
699
700         switch (level) {
701                 case 0:
702                         info0.grpi0_name        = info->name.string;
703
704                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
705
706                         break;
707                 case 1:
708                         info1.grpi1_name        = info->name.string;
709                         info1.grpi1_comment     = info->description.string;
710
711                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
712
713                         break;
714                 case 2:
715                         info2.grpi2_name        = info->name.string;
716                         info2.grpi2_comment     = info->description.string;
717                         info2.grpi2_group_id    = rid;
718                         info2.grpi2_attributes  = info->attributes;
719
720                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
721
722                         break;
723                 case 3:
724                         if (!sid_compose(&sid, domain_sid, rid)) {
725                                 return WERR_NOT_ENOUGH_MEMORY;
726                         }
727
728                         info3.grpi3_name        = info->name.string;
729                         info3.grpi3_comment     = info->description.string;
730                         info3.grpi3_attributes  = info->attributes;
731                         info3.grpi3_group_sid   = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
732
733                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
734
735                         break;
736                 default:
737                         return WERR_UNKNOWN_LEVEL;
738         }
739
740         W_ERROR_HAVE_NO_MEMORY(*buffer);
741
742         return WERR_OK;
743 }
744
745 /****************************************************************
746 ****************************************************************/
747
748 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
749                          struct NetGroupGetInfo *r)
750 {
751         struct rpc_pipe_client *pipe_cli = NULL;
752         NTSTATUS status, result;
753         WERROR werr;
754         struct policy_handle connect_handle, domain_handle, group_handle;
755         struct lsa_String lsa_group_name;
756         struct dom_sid2 *domain_sid = NULL;
757         struct dcerpc_binding_handle *b = NULL;
758
759         struct samr_Ids rids;
760         struct samr_Ids types;
761         union samr_GroupInfo *info = NULL;
762         bool group_info_all = false;
763
764         ZERO_STRUCT(connect_handle);
765         ZERO_STRUCT(domain_handle);
766         ZERO_STRUCT(group_handle);
767
768         if (!r->in.group_name) {
769                 return WERR_INVALID_PARAMETER;
770         }
771
772         werr = libnetapi_open_pipe(ctx, r->in.server_name,
773                                    &ndr_table_samr,
774                                    &pipe_cli);
775         if (!W_ERROR_IS_OK(werr)) {
776                 goto done;
777         }
778
779         b = pipe_cli->binding_handle;
780
781         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
782                                           SAMR_ACCESS_ENUM_DOMAINS |
783                                           SAMR_ACCESS_LOOKUP_DOMAIN,
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         init_lsa_String(&lsa_group_name, r->in.group_name);
793
794         status = dcerpc_samr_LookupNames(b, talloc_tos(),
795                                          &domain_handle,
796                                          1,
797                                          &lsa_group_name,
798                                          &rids,
799                                          &types,
800                                          &result);
801         if (!NT_STATUS_IS_OK(status)) {
802                 werr = ntstatus_to_werror(status);
803                 goto done;
804         }
805         if (!NT_STATUS_IS_OK(result)) {
806                 werr = ntstatus_to_werror(result);
807                 goto done;
808         }
809         if (rids.count != 1) {
810                 werr = WERR_BAD_NET_RESP;
811                 goto done;
812         }
813         if (types.count != 1) {
814                 werr = WERR_BAD_NET_RESP;
815                 goto done;
816         }
817
818         if (types.ids[0] != SID_NAME_DOM_GRP) {
819                 werr = WERR_INVALID_DATATYPE;
820                 goto done;
821         }
822
823         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
824                                        &domain_handle,
825                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
826                                        rids.ids[0],
827                                        &group_handle,
828                                        &result);
829         if (!NT_STATUS_IS_OK(status)) {
830                 werr = ntstatus_to_werror(status);
831                 goto done;
832         }
833         if (!NT_STATUS_IS_OK(result)) {
834                 werr = ntstatus_to_werror(result);
835                 goto done;
836         }
837
838         status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
839                                             &group_handle,
840                                             GROUPINFOALL2,
841                                             &info,
842                                             &result);
843         if (!NT_STATUS_IS_OK(status)) {
844                 werr = ntstatus_to_werror(status);
845                 goto done;
846         }
847
848         if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
849                 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
850                                                     &group_handle,
851                                                     GROUPINFOALL,
852                                                     &info,
853                                                     &result);
854                 group_info_all = true;
855                 if (!NT_STATUS_IS_OK(status)) {
856                         werr = ntstatus_to_werror(status);
857                         goto done;
858                 }
859         }
860
861         if (!NT_STATUS_IS_OK(result)) {
862                 werr = ntstatus_to_werror(result);
863                 goto done;
864         }
865
866         werr = map_group_info_to_buffer(ctx, r->in.level,
867                                         group_info_all ? &info->all : &info->all2,
868                                         domain_sid, rids.ids[0],
869                                         r->out.buffer);
870         if (!W_ERROR_IS_OK(werr)) {
871                 goto done;
872         }
873  done:
874         if (is_valid_policy_hnd(&group_handle)) {
875                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
876         }
877
878         if (ctx->disable_policy_handle_cache) {
879                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
880                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
881         }
882
883         return werr;
884 }
885
886 /****************************************************************
887 ****************************************************************/
888
889 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
890                          struct NetGroupGetInfo *r)
891 {
892         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
893 }
894
895 /****************************************************************
896 ****************************************************************/
897
898 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
899                          struct NetGroupAddUser *r)
900 {
901         struct rpc_pipe_client *pipe_cli = NULL;
902         NTSTATUS status, result;
903         WERROR werr;
904         struct policy_handle connect_handle, domain_handle, group_handle;
905         struct lsa_String lsa_group_name, lsa_user_name;
906         struct dom_sid2 *domain_sid = NULL;
907         struct dcerpc_binding_handle *b = NULL;
908
909         struct samr_Ids rids;
910         struct samr_Ids types;
911
912         ZERO_STRUCT(connect_handle);
913         ZERO_STRUCT(domain_handle);
914         ZERO_STRUCT(group_handle);
915
916         if (!r->in.group_name) {
917                 return WERR_INVALID_PARAMETER;
918         }
919
920         werr = libnetapi_open_pipe(ctx, r->in.server_name,
921                                    &ndr_table_samr,
922                                    &pipe_cli);
923         if (!W_ERROR_IS_OK(werr)) {
924                 goto done;
925         }
926
927         b = pipe_cli->binding_handle;
928
929         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
930                                           SAMR_ACCESS_ENUM_DOMAINS |
931                                           SAMR_ACCESS_LOOKUP_DOMAIN,
932                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
933                                           &connect_handle,
934                                           &domain_handle,
935                                           &domain_sid);
936         if (!W_ERROR_IS_OK(werr)) {
937                 goto done;
938         }
939
940         init_lsa_String(&lsa_group_name, r->in.group_name);
941
942         status = dcerpc_samr_LookupNames(b, talloc_tos(),
943                                          &domain_handle,
944                                          1,
945                                          &lsa_group_name,
946                                          &rids,
947                                          &types,
948                                          &result);
949         if (!NT_STATUS_IS_OK(status)) {
950                 werr = ntstatus_to_werror(status);
951                 goto done;
952         }
953         if (!NT_STATUS_IS_OK(result)) {
954                 werr = WERR_NERR_GROUPNOTFOUND;
955                 goto done;
956         }
957         if (rids.count != 1) {
958                 werr = WERR_BAD_NET_RESP;
959                 goto done;
960         }
961         if (types.count != 1) {
962                 werr = WERR_BAD_NET_RESP;
963                 goto done;
964         }
965
966         if (types.ids[0] != SID_NAME_DOM_GRP) {
967                 werr = WERR_NERR_GROUPNOTFOUND;
968                 goto done;
969         }
970
971         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
972                                        &domain_handle,
973                                        SAMR_GROUP_ACCESS_ADD_MEMBER,
974                                        rids.ids[0],
975                                        &group_handle,
976                                        &result);
977         if (!NT_STATUS_IS_OK(status)) {
978                 werr = ntstatus_to_werror(status);
979                 goto done;
980         }
981         if (!NT_STATUS_IS_OK(result)) {
982                 werr = ntstatus_to_werror(result);
983                 goto done;
984         }
985
986         init_lsa_String(&lsa_user_name, r->in.user_name);
987
988         status = dcerpc_samr_LookupNames(b, talloc_tos(),
989                                          &domain_handle,
990                                          1,
991                                          &lsa_user_name,
992                                          &rids,
993                                          &types,
994                                          &result);
995         if (!NT_STATUS_IS_OK(status)) {
996                 werr = ntstatus_to_werror(status);
997                 goto done;
998         }
999         if (!NT_STATUS_IS_OK(result)) {
1000                 werr = WERR_USER_NOT_FOUND;
1001                 goto done;
1002         }
1003         if (rids.count != 1) {
1004                 werr = WERR_BAD_NET_RESP;
1005                 goto done;
1006         }
1007         if (types.count != 1) {
1008                 werr = WERR_BAD_NET_RESP;
1009                 goto done;
1010         }
1011
1012         if (types.ids[0] != SID_NAME_USER) {
1013                 werr = WERR_USER_NOT_FOUND;
1014                 goto done;
1015         }
1016
1017         status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1018                                             &group_handle,
1019                                             rids.ids[0],
1020                                             7, /* why ? */
1021                                             &result);
1022         if (!NT_STATUS_IS_OK(status)) {
1023                 werr = ntstatus_to_werror(status);
1024                 goto done;
1025         }
1026         if (!NT_STATUS_IS_OK(result)) {
1027                 werr = ntstatus_to_werror(result);
1028                 goto done;
1029         }
1030
1031         werr = WERR_OK;
1032
1033  done:
1034         if (is_valid_policy_hnd(&group_handle)) {
1035                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1036         }
1037
1038         if (ctx->disable_policy_handle_cache) {
1039                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1040                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1041         }
1042
1043         return werr;
1044 }
1045
1046 /****************************************************************
1047 ****************************************************************/
1048
1049 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
1050                          struct NetGroupAddUser *r)
1051 {
1052         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
1053 }
1054
1055 /****************************************************************
1056 ****************************************************************/
1057
1058 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
1059                          struct NetGroupDelUser *r)
1060 {
1061         struct rpc_pipe_client *pipe_cli = NULL;
1062         NTSTATUS status, result;
1063         WERROR werr;
1064         struct policy_handle connect_handle, domain_handle, group_handle;
1065         struct lsa_String lsa_group_name, lsa_user_name;
1066         struct dom_sid2 *domain_sid = NULL;
1067         struct dcerpc_binding_handle *b = NULL;
1068
1069         struct samr_Ids rids;
1070         struct samr_Ids types;
1071
1072         ZERO_STRUCT(connect_handle);
1073         ZERO_STRUCT(domain_handle);
1074         ZERO_STRUCT(group_handle);
1075
1076         if (!r->in.group_name) {
1077                 return WERR_INVALID_PARAMETER;
1078         }
1079
1080         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1081                                    &ndr_table_samr,
1082                                    &pipe_cli);
1083         if (!W_ERROR_IS_OK(werr)) {
1084                 goto done;
1085         }
1086
1087         b = pipe_cli->binding_handle;
1088
1089         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1090                                           SAMR_ACCESS_ENUM_DOMAINS |
1091                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1092                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1093                                           &connect_handle,
1094                                           &domain_handle,
1095                                           &domain_sid);
1096         if (!W_ERROR_IS_OK(werr)) {
1097                 goto done;
1098         }
1099
1100         init_lsa_String(&lsa_group_name, r->in.group_name);
1101
1102         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1103                                          &domain_handle,
1104                                          1,
1105                                          &lsa_group_name,
1106                                          &rids,
1107                                          &types,
1108                                          &result);
1109         if (!NT_STATUS_IS_OK(status)) {
1110                 werr = ntstatus_to_werror(status);
1111                 goto done;
1112         }
1113         if (!NT_STATUS_IS_OK(result)) {
1114                 werr = WERR_NERR_GROUPNOTFOUND;
1115                 goto done;
1116         }
1117         if (rids.count != 1) {
1118                 werr = WERR_BAD_NET_RESP;
1119                 goto done;
1120         }
1121         if (types.count != 1) {
1122                 werr = WERR_BAD_NET_RESP;
1123                 goto done;
1124         }
1125
1126         if (types.ids[0] != SID_NAME_DOM_GRP) {
1127                 werr = WERR_NERR_GROUPNOTFOUND;
1128                 goto done;
1129         }
1130
1131         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1132                                        &domain_handle,
1133                                        SAMR_GROUP_ACCESS_REMOVE_MEMBER,
1134                                        rids.ids[0],
1135                                        &group_handle,
1136                                        &result);
1137         if (!NT_STATUS_IS_OK(status)) {
1138                 werr = ntstatus_to_werror(status);
1139                 goto done;
1140         }
1141         if (!NT_STATUS_IS_OK(result)) {
1142                 werr = ntstatus_to_werror(result);
1143                 goto done;
1144         }
1145
1146         init_lsa_String(&lsa_user_name, r->in.user_name);
1147
1148         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1149                                          &domain_handle,
1150                                          1,
1151                                          &lsa_user_name,
1152                                          &rids,
1153                                          &types,
1154                                          &result);
1155         if (!NT_STATUS_IS_OK(status)) {
1156                 werr = ntstatus_to_werror(status);
1157                 goto done;
1158         }
1159
1160         if (!NT_STATUS_IS_OK(result)) {
1161                 werr = WERR_USER_NOT_FOUND;
1162                 goto done;
1163         }
1164         if (rids.count != 1) {
1165                 werr = WERR_BAD_NET_RESP;
1166                 goto done;
1167         }
1168         if (types.count != 1) {
1169                 werr = WERR_BAD_NET_RESP;
1170                 goto done;
1171         }
1172
1173         if (types.ids[0] != SID_NAME_USER) {
1174                 werr = WERR_USER_NOT_FOUND;
1175                 goto done;
1176         }
1177
1178         status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1179                                                &group_handle,
1180                                                rids.ids[0],
1181                                                &result);
1182         if (!NT_STATUS_IS_OK(status)) {
1183                 werr = ntstatus_to_werror(status);
1184                 goto done;
1185         }
1186         if (!NT_STATUS_IS_OK(result)) {
1187                 werr = ntstatus_to_werror(result);
1188                 goto done;
1189         }
1190
1191         werr = WERR_OK;
1192
1193  done:
1194         if (is_valid_policy_hnd(&group_handle)) {
1195                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1196         }
1197
1198         if (ctx->disable_policy_handle_cache) {
1199                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1200                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1201         }
1202
1203         return werr;
1204 }
1205
1206 /****************************************************************
1207 ****************************************************************/
1208
1209 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1210                          struct NetGroupDelUser *r)
1211 {
1212         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1213 }
1214
1215 /****************************************************************
1216 ****************************************************************/
1217
1218 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1219                                                               struct samr_DispInfoFullGroups *groups,
1220                                                               uint8_t **buffer)
1221 {
1222         struct GROUP_INFO_0 *g0;
1223         int i;
1224
1225         g0 = talloc_zero_array(mem_ctx, struct GROUP_INFO_0, groups->count);
1226         W_ERROR_HAVE_NO_MEMORY(g0);
1227
1228         for (i=0; i<groups->count; i++) {
1229                 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1230                         groups->entries[i].account_name.string);
1231                 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1232         }
1233
1234         *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1235                                            sizeof(struct GROUP_INFO_0) * groups->count);
1236         W_ERROR_HAVE_NO_MEMORY(*buffer);
1237
1238         return WERR_OK;
1239 }
1240
1241 /****************************************************************
1242 ****************************************************************/
1243
1244 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1245                                                               struct samr_DispInfoFullGroups *groups,
1246                                                               uint8_t **buffer)
1247 {
1248         struct GROUP_INFO_1 *g1;
1249         int i;
1250
1251         g1 = talloc_zero_array(mem_ctx, struct GROUP_INFO_1, groups->count);
1252         W_ERROR_HAVE_NO_MEMORY(g1);
1253
1254         for (i=0; i<groups->count; i++) {
1255                 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1256                         groups->entries[i].account_name.string);
1257                 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1258                         groups->entries[i].description.string);
1259                 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1260         }
1261
1262         *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1263                                            sizeof(struct GROUP_INFO_1) * groups->count);
1264         W_ERROR_HAVE_NO_MEMORY(*buffer);
1265
1266         return WERR_OK;
1267 }
1268
1269 /****************************************************************
1270 ****************************************************************/
1271
1272 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1273                                                               struct samr_DispInfoFullGroups *groups,
1274                                                               uint8_t **buffer)
1275 {
1276         struct GROUP_INFO_2 *g2;
1277         int i;
1278
1279         g2 = talloc_zero_array(mem_ctx, struct GROUP_INFO_2, groups->count);
1280         W_ERROR_HAVE_NO_MEMORY(g2);
1281
1282         for (i=0; i<groups->count; i++) {
1283                 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1284                         groups->entries[i].account_name.string);
1285                 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1286                         groups->entries[i].description.string);
1287                 g2[i].grpi2_group_id = groups->entries[i].rid;
1288                 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1289                 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1290         }
1291
1292         *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1293                                            sizeof(struct GROUP_INFO_2) * groups->count);
1294         W_ERROR_HAVE_NO_MEMORY(*buffer);
1295
1296         return WERR_OK;
1297 }
1298
1299 /****************************************************************
1300 ****************************************************************/
1301
1302 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1303                                                               struct samr_DispInfoFullGroups *groups,
1304                                                               const struct dom_sid *domain_sid,
1305                                                               uint8_t **buffer)
1306 {
1307         struct GROUP_INFO_3 *g3;
1308         int i;
1309
1310         g3 = talloc_zero_array(mem_ctx, struct GROUP_INFO_3, groups->count);
1311         W_ERROR_HAVE_NO_MEMORY(g3);
1312
1313         for (i=0; i<groups->count; i++) {
1314
1315                 struct dom_sid sid;
1316
1317                 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1318                         return WERR_NOT_ENOUGH_MEMORY;
1319                 }
1320
1321                 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1322                         groups->entries[i].account_name.string);
1323                 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1324                         groups->entries[i].description.string);
1325                 g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1326                 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1327                 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1328         }
1329
1330         *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1331                                            sizeof(struct GROUP_INFO_3) * groups->count);
1332         W_ERROR_HAVE_NO_MEMORY(*buffer);
1333
1334         return WERR_OK;
1335 }
1336
1337 /****************************************************************
1338 ****************************************************************/
1339
1340 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1341                                                             uint32_t level,
1342                                                             struct samr_DispInfoFullGroups *groups,
1343                                                             const struct dom_sid *domain_sid,
1344                                                             uint32_t *entries_read,
1345                                                             uint8_t **buffer)
1346 {
1347         if (entries_read) {
1348                 *entries_read = groups->count;
1349         }
1350
1351         switch (level) {
1352                 case 0:
1353                         return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1354                 case 1:
1355                         return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1356                 case 2:
1357                         return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1358                 case 3:
1359                         return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1360                 default:
1361                         return WERR_UNKNOWN_LEVEL;
1362         }
1363 }
1364
1365 /****************************************************************
1366 ****************************************************************/
1367
1368 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1369                       struct NetGroupEnum *r)
1370 {
1371         struct rpc_pipe_client *pipe_cli = NULL;
1372         struct policy_handle connect_handle;
1373         struct dom_sid2 *domain_sid = NULL;
1374         struct policy_handle domain_handle;
1375         union samr_DispInfo info;
1376         union samr_DomainInfo *domain_info = NULL;
1377         struct dcerpc_binding_handle *b = NULL;
1378
1379         uint32_t total_size = 0;
1380         uint32_t returned_size = 0;
1381
1382         NTSTATUS result = NT_STATUS_OK;
1383         NTSTATUS status = NT_STATUS_OK;
1384         WERROR werr, tmp_werr;
1385
1386         ZERO_STRUCT(connect_handle);
1387         ZERO_STRUCT(domain_handle);
1388
1389         switch (r->in.level) {
1390                 case 0:
1391                 case 1:
1392                 case 2:
1393                 case 3:
1394                         break;
1395                 default:
1396                         return WERR_UNKNOWN_LEVEL;
1397         }
1398
1399         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1400                                    &ndr_table_samr,
1401                                    &pipe_cli);
1402         if (!W_ERROR_IS_OK(werr)) {
1403                 goto done;
1404         }
1405
1406         b = pipe_cli->binding_handle;
1407
1408         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1409                                           SAMR_ACCESS_ENUM_DOMAINS |
1410                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1411                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1412                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1413                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1414                                           &connect_handle,
1415                                           &domain_handle,
1416                                           &domain_sid);
1417         if (!W_ERROR_IS_OK(werr)) {
1418                 goto done;
1419         }
1420
1421         status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
1422                                              &domain_handle,
1423                                              2,
1424                                              &domain_info,
1425                                              &result);
1426         if (!NT_STATUS_IS_OK(status)) {
1427                 werr = ntstatus_to_werror(status);
1428                 goto done;
1429         }
1430         if (!NT_STATUS_IS_OK(result)) {
1431                 werr = ntstatus_to_werror(result);
1432                 goto done;
1433         }
1434
1435         if (r->out.total_entries) {
1436                 *r->out.total_entries = domain_info->general.num_groups;
1437         }
1438
1439         status = dcerpc_samr_QueryDisplayInfo2(b,
1440                                                ctx,
1441                                                &domain_handle,
1442                                                3,
1443                                                r->in.resume_handle ?
1444                                                *r->in.resume_handle : 0,
1445                                                (uint32_t)-1,
1446                                                r->in.prefmaxlen,
1447                                                &total_size,
1448                                                &returned_size,
1449                                                &info,
1450                                                &result);
1451         if (!NT_STATUS_IS_OK(status)) {
1452                 werr = ntstatus_to_werror(status);
1453                 goto done;
1454         }
1455
1456         werr = ntstatus_to_werror(result);
1457         if (NT_STATUS_IS_ERR(result)) {
1458                 goto done;
1459         }
1460
1461         if (r->out.resume_handle && info.info3.count > 0) {
1462                 *r->out.resume_handle =
1463                         info.info3.entries[info.info3.count-1].idx;
1464         }
1465
1466         tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1467                                                                  r->in.level,
1468                                                                  &info.info3,
1469                                                                  domain_sid,
1470                                                                  r->out.entries_read,
1471                                                                  r->out.buffer);
1472         if (!W_ERROR_IS_OK(tmp_werr)) {
1473                 werr = tmp_werr;
1474                 goto done;
1475         }
1476
1477  done:
1478         /* if last query */
1479         if (NT_STATUS_IS_OK(result) ||
1480             NT_STATUS_IS_ERR(result)) {
1481
1482                 if (ctx->disable_policy_handle_cache) {
1483                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1484                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1485                 }
1486         }
1487
1488         return werr;
1489 }
1490
1491 /****************************************************************
1492 ****************************************************************/
1493
1494 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1495                       struct NetGroupEnum *r)
1496 {
1497         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1498 }
1499
1500 /****************************************************************
1501 ****************************************************************/
1502
1503 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1504                           struct NetGroupGetUsers *r)
1505 {
1506         /* FIXME: this call needs to cope with large replies */
1507
1508         struct rpc_pipe_client *pipe_cli = NULL;
1509         struct policy_handle connect_handle, domain_handle, group_handle;
1510         struct lsa_String lsa_account_name;
1511         struct dom_sid2 *domain_sid = NULL;
1512         struct samr_Ids group_rids, name_types;
1513         struct samr_RidAttrArray *rid_array = NULL;
1514         struct lsa_Strings names;
1515         struct samr_Ids member_types;
1516         struct dcerpc_binding_handle *b = NULL;
1517
1518         int i;
1519         uint32_t entries_read = 0;
1520
1521         NTSTATUS status = NT_STATUS_OK;
1522         NTSTATUS result = NT_STATUS_OK;
1523         WERROR werr;
1524
1525         ZERO_STRUCT(connect_handle);
1526         ZERO_STRUCT(domain_handle);
1527         ZERO_STRUCT(group_handle);
1528
1529         if (!r->out.buffer) {
1530                 return WERR_INVALID_PARAMETER;
1531         }
1532
1533         *r->out.buffer = NULL;
1534         *r->out.entries_read = 0;
1535         *r->out.total_entries = 0;
1536
1537         switch (r->in.level) {
1538                 case 0:
1539                 case 1:
1540                         break;
1541                 default:
1542                         return WERR_UNKNOWN_LEVEL;
1543         }
1544
1545
1546         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1547                                    &ndr_table_samr,
1548                                    &pipe_cli);
1549         if (!W_ERROR_IS_OK(werr)) {
1550                 goto done;
1551         }
1552
1553         b = pipe_cli->binding_handle;
1554
1555         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1556                                           SAMR_ACCESS_ENUM_DOMAINS |
1557                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1558                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1559                                           &connect_handle,
1560                                           &domain_handle,
1561                                           &domain_sid);
1562         if (!W_ERROR_IS_OK(werr)) {
1563                 goto done;
1564         }
1565
1566         init_lsa_String(&lsa_account_name, r->in.group_name);
1567
1568         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1569                                          &domain_handle,
1570                                          1,
1571                                          &lsa_account_name,
1572                                          &group_rids,
1573                                          &name_types,
1574                                          &result);
1575         if (!NT_STATUS_IS_OK(status)) {
1576                 werr = ntstatus_to_werror(status);
1577                 goto done;
1578         }
1579         if (!NT_STATUS_IS_OK(result)) {
1580                 werr = ntstatus_to_werror(result);
1581                 goto done;
1582         }
1583         if (group_rids.count != 1) {
1584                 werr = WERR_BAD_NET_RESP;
1585                 goto done;
1586         }
1587         if (name_types.count != 1) {
1588                 werr = WERR_BAD_NET_RESP;
1589                 goto done;
1590         }
1591
1592         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1593                                        &domain_handle,
1594                                        SAMR_GROUP_ACCESS_GET_MEMBERS,
1595                                        group_rids.ids[0],
1596                                        &group_handle,
1597                                        &result);
1598         if (!NT_STATUS_IS_OK(status)) {
1599                 werr = ntstatus_to_werror(status);
1600                 goto done;
1601         }
1602         if (!NT_STATUS_IS_OK(result)) {
1603                 werr = ntstatus_to_werror(result);
1604                 goto done;
1605         }
1606
1607         status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1608                                               &group_handle,
1609                                               &rid_array,
1610                                               &result);
1611         if (!NT_STATUS_IS_OK(status)) {
1612                 werr = ntstatus_to_werror(status);
1613                 goto done;
1614         }
1615         if (!NT_STATUS_IS_OK(result)) {
1616                 werr = ntstatus_to_werror(result);
1617                 goto done;
1618         }
1619
1620         status = dcerpc_samr_LookupRids(b, talloc_tos(),
1621                                         &domain_handle,
1622                                         rid_array->count,
1623                                         rid_array->rids,
1624                                         &names,
1625                                         &member_types,
1626                                         &result);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 werr = ntstatus_to_werror(status);
1629                 goto done;
1630         }
1631         if (!NT_STATUS_IS_OK(result)) {
1632                 werr = ntstatus_to_werror(result);
1633                 goto done;
1634         }
1635         if (names.count != rid_array->count) {
1636                 werr = WERR_BAD_NET_RESP;
1637                 goto done;
1638         }
1639         if (member_types.count != rid_array->count) {
1640                 werr = WERR_BAD_NET_RESP;
1641                 goto done;
1642         }
1643
1644         for (i=0; i < names.count; i++) {
1645
1646                 if (member_types.ids[i] != SID_NAME_USER) {
1647                         continue;
1648                 }
1649
1650                 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1651                                                        r->in.level,
1652                                                        names.names[i].string,
1653                                                        7,
1654                                                        r->out.buffer,
1655                                                        &entries_read);
1656                 if (!NT_STATUS_IS_OK(status)) {
1657                         werr = ntstatus_to_werror(status);
1658                         goto done;
1659                 }
1660         }
1661
1662         *r->out.entries_read = entries_read;
1663         *r->out.total_entries = entries_read;
1664
1665         werr = WERR_OK;
1666
1667  done:
1668         if (is_valid_policy_hnd(&group_handle)) {
1669                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1670         }
1671
1672         if (ctx->disable_policy_handle_cache) {
1673                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1674                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1675         }
1676
1677         return werr;
1678 }
1679
1680 /****************************************************************
1681 ****************************************************************/
1682
1683 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1684                           struct NetGroupGetUsers *r)
1685 {
1686         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1687 }
1688
1689 /****************************************************************
1690 ****************************************************************/
1691
1692 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1693                           struct NetGroupSetUsers *r)
1694 {
1695         struct rpc_pipe_client *pipe_cli = NULL;
1696         struct policy_handle connect_handle, domain_handle, group_handle;
1697         struct lsa_String lsa_account_name;
1698         struct dom_sid2 *domain_sid = NULL;
1699         union samr_GroupInfo *group_info = NULL;
1700         struct samr_Ids user_rids, name_types;
1701         struct samr_Ids group_rids, group_types;
1702         struct samr_RidAttrArray *rid_array = NULL;
1703         struct lsa_String *lsa_names = NULL;
1704         struct dcerpc_binding_handle *b = NULL;
1705
1706         uint32_t *add_rids = NULL;
1707         uint32_t *del_rids = NULL;
1708         size_t num_add_rids = 0;
1709         size_t num_del_rids = 0;
1710
1711         uint32_t *member_rids = NULL;
1712
1713         struct GROUP_USERS_INFO_0 *i0 = NULL;
1714         struct GROUP_USERS_INFO_1 *i1 = NULL;
1715
1716         int i, k;
1717
1718         NTSTATUS status = NT_STATUS_OK;
1719         NTSTATUS result = NT_STATUS_OK;
1720         WERROR werr;
1721
1722         ZERO_STRUCT(connect_handle);
1723         ZERO_STRUCT(domain_handle);
1724         ZERO_STRUCT(group_handle);
1725
1726         if (!r->in.buffer) {
1727                 return WERR_INVALID_PARAMETER;
1728         }
1729
1730         switch (r->in.level) {
1731                 case 0:
1732                 case 1:
1733                         break;
1734                 default:
1735                         return WERR_UNKNOWN_LEVEL;
1736         }
1737
1738         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1739                                    &ndr_table_samr,
1740                                    &pipe_cli);
1741         if (!W_ERROR_IS_OK(werr)) {
1742                 goto done;
1743         }
1744
1745         b = pipe_cli->binding_handle;
1746
1747         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1748                                           SAMR_ACCESS_ENUM_DOMAINS |
1749                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1750                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1751                                           &connect_handle,
1752                                           &domain_handle,
1753                                           &domain_sid);
1754         if (!W_ERROR_IS_OK(werr)) {
1755                 goto done;
1756         }
1757
1758         init_lsa_String(&lsa_account_name, r->in.group_name);
1759
1760         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1761                                          &domain_handle,
1762                                          1,
1763                                          &lsa_account_name,
1764                                          &group_rids,
1765                                          &group_types,
1766                                          &result);
1767         if (!NT_STATUS_IS_OK(status)) {
1768                 werr = ntstatus_to_werror(status);
1769                 goto done;
1770         }
1771         if (!NT_STATUS_IS_OK(result)) {
1772                 werr = ntstatus_to_werror(result);
1773                 goto done;
1774         }
1775         if (group_rids.count != 1) {
1776                 werr = WERR_BAD_NET_RESP;
1777                 goto done;
1778         }
1779         if (group_types.count != 1) {
1780                 werr = WERR_BAD_NET_RESP;
1781                 goto done;
1782         }
1783
1784         status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1785                                        &domain_handle,
1786                                        SAMR_GROUP_ACCESS_GET_MEMBERS |
1787                                        SAMR_GROUP_ACCESS_ADD_MEMBER |
1788                                        SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1789                                        SAMR_GROUP_ACCESS_LOOKUP_INFO,
1790                                        group_rids.ids[0],
1791                                        &group_handle,
1792                                        &result);
1793         if (!NT_STATUS_IS_OK(status)) {
1794                 werr = ntstatus_to_werror(status);
1795                 goto done;
1796         }
1797         if (!NT_STATUS_IS_OK(result)) {
1798                 werr = ntstatus_to_werror(result);
1799                 goto done;
1800         }
1801
1802         status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1803                                             &group_handle,
1804                                             GROUPINFOATTRIBUTES,
1805                                             &group_info,
1806                                             &result);
1807         if (!NT_STATUS_IS_OK(status)) {
1808                 werr = ntstatus_to_werror(status);
1809                 goto done;
1810         }
1811         if (!NT_STATUS_IS_OK(result)) {
1812                 werr = ntstatus_to_werror(result);
1813                 goto done;
1814         }
1815
1816         switch (r->in.level) {
1817                 case 0:
1818                         i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1819                         break;
1820                 case 1:
1821                         i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1822                         break;
1823         }
1824
1825         lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1826         if (!lsa_names) {
1827                 werr = WERR_NOT_ENOUGH_MEMORY;
1828                 goto done;
1829         }
1830
1831         for (i=0; i < r->in.num_entries; i++) {
1832
1833                 switch (r->in.level) {
1834                         case 0:
1835                                 init_lsa_String(&lsa_names[i], i0->grui0_name);
1836                                 i0++;
1837                                 break;
1838                         case 1:
1839                                 init_lsa_String(&lsa_names[i], i1->grui1_name);
1840                                 i1++;
1841                                 break;
1842                 }
1843         }
1844
1845         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1846                                          &domain_handle,
1847                                          r->in.num_entries,
1848                                          lsa_names,
1849                                          &user_rids,
1850                                          &name_types,
1851                                          &result);
1852         if (!NT_STATUS_IS_OK(status)) {
1853                 werr = ntstatus_to_werror(status);
1854                 goto done;
1855         }
1856         if (!NT_STATUS_IS_OK(result)) {
1857                 werr = ntstatus_to_werror(result);
1858                 goto done;
1859         }
1860
1861         if (r->in.num_entries != user_rids.count) {
1862                 werr = WERR_BAD_NET_RESP;
1863                 goto done;
1864         }
1865         if (r->in.num_entries != name_types.count) {
1866                 werr = WERR_BAD_NET_RESP;
1867                 goto done;
1868         }
1869
1870         member_rids = user_rids.ids;
1871
1872         status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1873                                               &group_handle,
1874                                               &rid_array,
1875                                               &result);
1876         if (!NT_STATUS_IS_OK(status)) {
1877                 werr = ntstatus_to_werror(status);
1878                 goto done;
1879         }
1880         if (!NT_STATUS_IS_OK(result)) {
1881                 werr = ntstatus_to_werror(result);
1882                 goto done;
1883         }
1884
1885         /* add list */
1886
1887         for (i=0; i < r->in.num_entries; i++) {
1888                 bool already_member = false;
1889                 for (k=0; k < rid_array->count; k++) {
1890                         if (member_rids[i] == rid_array->rids[k]) {
1891                                 already_member = true;
1892                                 break;
1893                         }
1894                 }
1895                 if (!already_member) {
1896                         if (!add_rid_to_array_unique(ctx,
1897                                                      member_rids[i],
1898                                                      &add_rids, &num_add_rids)) {
1899                                 werr = WERR_GEN_FAILURE;
1900                                 goto done;
1901                         }
1902                 }
1903         }
1904
1905         /* del list */
1906
1907         for (k=0; k < rid_array->count; k++) {
1908                 bool keep_member = false;
1909                 for (i=0; i < r->in.num_entries; i++) {
1910                         if (member_rids[i] == rid_array->rids[k]) {
1911                                 keep_member = true;
1912                                 break;
1913                         }
1914                 }
1915                 if (!keep_member) {
1916                         if (!add_rid_to_array_unique(ctx,
1917                                                      rid_array->rids[k],
1918                                                      &del_rids, &num_del_rids)) {
1919                                 werr = WERR_GEN_FAILURE;
1920                                 goto done;
1921                         }
1922                 }
1923         }
1924
1925         /* add list */
1926
1927         for (i=0; i < num_add_rids; i++) {
1928                 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1929                                                     &group_handle,
1930                                                     add_rids[i],
1931                                                     7 /* ? */,
1932                                                     &result);
1933                 if (!NT_STATUS_IS_OK(status)) {
1934                         werr = ntstatus_to_werror(status);
1935                         goto done;
1936                 }
1937                 if (!NT_STATUS_IS_OK(result)) {
1938                         werr = ntstatus_to_werror(result);
1939                         goto done;
1940                 }
1941         }
1942
1943         /* del list */
1944
1945         for (i=0; i < num_del_rids; i++) {
1946                 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1947                                                        &group_handle,
1948                                                        del_rids[i],
1949                                                        &result);
1950                 if (!NT_STATUS_IS_OK(status)) {
1951                         werr = ntstatus_to_werror(status);
1952                         goto done;
1953                 }
1954                 if (!NT_STATUS_IS_OK(result)) {
1955                         werr = ntstatus_to_werror(result);
1956                         goto done;
1957                 }
1958         }
1959
1960         werr = WERR_OK;
1961
1962  done:
1963         if (is_valid_policy_hnd(&group_handle)) {
1964                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1965         }
1966
1967         if (ctx->disable_policy_handle_cache) {
1968                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1969                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1970         }
1971
1972         return werr;
1973 }
1974
1975 /****************************************************************
1976 ****************************************************************/
1977
1978 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1979                           struct NetGroupSetUsers *r)
1980 {
1981         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
1982 }