source: branches/samba-3.3.x/source/lib/netapi/group.c

Last change on this file was 224, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 branch to 3.3.4

File size: 41.6 KB
Line 
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
30WERROR 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.buffer) {
53 return WERR_INVALID_PARAM;
54 }
55
56 switch (r->in.level) {
57 case 0:
58 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
59 break;
60 case 1:
61 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
62 break;
63 case 2:
64 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
65 break;
66 case 3:
67 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
68 break;
69 default:
70 werr = WERR_UNKNOWN_LEVEL;
71 goto done;
72 }
73
74 werr = libnetapi_open_pipe(ctx, r->in.server_name,
75 &ndr_table_samr.syntax_id,
76 &cli,
77 &pipe_cli);
78 if (!W_ERROR_IS_OK(werr)) {
79 goto done;
80 }
81
82 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
83 SAMR_ACCESS_ENUM_DOMAINS |
84 SAMR_ACCESS_LOOKUP_DOMAIN,
85 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
86 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
87 &connect_handle,
88 &domain_handle,
89 &domain_sid);
90 if (!W_ERROR_IS_OK(werr)) {
91 goto done;
92 }
93
94 switch (r->in.level) {
95 case 0:
96 init_lsa_String(&lsa_group_name, info0->grpi0_name);
97 break;
98 case 1:
99 init_lsa_String(&lsa_group_name, info1->grpi1_name);
100 break;
101 case 2:
102 init_lsa_String(&lsa_group_name, info2->grpi2_name);
103 break;
104 case 3:
105 init_lsa_String(&lsa_group_name, info3->grpi3_name);
106 break;
107 }
108
109 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
110 &domain_handle,
111 &lsa_group_name,
112 SEC_STD_DELETE |
113 SAMR_GROUP_ACCESS_SET_INFO,
114 &group_handle,
115 &rid);
116
117 if (!NT_STATUS_IS_OK(status)) {
118 werr = ntstatus_to_werror(status);
119 goto done;
120 }
121
122 switch (r->in.level) {
123 case 1:
124 if (info1->grpi1_comment) {
125 init_lsa_String(&info.description,
126 info1->grpi1_comment);
127
128 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
129 &group_handle,
130 GROUPINFODESCRIPTION,
131 &info);
132 }
133 break;
134 case 2:
135 if (info2->grpi2_comment) {
136 init_lsa_String(&info.description,
137 info2->grpi2_comment);
138
139 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
140 &group_handle,
141 GROUPINFODESCRIPTION,
142 &info);
143 if (!NT_STATUS_IS_OK(status)) {
144 werr = ntstatus_to_werror(status);
145 goto failed;
146 }
147 }
148
149 if (info2->grpi2_attributes != 0) {
150 info.attributes.attributes = info2->grpi2_attributes;
151 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
152 &group_handle,
153 GROUPINFOATTRIBUTES,
154 &info);
155
156 }
157 break;
158 case 3:
159 if (info3->grpi3_comment) {
160 init_lsa_String(&info.description,
161 info3->grpi3_comment);
162
163 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
164 &group_handle,
165 GROUPINFODESCRIPTION,
166 &info);
167 if (!NT_STATUS_IS_OK(status)) {
168 werr = ntstatus_to_werror(status);
169 goto failed;
170 }
171 }
172
173 if (info3->grpi3_attributes != 0) {
174 info.attributes.attributes = info3->grpi3_attributes;
175 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
176 &group_handle,
177 GROUPINFOATTRIBUTES,
178 &info);
179 }
180 break;
181 default:
182 break;
183 }
184
185 if (!NT_STATUS_IS_OK(status)) {
186 werr = ntstatus_to_werror(status);
187 goto failed;
188 }
189
190 werr = WERR_OK;
191 goto done;
192
193 failed:
194 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
195 &group_handle);
196
197 done:
198 if (!cli) {
199 return werr;
200 }
201
202 if (is_valid_policy_hnd(&group_handle)) {
203 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
204 }
205
206 if (ctx->disable_policy_handle_cache) {
207 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
208 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
209 }
210
211 return werr;
212}
213
214/****************************************************************
215****************************************************************/
216
217WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
218 struct NetGroupAdd *r)
219{
220 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
221}
222
223/****************************************************************
224****************************************************************/
225
226WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
227 struct NetGroupDel *r)
228{
229 struct cli_state *cli = NULL;
230 struct rpc_pipe_client *pipe_cli = NULL;
231 NTSTATUS status;
232 WERROR werr;
233 POLICY_HND connect_handle, domain_handle, group_handle;
234 struct lsa_String lsa_group_name;
235 struct dom_sid2 *domain_sid = NULL;
236 int i = 0;
237
238 struct samr_Ids rids;
239 struct samr_Ids types;
240 union samr_GroupInfo *info = NULL;
241 struct samr_RidTypeArray *rid_array = NULL;
242
243 ZERO_STRUCT(connect_handle);
244 ZERO_STRUCT(domain_handle);
245 ZERO_STRUCT(group_handle);
246
247 if (!r->in.group_name) {
248 return WERR_INVALID_PARAM;
249 }
250
251 werr = libnetapi_open_pipe(ctx, r->in.server_name,
252 &ndr_table_samr.syntax_id,
253 &cli,
254 &pipe_cli);
255 if (!W_ERROR_IS_OK(werr)) {
256 goto done;
257 }
258
259 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
260 SAMR_ACCESS_ENUM_DOMAINS |
261 SAMR_ACCESS_LOOKUP_DOMAIN,
262 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
263 &connect_handle,
264 &domain_handle,
265 &domain_sid);
266 if (!W_ERROR_IS_OK(werr)) {
267 goto done;
268 }
269
270 init_lsa_String(&lsa_group_name, r->in.group_name);
271
272 status = rpccli_samr_LookupNames(pipe_cli, ctx,
273 &domain_handle,
274 1,
275 &lsa_group_name,
276 &rids,
277 &types);
278 if (!NT_STATUS_IS_OK(status)) {
279 werr = ntstatus_to_werror(status);
280 goto done;
281 }
282
283 if (types.ids[0] != SID_NAME_DOM_GRP) {
284 werr = WERR_INVALID_DATATYPE;
285 goto done;
286 }
287
288 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
289 &domain_handle,
290 SEC_STD_DELETE |
291 SAMR_GROUP_ACCESS_GET_MEMBERS |
292 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
293 SAMR_GROUP_ACCESS_ADD_MEMBER |
294 SAMR_GROUP_ACCESS_LOOKUP_INFO,
295 rids.ids[0],
296 &group_handle);
297 if (!NT_STATUS_IS_OK(status)) {
298 werr = ntstatus_to_werror(status);
299 goto done;
300 }
301
302 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
303 &group_handle,
304 GROUPINFOATTRIBUTES,
305 &info);
306 if (!NT_STATUS_IS_OK(status)) {
307 werr = ntstatus_to_werror(status);
308 goto done;
309 }
310
311#if 0
312 /* breaks against NT4 */
313 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
314 werr = WERR_ACCESS_DENIED;
315 goto done;
316 }
317#endif
318 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
319 &group_handle,
320 &rid_array);
321 if (!NT_STATUS_IS_OK(status)) {
322 werr = ntstatus_to_werror(status);
323 goto done;
324 }
325
326 {
327 struct lsa_Strings names;
328 struct samr_Ids member_types;
329
330 status = rpccli_samr_LookupRids(pipe_cli, ctx,
331 &domain_handle,
332 rid_array->count,
333 rid_array->rids,
334 &names,
335 &member_types);
336 if (!NT_STATUS_IS_OK(status)) {
337 werr = ntstatus_to_werror(status);
338 goto done;
339 }
340 }
341
342 for (i=0; i < rid_array->count; i++) {
343
344 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
345 &group_handle,
346 rid_array->rids[i]);
347 if (!NT_STATUS_IS_OK(status)) {
348 werr = ntstatus_to_werror(status);
349 goto done;
350 }
351 }
352
353 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
354 &group_handle);
355 if (!NT_STATUS_IS_OK(status)) {
356 werr = ntstatus_to_werror(status);
357 goto done;
358 }
359
360 ZERO_STRUCT(group_handle);
361
362 werr = WERR_OK;
363
364 done:
365 if (!cli) {
366 return werr;
367 }
368
369 if (is_valid_policy_hnd(&group_handle)) {
370 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
371 }
372
373 if (ctx->disable_policy_handle_cache) {
374 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
375 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
376 }
377
378 return werr;
379}
380
381/****************************************************************
382****************************************************************/
383
384WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
385 struct NetGroupDel *r)
386{
387 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
388}
389
390/****************************************************************
391****************************************************************/
392
393WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
394 struct NetGroupSetInfo *r)
395{
396 struct cli_state *cli = NULL;
397 struct rpc_pipe_client *pipe_cli = NULL;
398 NTSTATUS status;
399 WERROR werr;
400 POLICY_HND connect_handle, domain_handle, group_handle;
401 struct lsa_String lsa_group_name;
402 struct dom_sid2 *domain_sid = NULL;
403
404 struct samr_Ids rids;
405 struct samr_Ids types;
406 union samr_GroupInfo info;
407 struct GROUP_INFO_0 *g0;
408 struct GROUP_INFO_1 *g1;
409 struct GROUP_INFO_2 *g2;
410 struct GROUP_INFO_3 *g3;
411 struct GROUP_INFO_1002 *g1002;
412 struct GROUP_INFO_1005 *g1005;
413
414 ZERO_STRUCT(connect_handle);
415 ZERO_STRUCT(domain_handle);
416 ZERO_STRUCT(group_handle);
417
418 if (!r->in.group_name) {
419 return WERR_INVALID_PARAM;
420 }
421
422 werr = libnetapi_open_pipe(ctx, r->in.server_name,
423 &ndr_table_samr.syntax_id,
424 &cli,
425 &pipe_cli);
426 if (!W_ERROR_IS_OK(werr)) {
427 goto done;
428 }
429
430 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
431 SAMR_ACCESS_ENUM_DOMAINS |
432 SAMR_ACCESS_LOOKUP_DOMAIN,
433 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
434 &connect_handle,
435 &domain_handle,
436 &domain_sid);
437 if (!W_ERROR_IS_OK(werr)) {
438 goto done;
439 }
440
441 init_lsa_String(&lsa_group_name, r->in.group_name);
442
443 status = rpccli_samr_LookupNames(pipe_cli, ctx,
444 &domain_handle,
445 1,
446 &lsa_group_name,
447 &rids,
448 &types);
449 if (!NT_STATUS_IS_OK(status)) {
450 werr = ntstatus_to_werror(status);
451 goto done;
452 }
453
454 if (types.ids[0] != SID_NAME_DOM_GRP) {
455 werr = WERR_INVALID_DATATYPE;
456 goto done;
457 }
458
459 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
460 &domain_handle,
461 SAMR_GROUP_ACCESS_SET_INFO |
462 SAMR_GROUP_ACCESS_LOOKUP_INFO,
463 rids.ids[0],
464 &group_handle);
465 if (!NT_STATUS_IS_OK(status)) {
466 werr = ntstatus_to_werror(status);
467 goto done;
468 }
469
470 switch (r->in.level) {
471 case 0:
472 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
473 init_lsa_String(&info.name, g0->grpi0_name);
474 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
475 &group_handle,
476 GROUPINFONAME,
477 &info);
478 break;
479 case 1:
480 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
481 init_lsa_String(&info.description, g1->grpi1_comment);
482 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
483 &group_handle,
484 GROUPINFODESCRIPTION,
485 &info);
486 break;
487 case 2:
488 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
489 init_lsa_String(&info.description, g2->grpi2_comment);
490 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
491 &group_handle,
492 GROUPINFODESCRIPTION,
493 &info);
494 if (!NT_STATUS_IS_OK(status)) {
495 werr = ntstatus_to_werror(status);
496 goto done;
497 }
498 info.attributes.attributes = g2->grpi2_attributes;
499 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
500 &group_handle,
501 GROUPINFOATTRIBUTES,
502 &info);
503 break;
504 case 3:
505 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
506 init_lsa_String(&info.description, g3->grpi3_comment);
507 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
508 &group_handle,
509 GROUPINFODESCRIPTION,
510 &info);
511 if (!NT_STATUS_IS_OK(status)) {
512 werr = ntstatus_to_werror(status);
513 goto done;
514 }
515 info.attributes.attributes = g3->grpi3_attributes;
516 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
517 &group_handle,
518 GROUPINFOATTRIBUTES,
519 &info);
520 break;
521 case 1002:
522 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
523 init_lsa_String(&info.description, g1002->grpi1002_comment);
524 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
525 &group_handle,
526 GROUPINFODESCRIPTION,
527 &info);
528 break;
529 case 1005:
530 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
531 info.attributes.attributes = g1005->grpi1005_attributes;
532 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
533 &group_handle,
534 GROUPINFOATTRIBUTES,
535 &info);
536 break;
537 default:
538 status = NT_STATUS_INVALID_LEVEL;
539 break;
540 }
541
542 if (!NT_STATUS_IS_OK(status)) {
543 werr = ntstatus_to_werror(status);
544 goto done;
545 }
546
547 werr = WERR_OK;
548
549 done:
550 if (!cli) {
551 return werr;
552 }
553
554 if (is_valid_policy_hnd(&group_handle)) {
555 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
556 }
557
558 if (ctx->disable_policy_handle_cache) {
559 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
560 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
561 }
562
563 return werr;
564}
565
566/****************************************************************
567****************************************************************/
568
569WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
570 struct NetGroupSetInfo *r)
571{
572 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
573}
574
575/****************************************************************
576****************************************************************/
577
578static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
579 uint32_t level,
580 struct samr_GroupInfoAll *info,
581 struct dom_sid2 *domain_sid,
582 uint32_t rid,
583 uint8_t **buffer)
584{
585 struct GROUP_INFO_0 info0;
586 struct GROUP_INFO_1 info1;
587 struct GROUP_INFO_2 info2;
588 struct GROUP_INFO_3 info3;
589 struct dom_sid sid;
590
591 switch (level) {
592 case 0:
593 info0.grpi0_name = info->name.string;
594
595 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
596
597 break;
598 case 1:
599 info1.grpi1_name = info->name.string;
600 info1.grpi1_comment = info->description.string;
601
602 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
603
604 break;
605 case 2:
606 info2.grpi2_name = info->name.string;
607 info2.grpi2_comment = info->description.string;
608 info2.grpi2_group_id = rid;
609 info2.grpi2_attributes = info->attributes;
610
611 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
612
613 break;
614 case 3:
615 if (!sid_compose(&sid, domain_sid, rid)) {
616 return WERR_NOMEM;
617 }
618
619 info3.grpi3_name = info->name.string;
620 info3.grpi3_comment = info->description.string;
621 info3.grpi3_attributes = info->attributes;
622 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
623
624 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
625
626 break;
627 default:
628 return WERR_UNKNOWN_LEVEL;
629 }
630
631 W_ERROR_HAVE_NO_MEMORY(*buffer);
632
633 return WERR_OK;
634}
635
636/****************************************************************
637****************************************************************/
638
639WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
640 struct NetGroupGetInfo *r)
641{
642 struct cli_state *cli = NULL;
643 struct rpc_pipe_client *pipe_cli = NULL;
644 NTSTATUS status;
645 WERROR werr;
646 POLICY_HND connect_handle, domain_handle, group_handle;
647 struct lsa_String lsa_group_name;
648 struct dom_sid2 *domain_sid = NULL;
649
650 struct samr_Ids rids;
651 struct samr_Ids types;
652 union samr_GroupInfo *info = NULL;
653 bool group_info_all = false;
654
655 ZERO_STRUCT(connect_handle);
656 ZERO_STRUCT(domain_handle);
657 ZERO_STRUCT(group_handle);
658
659 if (!r->in.group_name) {
660 return WERR_INVALID_PARAM;
661 }
662
663 werr = libnetapi_open_pipe(ctx, r->in.server_name,
664 &ndr_table_samr.syntax_id,
665 &cli,
666 &pipe_cli);
667 if (!W_ERROR_IS_OK(werr)) {
668 goto done;
669 }
670
671 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
672 SAMR_ACCESS_ENUM_DOMAINS |
673 SAMR_ACCESS_LOOKUP_DOMAIN,
674 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
675 &connect_handle,
676 &domain_handle,
677 &domain_sid);
678 if (!W_ERROR_IS_OK(werr)) {
679 goto done;
680 }
681
682 init_lsa_String(&lsa_group_name, r->in.group_name);
683
684 status = rpccli_samr_LookupNames(pipe_cli, ctx,
685 &domain_handle,
686 1,
687 &lsa_group_name,
688 &rids,
689 &types);
690 if (!NT_STATUS_IS_OK(status)) {
691 werr = ntstatus_to_werror(status);
692 goto done;
693 }
694
695 if (types.ids[0] != SID_NAME_DOM_GRP) {
696 werr = WERR_INVALID_DATATYPE;
697 goto done;
698 }
699
700 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
701 &domain_handle,
702 SAMR_GROUP_ACCESS_LOOKUP_INFO,
703 rids.ids[0],
704 &group_handle);
705 if (!NT_STATUS_IS_OK(status)) {
706 werr = ntstatus_to_werror(status);
707 goto done;
708 }
709
710 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
711 &group_handle,
712 GROUPINFOALL2,
713 &info);
714 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
715 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
716 &group_handle,
717 GROUPINFOALL,
718 &info);
719 group_info_all = true;
720 }
721
722 if (!NT_STATUS_IS_OK(status)) {
723 werr = ntstatus_to_werror(status);
724 goto done;
725 }
726
727 werr = map_group_info_to_buffer(ctx, r->in.level,
728 group_info_all ? &info->all : &info->all2,
729 domain_sid, rids.ids[0],
730 r->out.buffer);
731 if (!W_ERROR_IS_OK(werr)) {
732 goto done;
733 }
734 done:
735 if (!cli) {
736 return werr;
737 }
738
739 if (is_valid_policy_hnd(&group_handle)) {
740 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
741 }
742
743 if (ctx->disable_policy_handle_cache) {
744 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
745 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
746 }
747
748 return werr;
749}
750
751/****************************************************************
752****************************************************************/
753
754WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
755 struct NetGroupGetInfo *r)
756{
757 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
758}
759
760/****************************************************************
761****************************************************************/
762
763WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
764 struct NetGroupAddUser *r)
765{
766 struct cli_state *cli = NULL;
767 struct rpc_pipe_client *pipe_cli = NULL;
768 NTSTATUS status;
769 WERROR werr;
770 POLICY_HND connect_handle, domain_handle, group_handle;
771 struct lsa_String lsa_group_name, lsa_user_name;
772 struct dom_sid2 *domain_sid = NULL;
773
774 struct samr_Ids rids;
775 struct samr_Ids types;
776
777 ZERO_STRUCT(connect_handle);
778 ZERO_STRUCT(domain_handle);
779 ZERO_STRUCT(group_handle);
780
781 if (!r->in.group_name) {
782 return WERR_INVALID_PARAM;
783 }
784
785 werr = libnetapi_open_pipe(ctx, r->in.server_name,
786 &ndr_table_samr.syntax_id,
787 &cli,
788 &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_LOOKUP_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
870 if (ctx->disable_policy_handle_cache) {
871 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
872 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
873 }
874
875 return werr;
876}
877
878/****************************************************************
879****************************************************************/
880
881WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
882 struct NetGroupAddUser *r)
883{
884 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
885}
886
887/****************************************************************
888****************************************************************/
889
890WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
891 struct NetGroupDelUser *r)
892{
893 struct cli_state *cli = NULL;
894 struct rpc_pipe_client *pipe_cli = NULL;
895 NTSTATUS status;
896 WERROR werr;
897 POLICY_HND connect_handle, domain_handle, group_handle;
898 struct lsa_String lsa_group_name, lsa_user_name;
899 struct dom_sid2 *domain_sid = NULL;
900
901 struct samr_Ids rids;
902 struct samr_Ids types;
903
904 ZERO_STRUCT(connect_handle);
905 ZERO_STRUCT(domain_handle);
906 ZERO_STRUCT(group_handle);
907
908 if (!r->in.group_name) {
909 return WERR_INVALID_PARAM;
910 }
911
912 werr = libnetapi_open_pipe(ctx, r->in.server_name,
913 &ndr_table_samr.syntax_id,
914 &cli,
915 &pipe_cli);
916 if (!W_ERROR_IS_OK(werr)) {
917 goto done;
918 }
919
920 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
921 SAMR_ACCESS_ENUM_DOMAINS |
922 SAMR_ACCESS_LOOKUP_DOMAIN,
923 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
924 &connect_handle,
925 &domain_handle,
926 &domain_sid);
927 if (!W_ERROR_IS_OK(werr)) {
928 goto done;
929 }
930
931 init_lsa_String(&lsa_group_name, r->in.group_name);
932
933 status = rpccli_samr_LookupNames(pipe_cli, ctx,
934 &domain_handle,
935 1,
936 &lsa_group_name,
937 &rids,
938 &types);
939 if (!NT_STATUS_IS_OK(status)) {
940 werr = WERR_GROUP_NOT_FOUND;
941 goto done;
942 }
943
944 if (types.ids[0] != SID_NAME_DOM_GRP) {
945 werr = WERR_GROUP_NOT_FOUND;
946 goto done;
947 }
948
949 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
950 &domain_handle,
951 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
952 rids.ids[0],
953 &group_handle);
954 if (!NT_STATUS_IS_OK(status)) {
955 werr = ntstatus_to_werror(status);
956 goto done;
957 }
958
959 init_lsa_String(&lsa_user_name, r->in.user_name);
960
961 status = rpccli_samr_LookupNames(pipe_cli, ctx,
962 &domain_handle,
963 1,
964 &lsa_user_name,
965 &rids,
966 &types);
967 if (!NT_STATUS_IS_OK(status)) {
968 werr = WERR_USER_NOT_FOUND;
969 goto done;
970 }
971
972 if (types.ids[0] != SID_NAME_USER) {
973 werr = WERR_USER_NOT_FOUND;
974 goto done;
975 }
976
977 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
978 &group_handle,
979 rids.ids[0]);
980 if (!NT_STATUS_IS_OK(status)) {
981 werr = ntstatus_to_werror(status);
982 goto done;
983 }
984
985 werr = WERR_OK;
986
987 done:
988 if (!cli) {
989 return werr;
990 }
991
992 if (is_valid_policy_hnd(&group_handle)) {
993 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
994 }
995
996 if (ctx->disable_policy_handle_cache) {
997 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
998 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
999 }
1000
1001 return werr;
1002}
1003
1004/****************************************************************
1005****************************************************************/
1006
1007WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1008 struct NetGroupDelUser *r)
1009{
1010 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1011}
1012
1013/****************************************************************
1014****************************************************************/
1015
1016static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1017 struct samr_DispInfoFullGroups *groups,
1018 uint8_t **buffer)
1019{
1020 struct GROUP_INFO_0 *g0;
1021 int i;
1022
1023 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
1024 W_ERROR_HAVE_NO_MEMORY(g0);
1025
1026 for (i=0; i<groups->count; i++) {
1027 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1028 groups->entries[i].account_name.string);
1029 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1030 }
1031
1032 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1033 sizeof(struct GROUP_INFO_0) * groups->count);
1034 W_ERROR_HAVE_NO_MEMORY(*buffer);
1035
1036 return WERR_OK;
1037}
1038
1039/****************************************************************
1040****************************************************************/
1041
1042static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1043 struct samr_DispInfoFullGroups *groups,
1044 uint8_t **buffer)
1045{
1046 struct GROUP_INFO_1 *g1;
1047 int i;
1048
1049 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1050 W_ERROR_HAVE_NO_MEMORY(g1);
1051
1052 for (i=0; i<groups->count; i++) {
1053 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1054 groups->entries[i].account_name.string);
1055 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1056 groups->entries[i].description.string);
1057 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1058 }
1059
1060 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1061 sizeof(struct GROUP_INFO_1) * groups->count);
1062 W_ERROR_HAVE_NO_MEMORY(*buffer);
1063
1064 return WERR_OK;
1065}
1066
1067/****************************************************************
1068****************************************************************/
1069
1070static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1071 struct samr_DispInfoFullGroups *groups,
1072 uint8_t **buffer)
1073{
1074 struct GROUP_INFO_2 *g2;
1075 int i;
1076
1077 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1078 W_ERROR_HAVE_NO_MEMORY(g2);
1079
1080 for (i=0; i<groups->count; i++) {
1081 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1082 groups->entries[i].account_name.string);
1083 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1084 groups->entries[i].description.string);
1085 g2[i].grpi2_group_id = groups->entries[i].rid;
1086 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1087 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1088 }
1089
1090 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1091 sizeof(struct GROUP_INFO_2) * groups->count);
1092 W_ERROR_HAVE_NO_MEMORY(*buffer);
1093
1094 return WERR_OK;
1095}
1096
1097/****************************************************************
1098****************************************************************/
1099
1100static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1101 struct samr_DispInfoFullGroups *groups,
1102 const struct dom_sid *domain_sid,
1103 uint8_t **buffer)
1104{
1105 struct GROUP_INFO_3 *g3;
1106 int i;
1107
1108 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1109 W_ERROR_HAVE_NO_MEMORY(g3);
1110
1111 for (i=0; i<groups->count; i++) {
1112
1113 struct dom_sid sid;
1114
1115 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1116 return WERR_NOMEM;
1117 }
1118
1119 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1120 groups->entries[i].account_name.string);
1121 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1122 groups->entries[i].description.string);
1123 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1124 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1125 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1126 }
1127
1128 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1129 sizeof(struct GROUP_INFO_3) * groups->count);
1130 W_ERROR_HAVE_NO_MEMORY(*buffer);
1131
1132 return WERR_OK;
1133}
1134
1135/****************************************************************
1136****************************************************************/
1137
1138static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1139 uint32_t level,
1140 struct samr_DispInfoFullGroups *groups,
1141 const struct dom_sid *domain_sid,
1142 uint32_t *entries_read,
1143 uint8_t **buffer)
1144{
1145 if (entries_read) {
1146 *entries_read = groups->count;
1147 }
1148
1149 switch (level) {
1150 case 0:
1151 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1152 case 1:
1153 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1154 case 2:
1155 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1156 case 3:
1157 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1158 default:
1159 return WERR_UNKNOWN_LEVEL;
1160 }
1161}
1162
1163/****************************************************************
1164****************************************************************/
1165
1166WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1167 struct NetGroupEnum *r)
1168{
1169 struct cli_state *cli = NULL;
1170 struct rpc_pipe_client *pipe_cli = NULL;
1171 struct policy_handle connect_handle;
1172 struct dom_sid2 *domain_sid = NULL;
1173 struct policy_handle domain_handle;
1174 union samr_DispInfo info;
1175 union samr_DomainInfo *domain_info = NULL;
1176
1177 uint32_t total_size = 0;
1178 uint32_t returned_size = 0;
1179
1180 NTSTATUS status = NT_STATUS_OK;
1181 WERROR werr, tmp_werr;
1182
1183 ZERO_STRUCT(connect_handle);
1184 ZERO_STRUCT(domain_handle);
1185
1186 switch (r->in.level) {
1187 case 0:
1188 case 1:
1189 case 2:
1190 case 3:
1191 break;
1192 default:
1193 return WERR_UNKNOWN_LEVEL;
1194 }
1195
1196 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1197 &ndr_table_samr.syntax_id,
1198 &cli,
1199 &pipe_cli);
1200 if (!W_ERROR_IS_OK(werr)) {
1201 goto done;
1202 }
1203
1204 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1205 SAMR_ACCESS_ENUM_DOMAINS |
1206 SAMR_ACCESS_LOOKUP_DOMAIN,
1207 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1208 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1209 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1210 &connect_handle,
1211 &domain_handle,
1212 &domain_sid);
1213 if (!W_ERROR_IS_OK(werr)) {
1214 goto done;
1215 }
1216
1217 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1218 &domain_handle,
1219 2,
1220 &domain_info);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 werr = ntstatus_to_werror(status);
1223 goto done;
1224 }
1225
1226 if (r->out.total_entries) {
1227 *r->out.total_entries = domain_info->info2.num_groups;
1228 }
1229
1230 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1231 ctx,
1232 &domain_handle,
1233 3,
1234 r->in.resume_handle ?
1235 *r->in.resume_handle : 0,
1236 (uint32_t)-1,
1237 r->in.prefmaxlen,
1238 &total_size,
1239 &returned_size,
1240 &info);
1241 werr = ntstatus_to_werror(status);
1242 if (NT_STATUS_IS_ERR(status)) {
1243 goto done;
1244 }
1245
1246 if (r->out.resume_handle && info.info3.count > 0) {
1247 *r->out.resume_handle =
1248 info.info3.entries[info.info3.count-1].idx;
1249 }
1250
1251 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1252 r->in.level,
1253 &info.info3,
1254 domain_sid,
1255 r->out.entries_read,
1256 r->out.buffer);
1257 if (!W_ERROR_IS_OK(tmp_werr)) {
1258 werr = tmp_werr;
1259 goto done;
1260 }
1261
1262 done:
1263 if (!cli) {
1264 return werr;
1265 }
1266
1267 /* if last query */
1268 if (NT_STATUS_IS_OK(status) ||
1269 NT_STATUS_IS_ERR(status)) {
1270
1271 if (ctx->disable_policy_handle_cache) {
1272 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1273 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1274 }
1275 }
1276
1277 return werr;
1278}
1279
1280/****************************************************************
1281****************************************************************/
1282
1283WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1284 struct NetGroupEnum *r)
1285{
1286 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1287}
1288
1289/****************************************************************
1290****************************************************************/
1291
1292WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1293 struct NetGroupGetUsers *r)
1294{
1295 /* FIXME: this call needs to cope with large replies */
1296
1297 struct cli_state *cli = NULL;
1298 struct rpc_pipe_client *pipe_cli = NULL;
1299 struct policy_handle connect_handle, domain_handle, group_handle;
1300 struct lsa_String lsa_account_name;
1301 struct dom_sid2 *domain_sid = NULL;
1302 struct samr_Ids group_rids, name_types;
1303 struct samr_RidTypeArray *rid_array = NULL;
1304 struct lsa_Strings names;
1305 struct samr_Ids member_types;
1306
1307 int i;
1308 uint32_t entries_read = 0;
1309
1310 NTSTATUS status = NT_STATUS_OK;
1311 WERROR werr;
1312
1313 ZERO_STRUCT(connect_handle);
1314 ZERO_STRUCT(domain_handle);
1315
1316 if (!r->out.buffer) {
1317 return WERR_INVALID_PARAM;
1318 }
1319
1320 *r->out.buffer = NULL;
1321 *r->out.entries_read = 0;
1322 *r->out.total_entries = 0;
1323
1324 switch (r->in.level) {
1325 case 0:
1326 case 1:
1327 break;
1328 default:
1329 return WERR_UNKNOWN_LEVEL;
1330 }
1331
1332
1333 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1334 &ndr_table_samr.syntax_id,
1335 &cli,
1336 &pipe_cli);
1337 if (!W_ERROR_IS_OK(werr)) {
1338 goto done;
1339 }
1340
1341 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1342 SAMR_ACCESS_ENUM_DOMAINS |
1343 SAMR_ACCESS_LOOKUP_DOMAIN,
1344 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1345 &connect_handle,
1346 &domain_handle,
1347 &domain_sid);
1348 if (!W_ERROR_IS_OK(werr)) {
1349 goto done;
1350 }
1351
1352 init_lsa_String(&lsa_account_name, r->in.group_name);
1353
1354 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1355 &domain_handle,
1356 1,
1357 &lsa_account_name,
1358 &group_rids,
1359 &name_types);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 werr = ntstatus_to_werror(status);
1362 goto done;
1363 }
1364
1365 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1366 &domain_handle,
1367 SAMR_GROUP_ACCESS_GET_MEMBERS,
1368 group_rids.ids[0],
1369 &group_handle);
1370 if (!NT_STATUS_IS_OK(status)) {
1371 werr = ntstatus_to_werror(status);
1372 goto done;
1373 }
1374
1375 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1376 &group_handle,
1377 &rid_array);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 werr = ntstatus_to_werror(status);
1380 goto done;
1381 }
1382
1383 status = rpccli_samr_LookupRids(pipe_cli, ctx,
1384 &domain_handle,
1385 rid_array->count,
1386 rid_array->rids,
1387 &names,
1388 &member_types);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 werr = ntstatus_to_werror(status);
1391 goto done;
1392 }
1393
1394 for (i=0; i < names.count; i++) {
1395
1396 if (member_types.ids[i] != SID_NAME_USER) {
1397 continue;
1398 }
1399
1400 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1401 r->in.level,
1402 names.names[i].string,
1403 7,
1404 r->out.buffer,
1405 &entries_read);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 werr = ntstatus_to_werror(status);
1408 goto done;
1409 }
1410 }
1411
1412 *r->out.entries_read = entries_read;
1413 *r->out.total_entries = entries_read;
1414
1415 werr = WERR_OK;
1416
1417 done:
1418 if (!cli) {
1419 return werr;
1420 }
1421
1422 if (is_valid_policy_hnd(&group_handle)) {
1423 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1424 }
1425
1426 if (ctx->disable_policy_handle_cache) {
1427 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1428 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1429 }
1430
1431 return werr;
1432}
1433
1434/****************************************************************
1435****************************************************************/
1436
1437WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1438 struct NetGroupGetUsers *r)
1439{
1440 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1441}
1442
1443/****************************************************************
1444****************************************************************/
1445
1446WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1447 struct NetGroupSetUsers *r)
1448{
1449 struct cli_state *cli = NULL;
1450 struct rpc_pipe_client *pipe_cli = NULL;
1451 struct policy_handle connect_handle, domain_handle, group_handle;
1452 struct lsa_String lsa_account_name;
1453 struct dom_sid2 *domain_sid = NULL;
1454 union samr_GroupInfo *group_info = NULL;
1455 struct samr_Ids user_rids, name_types;
1456 struct samr_Ids group_rids, group_types;
1457 struct samr_RidTypeArray *rid_array = NULL;
1458 struct lsa_String *lsa_names = NULL;
1459
1460 uint32_t *add_rids = NULL;
1461 uint32_t *del_rids = NULL;
1462 size_t num_add_rids = 0;
1463 size_t num_del_rids = 0;
1464
1465 uint32_t *member_rids = NULL;
1466 size_t num_member_rids = 0;
1467
1468 struct GROUP_USERS_INFO_0 *i0 = NULL;
1469 struct GROUP_USERS_INFO_1 *i1 = NULL;
1470
1471 int i, k;
1472
1473 NTSTATUS status = NT_STATUS_OK;
1474 WERROR werr;
1475
1476 ZERO_STRUCT(connect_handle);
1477 ZERO_STRUCT(domain_handle);
1478
1479 if (!r->in.buffer) {
1480 return WERR_INVALID_PARAM;
1481 }
1482
1483 switch (r->in.level) {
1484 case 0:
1485 case 1:
1486 break;
1487 default:
1488 return WERR_UNKNOWN_LEVEL;
1489 }
1490
1491 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1492 &ndr_table_samr.syntax_id,
1493 &cli,
1494 &pipe_cli);
1495 if (!W_ERROR_IS_OK(werr)) {
1496 goto done;
1497 }
1498
1499 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1500 SAMR_ACCESS_ENUM_DOMAINS |
1501 SAMR_ACCESS_LOOKUP_DOMAIN,
1502 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1503 &connect_handle,
1504 &domain_handle,
1505 &domain_sid);
1506 if (!W_ERROR_IS_OK(werr)) {
1507 goto done;
1508 }
1509
1510 init_lsa_String(&lsa_account_name, r->in.group_name);
1511
1512 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1513 &domain_handle,
1514 1,
1515 &lsa_account_name,
1516 &group_rids,
1517 &group_types);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 werr = ntstatus_to_werror(status);
1520 goto done;
1521 }
1522
1523 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1524 &domain_handle,
1525 SAMR_GROUP_ACCESS_GET_MEMBERS |
1526 SAMR_GROUP_ACCESS_ADD_MEMBER |
1527 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1528 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1529 group_rids.ids[0],
1530 &group_handle);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 werr = ntstatus_to_werror(status);
1533 goto done;
1534 }
1535
1536 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
1537 &group_handle,
1538 GROUPINFOATTRIBUTES,
1539 &group_info);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 werr = ntstatus_to_werror(status);
1542 goto done;
1543 }
1544
1545 switch (r->in.level) {
1546 case 0:
1547 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1548 break;
1549 case 1:
1550 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1551 break;
1552 }
1553
1554 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1555 if (!lsa_names) {
1556 werr = WERR_NOMEM;
1557 goto done;
1558 }
1559
1560 for (i=0; i < r->in.num_entries; i++) {
1561
1562 switch (r->in.level) {
1563 case 0:
1564 init_lsa_String(&lsa_names[i], i0->grui0_name);
1565 i0++;
1566 break;
1567 case 1:
1568 init_lsa_String(&lsa_names[i], i1->grui1_name);
1569 i1++;
1570 break;
1571 }
1572 }
1573
1574 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1575 &domain_handle,
1576 r->in.num_entries,
1577 lsa_names,
1578 &user_rids,
1579 &name_types);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 werr = ntstatus_to_werror(status);
1582 goto done;
1583 }
1584
1585 member_rids = user_rids.ids;
1586 num_member_rids = user_rids.count;
1587
1588 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1589 &group_handle,
1590 &rid_array);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 werr = ntstatus_to_werror(status);
1593 goto done;
1594 }
1595
1596 /* add list */
1597
1598 for (i=0; i < r->in.num_entries; i++) {
1599 bool already_member = false;
1600 for (k=0; k < rid_array->count; k++) {
1601 if (member_rids[i] == rid_array->rids[k]) {
1602 already_member = true;
1603 break;
1604 }
1605 }
1606 if (!already_member) {
1607 if (!add_rid_to_array_unique(ctx,
1608 member_rids[i],
1609 &add_rids, &num_add_rids)) {
1610 werr = WERR_GENERAL_FAILURE;
1611 goto done;
1612 }
1613 }
1614 }
1615
1616 /* del list */
1617
1618 for (k=0; k < rid_array->count; k++) {
1619 bool keep_member = false;
1620 for (i=0; i < r->in.num_entries; i++) {
1621 if (member_rids[i] == rid_array->rids[k]) {
1622 keep_member = true;
1623 break;
1624 }
1625 }
1626 if (!keep_member) {
1627 if (!add_rid_to_array_unique(ctx,
1628 rid_array->rids[k],
1629 &del_rids, &num_del_rids)) {
1630 werr = WERR_GENERAL_FAILURE;
1631 goto done;
1632 }
1633 }
1634 }
1635
1636 /* add list */
1637
1638 for (i=0; i < num_add_rids; i++) {
1639 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
1640 &group_handle,
1641 add_rids[i],
1642 7 /* ? */);
1643 if (!NT_STATUS_IS_OK(status)) {
1644 werr = ntstatus_to_werror(status);
1645 goto done;
1646 }
1647 }
1648
1649 /* del list */
1650
1651 for (i=0; i < num_del_rids; i++) {
1652 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
1653 &group_handle,
1654 del_rids[i]);
1655 if (!NT_STATUS_IS_OK(status)) {
1656 werr = ntstatus_to_werror(status);
1657 goto done;
1658 }
1659 }
1660
1661 werr = WERR_OK;
1662
1663 done:
1664 if (!cli) {
1665 return werr;
1666 }
1667
1668 if (is_valid_policy_hnd(&group_handle)) {
1669 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
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
1683WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1684 struct NetGroupSetUsers *r)
1685{
1686 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
1687}
Note: See TracBrowser for help on using the repository browser.