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