source: vendor/3.5.0/source3/lib/netapi/group.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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