libnetapi: fill in NetQueryDisplayInformation_r.
[Samba/gebeck_regimport.git] / source3 / lib / netapi / user.c
blob55d9795f2d1c18f4b978ea7a4f07e31f711d61fa
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi User Support
4 * Copyright (C) Guenther Deschner 2008
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.
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.
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/>.
20 #include "includes.h"
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"
27 /****************************************************************
28 ****************************************************************/
30 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
31 struct NetUserAdd *r)
33 return WERR_NOT_SUPPORTED;
36 /****************************************************************
37 ****************************************************************/
39 static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1,
40 DATA_BLOB *user_session_key,
41 struct samr_UserInfo25 *info25)
43 uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
44 struct samr_LogonHours zero_logon_hours;
45 struct lsa_BinaryString zero_parameters;
46 uint32_t acct_flags = 0;
47 NTTIME password_age;
49 ZERO_STRUCTP(info25);
50 ZERO_STRUCT(zero_logon_hours);
51 ZERO_STRUCT(zero_parameters);
53 if (info1->usri1_name) {
54 fields_present |= SAMR_FIELD_FULL_NAME;
56 if (info1->usri1_password) {
57 fields_present |= SAMR_FIELD_PASSWORD;
59 if (info1->usri1_flags) {
60 fields_present |= SAMR_FIELD_ACCT_FLAGS;
62 if (info1->usri1_name) {
63 fields_present |= SAMR_FIELD_FULL_NAME;
65 if (info1->usri1_home_dir) {
66 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
68 if (info1->usri1_script_path) {
69 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
71 if (info1->usri1_comment) {
72 fields_present |= SAMR_FIELD_DESCRIPTION;
74 if (info1->usri1_password_age) {
75 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
78 acct_flags |= info1->usri1_flags | ACB_NORMAL;
80 unix_to_nt_time_abs(&password_age, info1->usri1_password_age);
82 /* TODO: info1->usri1_priv */
83 init_samr_user_info21(&info25->info,
89 password_age,
90 NULL,
91 info1->usri1_name,
92 info1->usri1_home_dir,
93 NULL,
94 info1->usri1_script_path,
95 NULL,
96 info1->usri1_comment,
97 NULL,
98 NULL,
99 &zero_parameters,
102 acct_flags,
103 fields_present,
104 zero_logon_hours,
113 if (info1->usri1_password) {
114 uchar pwbuf[532];
115 struct MD5Context ctx;
116 uint8_t confounder[16];
117 DATA_BLOB confounded_session_key = data_blob(NULL, 16);
119 encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE);
121 generate_random_buffer((uint8_t *)confounder, 16);
123 MD5Init(&ctx);
124 MD5Update(&ctx, confounder, 16);
125 MD5Update(&ctx, user_session_key->data,
126 user_session_key->length);
127 MD5Final(confounded_session_key.data, &ctx);
129 SamOEMhashBlob(pwbuf, 516, &confounded_session_key);
130 memcpy(&pwbuf[516], confounder, 16);
132 memcpy(info25->password.data, pwbuf, sizeof(pwbuf));
133 data_blob_free(&confounded_session_key);
137 /****************************************************************
138 ****************************************************************/
140 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
141 struct NetUserAdd *r)
143 struct cli_state *cli = NULL;
144 struct rpc_pipe_client *pipe_cli = NULL;
145 NTSTATUS status;
146 WERROR werr;
147 uint32_t resume_handle = 0;
148 uint32_t num_entries = 0;
149 POLICY_HND connect_handle, domain_handle, user_handle;
150 struct samr_SamArray *sam = NULL;
151 const char *domain_name = NULL;
152 struct lsa_String lsa_domain_name, lsa_account_name;
153 struct dom_sid2 *domain_sid = NULL;
154 struct samr_UserInfo25 info25;
155 union samr_UserInfo *user_info = NULL;
156 struct samr_PwInfo pw_info;
157 uint32_t access_granted = 0;
158 uint32_t rid = 0;
159 bool domain_found = true;
160 int i;
161 struct USER_INFO_1 *info1;
163 ZERO_STRUCT(connect_handle);
164 ZERO_STRUCT(domain_handle);
165 ZERO_STRUCT(user_handle);
167 if (!r->in.buffer) {
168 return WERR_INVALID_PARAM;
171 switch (r->in.level) {
172 case 1:
173 info1 = (struct USER_INFO_1 *)r->in.buffer;
174 break;
175 case 2:
176 case 3:
177 case 4:
178 default:
179 werr = WERR_NOT_SUPPORTED;
180 goto done;
183 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
184 if (!W_ERROR_IS_OK(werr)) {
185 goto done;
188 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
189 if (!W_ERROR_IS_OK(werr)) {
190 goto done;
193 status = rpccli_try_samr_connects(pipe_cli, ctx,
194 SAMR_ACCESS_ENUM_DOMAINS |
195 SAMR_ACCESS_OPEN_DOMAIN,
196 &connect_handle);
197 if (!NT_STATUS_IS_OK(status)) {
198 werr = ntstatus_to_werror(status);
199 goto done;
202 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
203 &connect_handle,
204 &resume_handle,
205 &sam,
206 0xffffffff,
207 &num_entries);
208 if (!NT_STATUS_IS_OK(status)) {
209 werr = ntstatus_to_werror(status);
210 goto done;
213 for (i=0; i<num_entries; i++) {
215 domain_name = sam->entries[i].name.string;
217 if (strequal(domain_name, builtin_domain_name())) {
218 continue;
221 domain_found = true;
222 break;
225 if (!domain_found) {
226 werr = WERR_NO_SUCH_DOMAIN;
227 goto done;
230 init_lsa_String(&lsa_domain_name, domain_name);
232 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
233 &connect_handle,
234 &lsa_domain_name,
235 &domain_sid);
236 if (!NT_STATUS_IS_OK(status)) {
237 werr = ntstatus_to_werror(status);
238 goto done;
241 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
242 &connect_handle,
243 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
244 SAMR_DOMAIN_ACCESS_CREATE_USER |
245 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
246 domain_sid,
247 &domain_handle);
248 if (!NT_STATUS_IS_OK(status)) {
249 werr = ntstatus_to_werror(status);
250 goto done;
253 init_lsa_String(&lsa_account_name, info1->usri1_name);
255 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
256 &domain_handle,
257 &lsa_account_name,
258 ACB_NORMAL,
259 SEC_STD_WRITE_DAC |
260 SEC_STD_DELETE |
261 SAMR_USER_ACCESS_SET_PASSWORD |
262 SAMR_USER_ACCESS_SET_ATTRIBUTES |
263 SAMR_USER_ACCESS_GET_ATTRIBUTES,
264 &user_handle,
265 &access_granted,
266 &rid);
267 if (!NT_STATUS_IS_OK(status)) {
268 werr = ntstatus_to_werror(status);
269 goto done;
272 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
273 &user_handle,
275 &user_info);
276 if (!NT_STATUS_IS_OK(status)) {
277 werr = ntstatus_to_werror(status);
278 goto done;
281 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
282 werr = WERR_INVALID_PARAM;
283 goto done;
286 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
287 &user_handle,
288 &pw_info);
289 if (!NT_STATUS_IS_OK(status)) {
290 werr = ntstatus_to_werror(status);
291 goto done;
294 ZERO_STRUCTP(user_info);
296 convert_USER_INFO_1_to_samr_user_info25(info1,
297 &cli->user_session_key,
298 &info25);
300 if (info1->usri1_password) {
301 user_info->info25 = info25;
302 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
303 &user_handle,
305 user_info);
306 } else {
307 user_info->info21 = info25.info;
308 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
309 &user_handle,
311 user_info);
314 if (!NT_STATUS_IS_OK(status)) {
315 werr = ntstatus_to_werror(status);
316 goto failed;
319 werr = WERR_OK;
320 goto done;
322 failed:
323 rpccli_samr_DeleteUser(pipe_cli, ctx,
324 &user_handle);
326 done:
327 if (!cli) {
328 return werr;
331 if (is_valid_policy_hnd(&user_handle)) {
332 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
334 if (is_valid_policy_hnd(&domain_handle)) {
335 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
337 if (is_valid_policy_hnd(&connect_handle)) {
338 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
341 return werr;
344 /****************************************************************
345 ****************************************************************/
347 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
348 struct NetUserDel *r)
350 struct cli_state *cli = NULL;
351 struct rpc_pipe_client *pipe_cli = NULL;
352 NTSTATUS status;
353 WERROR werr;
354 uint32_t resume_handle = 0;
355 uint32_t num_entries = 0;
356 POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
357 struct samr_SamArray *sam = NULL;
358 const char *domain_name = NULL;
359 struct lsa_String lsa_domain_name, lsa_account_name;
360 struct samr_Ids user_rids, name_types;
361 struct dom_sid2 *domain_sid = NULL;
362 struct dom_sid2 user_sid;
363 bool domain_found = true;
364 int i;
366 ZERO_STRUCT(connect_handle);
367 ZERO_STRUCT(builtin_handle);
368 ZERO_STRUCT(domain_handle);
369 ZERO_STRUCT(user_handle);
371 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
372 if (!W_ERROR_IS_OK(werr)) {
373 goto done;
376 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
377 if (!W_ERROR_IS_OK(werr)) {
378 goto done;
381 status = rpccli_try_samr_connects(pipe_cli, ctx,
382 SAMR_ACCESS_ENUM_DOMAINS |
383 SAMR_ACCESS_OPEN_DOMAIN,
384 &connect_handle);
385 if (!NT_STATUS_IS_OK(status)) {
386 werr = ntstatus_to_werror(status);
387 goto done;
390 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
391 &connect_handle,
392 &resume_handle,
393 &sam,
394 0xffffffff,
395 &num_entries);
396 if (!NT_STATUS_IS_OK(status)) {
397 werr = ntstatus_to_werror(status);
398 goto done;
401 for (i=0; i<num_entries; i++) {
403 domain_name = sam->entries[i].name.string;
405 if (strequal(domain_name, builtin_domain_name())) {
406 continue;
409 domain_found = true;
410 break;
413 if (!domain_found) {
414 werr = WERR_NO_SUCH_DOMAIN;
415 goto done;
418 init_lsa_String(&lsa_domain_name, domain_name);
420 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
421 &connect_handle,
422 &lsa_domain_name,
423 &domain_sid);
424 if (!NT_STATUS_IS_OK(status)) {
425 werr = ntstatus_to_werror(status);
426 goto done;
429 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
430 &connect_handle,
431 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
432 domain_sid,
433 &domain_handle);
434 if (!NT_STATUS_IS_OK(status)) {
435 werr = ntstatus_to_werror(status);
436 goto done;
439 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
440 &connect_handle,
441 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
442 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
443 &builtin_handle);
444 if (!NT_STATUS_IS_OK(status)) {
445 werr = ntstatus_to_werror(status);
446 goto done;
449 init_lsa_String(&lsa_account_name, r->in.user_name);
451 status = rpccli_samr_LookupNames(pipe_cli, ctx,
452 &domain_handle,
454 &lsa_account_name,
455 &user_rids,
456 &name_types);
457 if (!NT_STATUS_IS_OK(status)) {
458 werr = ntstatus_to_werror(status);
459 goto done;
462 status = rpccli_samr_OpenUser(pipe_cli, ctx,
463 &domain_handle,
464 STD_RIGHT_DELETE_ACCESS,
465 user_rids.ids[0],
466 &user_handle);
467 if (!NT_STATUS_IS_OK(status)) {
468 werr = ntstatus_to_werror(status);
469 goto done;
472 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
474 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
475 &builtin_handle,
476 &user_sid);
477 if (!NT_STATUS_IS_OK(status)) {
478 werr = ntstatus_to_werror(status);
479 goto done;
482 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
483 &user_handle);
484 if (!NT_STATUS_IS_OK(status)) {
485 werr = ntstatus_to_werror(status);
486 goto done;
489 werr = WERR_OK;
491 done:
492 if (!cli) {
493 return werr;
496 if (is_valid_policy_hnd(&user_handle)) {
497 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
499 if (is_valid_policy_hnd(&builtin_handle)) {
500 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
502 if (is_valid_policy_hnd(&domain_handle)) {
503 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
505 if (is_valid_policy_hnd(&connect_handle)) {
506 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
509 return werr;
512 /****************************************************************
513 ****************************************************************/
515 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
516 struct NetUserDel *r)
518 return WERR_NOT_SUPPORTED;
521 /****************************************************************
522 ****************************************************************/
524 static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx,
525 struct samr_SamArray *sam_array,
526 uint32_t level,
527 uint8_t **buffer)
529 struct USER_INFO_0 *info0 = NULL;
530 int i;
532 switch (level) {
533 case 0:
534 info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0,
535 sam_array->count);
536 W_ERROR_HAVE_NO_MEMORY(info0);
538 for (i=0; i<sam_array->count; i++) {
539 info0[i].usri0_name = talloc_strdup(mem_ctx,
540 sam_array->entries[i].name.string);
541 W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name);
544 *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0,
545 sizeof(struct USER_INFO_0) * sam_array->count);
546 W_ERROR_HAVE_NO_MEMORY(*buffer);
547 break;
548 default:
549 return WERR_NOT_SUPPORTED;
552 return WERR_OK;
555 /****************************************************************
556 ****************************************************************/
558 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
559 struct NetUserEnum *r)
561 struct cli_state *cli = NULL;
562 struct rpc_pipe_client *pipe_cli = NULL;
563 struct policy_handle connect_handle;
564 struct dom_sid2 *domain_sid = NULL;
565 struct policy_handle domain_handle;
566 struct samr_SamArray *sam = NULL;
567 uint32_t num_entries = 0;
568 int i;
569 const char *domain_name = NULL;
570 bool domain_found = true;
571 uint32_t dom_resume_handle = 0;
572 struct lsa_String lsa_domain_name;
574 NTSTATUS status;
575 WERROR werr;
577 ZERO_STRUCT(connect_handle);
578 ZERO_STRUCT(domain_handle);
580 switch (r->in.level) {
581 case 0:
582 break;
583 case 1:
584 case 2:
585 case 3:
586 case 10:
587 case 11:
588 case 20:
589 case 23:
590 default:
591 return WERR_NOT_SUPPORTED;
594 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
595 if (!W_ERROR_IS_OK(werr)) {
596 goto done;
599 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
600 if (!W_ERROR_IS_OK(werr)) {
601 goto done;
604 status = rpccli_try_samr_connects(pipe_cli, ctx,
605 SAMR_ACCESS_OPEN_DOMAIN |
606 SAMR_ACCESS_ENUM_DOMAINS,
607 &connect_handle);
608 if (!NT_STATUS_IS_OK(status)) {
609 werr = ntstatus_to_werror(status);
610 goto done;
613 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
614 &connect_handle,
615 &dom_resume_handle,
616 &sam,
617 0xffffffff,
618 &num_entries);
619 if (!NT_STATUS_IS_OK(status)) {
620 werr = ntstatus_to_werror(status);
621 goto done;
624 for (i=0; i<num_entries; i++) {
626 domain_name = sam->entries[i].name.string;
628 if (strequal(domain_name, builtin_domain_name())) {
629 continue;
632 domain_found = true;
633 break;
636 if (!domain_found) {
637 werr = WERR_NO_SUCH_DOMAIN;
638 goto done;
641 init_lsa_String(&lsa_domain_name, domain_name);
643 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
644 &connect_handle,
645 &lsa_domain_name,
646 &domain_sid);
647 if (!NT_STATUS_IS_OK(status)) {
648 werr = ntstatus_to_werror(status);
649 goto done;
652 status = rpccli_samr_OpenDomain(pipe_cli,
653 ctx,
654 &connect_handle,
655 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
656 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
657 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
658 domain_sid,
659 &domain_handle);
660 if (!NT_STATUS_IS_OK(status)) {
661 werr = ntstatus_to_werror(status);
662 goto done;
665 status = rpccli_samr_EnumDomainUsers(pipe_cli,
666 ctx,
667 &domain_handle,
668 r->in.resume_handle,
669 r->in.filter,
670 &sam,
671 r->in.prefmaxlen,
672 r->out.entries_read);
673 if (!NT_STATUS_IS_OK(status)) {
674 werr = ntstatus_to_werror(status);
675 goto done;
678 werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
679 r->in.level,
680 r->out.buffer);
682 done:
683 if (!cli) {
684 return werr;
687 if (is_valid_policy_hnd(&domain_handle)) {
688 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
690 if (is_valid_policy_hnd(&connect_handle)) {
691 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
694 return werr;
697 /****************************************************************
698 ****************************************************************/
700 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
701 struct NetUserEnum *r)
703 return WERR_NOT_SUPPORTED;
706 /****************************************************************
707 ****************************************************************/
709 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
710 struct samr_DispInfoGeneral *info,
711 uint32_t *entries_read,
712 void **buffer)
714 struct NET_DISPLAY_USER *user = NULL;
715 int i;
717 user = TALLOC_ZERO_ARRAY(mem_ctx,
718 struct NET_DISPLAY_USER,
719 info->count);
720 W_ERROR_HAVE_NO_MEMORY(user);
722 for (i = 0; i < info->count; i++) {
723 user[i].usri1_name = talloc_strdup(mem_ctx,
724 info->entries[i].account_name.string);
725 user[i].usri1_comment = talloc_strdup(mem_ctx,
726 info->entries[i].description.string);
727 user[i].usri1_flags =
728 info->entries[i].acct_flags;
729 user[i].usri1_full_name = talloc_strdup(mem_ctx,
730 info->entries[i].full_name.string);
731 user[i].usri1_user_id =
732 info->entries[i].rid;
733 user[i].usri1_next_index =
734 info->entries[i].idx;
736 if (!user[i].usri1_name) {
737 return WERR_NOMEM;
741 *buffer = talloc_memdup(mem_ctx, user,
742 sizeof(struct NET_DISPLAY_USER) * info->count);
743 W_ERROR_HAVE_NO_MEMORY(*buffer);
745 *entries_read = info->count;
747 return WERR_OK;
750 /****************************************************************
751 ****************************************************************/
753 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
754 struct samr_DispInfoFull *info,
755 uint32_t *entries_read,
756 void **buffer)
758 struct NET_DISPLAY_MACHINE *machine = NULL;
759 int i;
761 machine = TALLOC_ZERO_ARRAY(mem_ctx,
762 struct NET_DISPLAY_MACHINE,
763 info->count);
764 W_ERROR_HAVE_NO_MEMORY(machine);
766 for (i = 0; i < info->count; i++) {
767 machine[i].usri2_name = talloc_strdup(mem_ctx,
768 info->entries[i].account_name.string);
769 machine[i].usri2_comment = talloc_strdup(mem_ctx,
770 info->entries[i].description.string);
771 machine[i].usri2_flags =
772 info->entries[i].acct_flags;
773 machine[i].usri2_user_id =
774 info->entries[i].rid;
775 machine[i].usri2_next_index =
776 info->entries[i].idx;
778 if (!machine[i].usri2_name) {
779 return WERR_NOMEM;
783 *buffer = talloc_memdup(mem_ctx, machine,
784 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
785 W_ERROR_HAVE_NO_MEMORY(*buffer);
787 *entries_read = info->count;
789 return WERR_OK;
792 /****************************************************************
793 ****************************************************************/
795 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
796 struct samr_DispInfoFullGroups *info,
797 uint32_t *entries_read,
798 void **buffer)
800 struct NET_DISPLAY_GROUP *group = NULL;
801 int i;
803 group = TALLOC_ZERO_ARRAY(mem_ctx,
804 struct NET_DISPLAY_GROUP,
805 info->count);
806 W_ERROR_HAVE_NO_MEMORY(group);
808 for (i = 0; i < info->count; i++) {
809 group[i].grpi3_name = talloc_strdup(mem_ctx,
810 info->entries[i].account_name.string);
811 group[i].grpi3_comment = talloc_strdup(mem_ctx,
812 info->entries[i].description.string);
813 group[i].grpi3_group_id =
814 info->entries[i].rid;
815 group[i].grpi3_attributes =
816 info->entries[i].acct_flags;
817 group[i].grpi3_next_index =
818 info->entries[i].idx;
820 if (!group[i].grpi3_name) {
821 return WERR_NOMEM;
825 *buffer = talloc_memdup(mem_ctx, group,
826 sizeof(struct NET_DISPLAY_GROUP) * info->count);
827 W_ERROR_HAVE_NO_MEMORY(*buffer);
829 *entries_read = info->count;
831 return WERR_OK;
835 /****************************************************************
836 ****************************************************************/
838 WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
839 union samr_DispInfo *info,
840 uint32_t level,
841 uint32_t *entries_read,
842 void **buffer)
844 switch (level) {
845 case 1:
846 return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
847 &info->info1,
848 entries_read,
849 buffer);
850 case 2:
851 return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
852 &info->info2,
853 entries_read,
854 buffer);
855 case 3:
856 return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
857 &info->info3,
858 entries_read,
859 buffer);
860 default:
861 return WERR_UNKNOWN_LEVEL;
864 return WERR_OK;
867 /****************************************************************
868 ****************************************************************/
870 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
871 struct NetQueryDisplayInformation *r)
873 struct cli_state *cli = NULL;
874 struct rpc_pipe_client *pipe_cli = NULL;
875 struct policy_handle connect_handle;
876 struct dom_sid2 *domain_sid = NULL;
877 struct policy_handle domain_handle;
878 union samr_DispInfo info;
879 struct samr_SamArray *sam = NULL;
880 uint32_t num_entries = 0;
881 int i;
882 const char *domain_name = NULL;
883 bool domain_found = true;
884 uint32_t dom_resume_handle = 0;
885 struct lsa_String lsa_domain_name;
887 uint32_t total_size = 0;
888 uint32_t returned_size = 0;
890 NTSTATUS status;
891 WERROR werr;
893 ZERO_STRUCT(connect_handle);
894 ZERO_STRUCT(domain_handle);
896 switch (r->in.level) {
897 case 1:
898 case 2:
899 case 3:
900 break;
901 default:
902 return WERR_UNKNOWN_LEVEL;
905 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
906 if (!W_ERROR_IS_OK(werr)) {
907 goto done;
910 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
911 if (!W_ERROR_IS_OK(werr)) {
912 goto done;
915 status = rpccli_try_samr_connects(pipe_cli, ctx,
916 SAMR_ACCESS_OPEN_DOMAIN |
917 SAMR_ACCESS_ENUM_DOMAINS,
918 &connect_handle);
919 if (!NT_STATUS_IS_OK(status)) {
920 werr = ntstatus_to_werror(status);
921 goto done;
924 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
925 &connect_handle,
926 &dom_resume_handle,
927 &sam,
928 0xffffffff,
929 &num_entries);
930 if (!NT_STATUS_IS_OK(status)) {
931 werr = ntstatus_to_werror(status);
932 goto done;
935 for (i=0; i<num_entries; i++) {
937 domain_name = sam->entries[i].name.string;
939 if (strequal(domain_name, builtin_domain_name())) {
940 continue;
943 domain_found = true;
944 break;
947 if (!domain_found) {
948 werr = WERR_NO_SUCH_DOMAIN;
949 goto done;
952 init_lsa_String(&lsa_domain_name, domain_name);
954 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
955 &connect_handle,
956 &lsa_domain_name,
957 &domain_sid);
958 if (!NT_STATUS_IS_OK(status)) {
959 werr = ntstatus_to_werror(status);
960 goto done;
963 status = rpccli_samr_OpenDomain(pipe_cli,
964 ctx,
965 &connect_handle,
966 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
967 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
968 domain_sid,
969 &domain_handle);
970 if (!NT_STATUS_IS_OK(status)) {
971 werr = ntstatus_to_werror(status);
972 goto done;
975 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
976 ctx,
977 &domain_handle,
978 r->in.level,
979 r->in.idx,
980 r->in.entries_requested,
981 r->in.prefmaxlen,
982 &total_size,
983 &returned_size,
984 &info);
985 if (!NT_STATUS_IS_OK(status)) {
986 werr = ntstatus_to_werror(status);
987 goto done;
990 werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
991 r->in.level,
992 r->out.entries_read,
993 r->out.buffer);
994 done:
995 if (!cli) {
996 return werr;
999 if (is_valid_policy_hnd(&domain_handle)) {
1000 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
1002 if (is_valid_policy_hnd(&connect_handle)) {
1003 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
1006 return werr;
1010 /****************************************************************
1011 ****************************************************************/
1014 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1015 struct NetQueryDisplayInformation *r)
1017 return WERR_NOT_SUPPORTED;