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

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

File size: 46.5 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 "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
34WERROR 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_PARAM;
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.syntax_id,
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
240WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
241 struct NetGroupAdd *r)
242{
243 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
244}
245
246/****************************************************************
247****************************************************************/
248
249WERROR 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_PARAM;
272 }
273
274 werr = libnetapi_open_pipe(ctx, r->in.server_name,
275 &ndr_table_samr.syntax_id,
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
456WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
457 struct NetGroupDel *r)
458{
459 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
460}
461
462/****************************************************************
463****************************************************************/
464
465WERROR 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_PARAM;
492 }
493
494 werr = libnetapi_open_pipe(ctx, r->in.server_name,
495 &ndr_table_samr.syntax_id,
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
678WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
679 struct NetGroupSetInfo *r)
680{
681 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
682}
683
684/****************************************************************
685****************************************************************/
686
687static 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_NOMEM;
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
748WERROR 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_PARAM;
770 }
771
772 werr = libnetapi_open_pipe(ctx, r->in.server_name,
773 &ndr_table_samr.syntax_id,
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
889WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
890 struct NetGroupGetInfo *r)
891{
892 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
893}
894
895/****************************************************************
896****************************************************************/
897
898WERROR 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_PARAM;
918 }
919
920 werr = libnetapi_open_pipe(ctx, r->in.server_name,
921 &ndr_table_samr.syntax_id,
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_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_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
1049WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
1050 struct NetGroupAddUser *r)
1051{
1052 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
1053}
1054
1055/****************************************************************
1056****************************************************************/
1057
1058WERROR 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_PARAM;
1078 }
1079
1080 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1081 &ndr_table_samr.syntax_id,
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_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_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
1209WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1210 struct NetGroupDelUser *r)
1211{
1212 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1213}
1214
1215/****************************************************************
1216****************************************************************/
1217
1218static 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
1244static 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
1272static 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
1302static 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_NOMEM;
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
1340static 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
1368WERROR 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.syntax_id,
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
1494WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1495 struct NetGroupEnum *r)
1496{
1497 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1498}
1499
1500/****************************************************************
1501****************************************************************/
1502
1503WERROR 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
1528 if (!r->out.buffer) {
1529 return WERR_INVALID_PARAM;
1530 }
1531
1532 *r->out.buffer = NULL;
1533 *r->out.entries_read = 0;
1534 *r->out.total_entries = 0;
1535
1536 switch (r->in.level) {
1537 case 0:
1538 case 1:
1539 break;
1540 default:
1541 return WERR_UNKNOWN_LEVEL;
1542 }
1543
1544
1545 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1546 &ndr_table_samr.syntax_id,
1547 &pipe_cli);
1548 if (!W_ERROR_IS_OK(werr)) {
1549 goto done;
1550 }
1551
1552 b = pipe_cli->binding_handle;
1553
1554 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1555 SAMR_ACCESS_ENUM_DOMAINS |
1556 SAMR_ACCESS_LOOKUP_DOMAIN,
1557 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1558 &connect_handle,
1559 &domain_handle,
1560 &domain_sid);
1561 if (!W_ERROR_IS_OK(werr)) {
1562 goto done;
1563 }
1564
1565 init_lsa_String(&lsa_account_name, r->in.group_name);
1566
1567 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1568 &domain_handle,
1569 1,
1570 &lsa_account_name,
1571 &group_rids,
1572 &name_types,
1573 &result);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 werr = ntstatus_to_werror(status);
1576 goto done;
1577 }
1578 if (!NT_STATUS_IS_OK(result)) {
1579 werr = ntstatus_to_werror(result);
1580 goto done;
1581 }
1582 if (group_rids.count != 1) {
1583 werr = WERR_BAD_NET_RESP;
1584 goto done;
1585 }
1586 if (name_types.count != 1) {
1587 werr = WERR_BAD_NET_RESP;
1588 goto done;
1589 }
1590
1591 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1592 &domain_handle,
1593 SAMR_GROUP_ACCESS_GET_MEMBERS,
1594 group_rids.ids[0],
1595 &group_handle,
1596 &result);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 werr = ntstatus_to_werror(status);
1599 goto done;
1600 }
1601 if (!NT_STATUS_IS_OK(result)) {
1602 werr = ntstatus_to_werror(result);
1603 goto done;
1604 }
1605
1606 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1607 &group_handle,
1608 &rid_array,
1609 &result);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 werr = ntstatus_to_werror(status);
1612 goto done;
1613 }
1614 if (!NT_STATUS_IS_OK(result)) {
1615 werr = ntstatus_to_werror(result);
1616 goto done;
1617 }
1618
1619 status = dcerpc_samr_LookupRids(b, talloc_tos(),
1620 &domain_handle,
1621 rid_array->count,
1622 rid_array->rids,
1623 &names,
1624 &member_types,
1625 &result);
1626 if (!NT_STATUS_IS_OK(status)) {
1627 werr = ntstatus_to_werror(status);
1628 goto done;
1629 }
1630 if (!NT_STATUS_IS_OK(result)) {
1631 werr = ntstatus_to_werror(result);
1632 goto done;
1633 }
1634 if (names.count != rid_array->count) {
1635 werr = WERR_BAD_NET_RESP;
1636 goto done;
1637 }
1638 if (member_types.count != rid_array->count) {
1639 werr = WERR_BAD_NET_RESP;
1640 goto done;
1641 }
1642
1643 for (i=0; i < names.count; i++) {
1644
1645 if (member_types.ids[i] != SID_NAME_USER) {
1646 continue;
1647 }
1648
1649 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1650 r->in.level,
1651 names.names[i].string,
1652 7,
1653 r->out.buffer,
1654 &entries_read);
1655 if (!NT_STATUS_IS_OK(status)) {
1656 werr = ntstatus_to_werror(status);
1657 goto done;
1658 }
1659 }
1660
1661 *r->out.entries_read = entries_read;
1662 *r->out.total_entries = entries_read;
1663
1664 werr = WERR_OK;
1665
1666 done:
1667 if (is_valid_policy_hnd(&group_handle)) {
1668 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1669 }
1670
1671 if (ctx->disable_policy_handle_cache) {
1672 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1673 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1674 }
1675
1676 return werr;
1677}
1678
1679/****************************************************************
1680****************************************************************/
1681
1682WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1683 struct NetGroupGetUsers *r)
1684{
1685 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1686}
1687
1688/****************************************************************
1689****************************************************************/
1690
1691WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1692 struct NetGroupSetUsers *r)
1693{
1694 struct rpc_pipe_client *pipe_cli = NULL;
1695 struct policy_handle connect_handle, domain_handle, group_handle;
1696 struct lsa_String lsa_account_name;
1697 struct dom_sid2 *domain_sid = NULL;
1698 union samr_GroupInfo *group_info = NULL;
1699 struct samr_Ids user_rids, name_types;
1700 struct samr_Ids group_rids, group_types;
1701 struct samr_RidAttrArray *rid_array = NULL;
1702 struct lsa_String *lsa_names = NULL;
1703 struct dcerpc_binding_handle *b = NULL;
1704
1705 uint32_t *add_rids = NULL;
1706 uint32_t *del_rids = NULL;
1707 size_t num_add_rids = 0;
1708 size_t num_del_rids = 0;
1709
1710 uint32_t *member_rids = NULL;
1711
1712 struct GROUP_USERS_INFO_0 *i0 = NULL;
1713 struct GROUP_USERS_INFO_1 *i1 = NULL;
1714
1715 int i, k;
1716
1717 NTSTATUS status = NT_STATUS_OK;
1718 NTSTATUS result = NT_STATUS_OK;
1719 WERROR werr;
1720
1721 ZERO_STRUCT(connect_handle);
1722 ZERO_STRUCT(domain_handle);
1723
1724 if (!r->in.buffer) {
1725 return WERR_INVALID_PARAM;
1726 }
1727
1728 switch (r->in.level) {
1729 case 0:
1730 case 1:
1731 break;
1732 default:
1733 return WERR_UNKNOWN_LEVEL;
1734 }
1735
1736 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1737 &ndr_table_samr.syntax_id,
1738 &pipe_cli);
1739 if (!W_ERROR_IS_OK(werr)) {
1740 goto done;
1741 }
1742
1743 b = pipe_cli->binding_handle;
1744
1745 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1746 SAMR_ACCESS_ENUM_DOMAINS |
1747 SAMR_ACCESS_LOOKUP_DOMAIN,
1748 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1749 &connect_handle,
1750 &domain_handle,
1751 &domain_sid);
1752 if (!W_ERROR_IS_OK(werr)) {
1753 goto done;
1754 }
1755
1756 init_lsa_String(&lsa_account_name, r->in.group_name);
1757
1758 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1759 &domain_handle,
1760 1,
1761 &lsa_account_name,
1762 &group_rids,
1763 &group_types,
1764 &result);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 werr = ntstatus_to_werror(status);
1767 goto done;
1768 }
1769 if (!NT_STATUS_IS_OK(result)) {
1770 werr = ntstatus_to_werror(result);
1771 goto done;
1772 }
1773 if (group_rids.count != 1) {
1774 werr = WERR_BAD_NET_RESP;
1775 goto done;
1776 }
1777 if (group_types.count != 1) {
1778 werr = WERR_BAD_NET_RESP;
1779 goto done;
1780 }
1781
1782 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1783 &domain_handle,
1784 SAMR_GROUP_ACCESS_GET_MEMBERS |
1785 SAMR_GROUP_ACCESS_ADD_MEMBER |
1786 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1787 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1788 group_rids.ids[0],
1789 &group_handle,
1790 &result);
1791 if (!NT_STATUS_IS_OK(status)) {
1792 werr = ntstatus_to_werror(status);
1793 goto done;
1794 }
1795 if (!NT_STATUS_IS_OK(result)) {
1796 werr = ntstatus_to_werror(result);
1797 goto done;
1798 }
1799
1800 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1801 &group_handle,
1802 GROUPINFOATTRIBUTES,
1803 &group_info,
1804 &result);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 werr = ntstatus_to_werror(status);
1807 goto done;
1808 }
1809 if (!NT_STATUS_IS_OK(result)) {
1810 werr = ntstatus_to_werror(result);
1811 goto done;
1812 }
1813
1814 switch (r->in.level) {
1815 case 0:
1816 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1817 break;
1818 case 1:
1819 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1820 break;
1821 }
1822
1823 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1824 if (!lsa_names) {
1825 werr = WERR_NOMEM;
1826 goto done;
1827 }
1828
1829 for (i=0; i < r->in.num_entries; i++) {
1830
1831 switch (r->in.level) {
1832 case 0:
1833 init_lsa_String(&lsa_names[i], i0->grui0_name);
1834 i0++;
1835 break;
1836 case 1:
1837 init_lsa_String(&lsa_names[i], i1->grui1_name);
1838 i1++;
1839 break;
1840 }
1841 }
1842
1843 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1844 &domain_handle,
1845 r->in.num_entries,
1846 lsa_names,
1847 &user_rids,
1848 &name_types,
1849 &result);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 werr = ntstatus_to_werror(status);
1852 goto done;
1853 }
1854 if (!NT_STATUS_IS_OK(result)) {
1855 werr = ntstatus_to_werror(result);
1856 goto done;
1857 }
1858
1859 if (r->in.num_entries != user_rids.count) {
1860 werr = WERR_BAD_NET_RESP;
1861 goto done;
1862 }
1863 if (r->in.num_entries != name_types.count) {
1864 werr = WERR_BAD_NET_RESP;
1865 goto done;
1866 }
1867
1868 member_rids = user_rids.ids;
1869
1870 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1871 &group_handle,
1872 &rid_array,
1873 &result);
1874 if (!NT_STATUS_IS_OK(status)) {
1875 werr = ntstatus_to_werror(status);
1876 goto done;
1877 }
1878 if (!NT_STATUS_IS_OK(result)) {
1879 werr = ntstatus_to_werror(result);
1880 goto done;
1881 }
1882
1883 /* add list */
1884
1885 for (i=0; i < r->in.num_entries; i++) {
1886 bool already_member = false;
1887 for (k=0; k < rid_array->count; k++) {
1888 if (member_rids[i] == rid_array->rids[k]) {
1889 already_member = true;
1890 break;
1891 }
1892 }
1893 if (!already_member) {
1894 if (!add_rid_to_array_unique(ctx,
1895 member_rids[i],
1896 &add_rids, &num_add_rids)) {
1897 werr = WERR_GENERAL_FAILURE;
1898 goto done;
1899 }
1900 }
1901 }
1902
1903 /* del list */
1904
1905 for (k=0; k < rid_array->count; k++) {
1906 bool keep_member = false;
1907 for (i=0; i < r->in.num_entries; i++) {
1908 if (member_rids[i] == rid_array->rids[k]) {
1909 keep_member = true;
1910 break;
1911 }
1912 }
1913 if (!keep_member) {
1914 if (!add_rid_to_array_unique(ctx,
1915 rid_array->rids[k],
1916 &del_rids, &num_del_rids)) {
1917 werr = WERR_GENERAL_FAILURE;
1918 goto done;
1919 }
1920 }
1921 }
1922
1923 /* add list */
1924
1925 for (i=0; i < num_add_rids; i++) {
1926 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1927 &group_handle,
1928 add_rids[i],
1929 7 /* ? */,
1930 &result);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 werr = ntstatus_to_werror(status);
1933 goto done;
1934 }
1935 if (!NT_STATUS_IS_OK(result)) {
1936 werr = ntstatus_to_werror(result);
1937 goto done;
1938 }
1939 }
1940
1941 /* del list */
1942
1943 for (i=0; i < num_del_rids; i++) {
1944 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1945 &group_handle,
1946 del_rids[i],
1947 &result);
1948 if (!NT_STATUS_IS_OK(status)) {
1949 werr = ntstatus_to_werror(status);
1950 goto done;
1951 }
1952 if (!NT_STATUS_IS_OK(result)) {
1953 werr = ntstatus_to_werror(result);
1954 goto done;
1955 }
1956 }
1957
1958 werr = WERR_OK;
1959
1960 done:
1961 if (is_valid_policy_hnd(&group_handle)) {
1962 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1963 }
1964
1965 if (ctx->disable_policy_handle_cache) {
1966 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1967 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1968 }
1969
1970 return werr;
1971}
1972
1973/****************************************************************
1974****************************************************************/
1975
1976WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1977 struct NetGroupSetUsers *r)
1978{
1979 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
1980}
Note: See TracBrowser for help on using the repository browser.