s3-net: Fix Bug #6102. NetQueryDisplayInformation could return wrong information.
[Samba.git] / source / lib / netapi / user.c
blobb31d8384be2baaf325f85c8e27aa50e3bd120039
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 static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1,
31 DATA_BLOB *user_session_key,
32 struct samr_UserInfo25 *info25)
34 uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
35 struct samr_LogonHours zero_logon_hours;
36 struct lsa_BinaryString zero_parameters;
37 uint32_t acct_flags = 0;
38 NTTIME password_age;
40 ZERO_STRUCTP(info25);
41 ZERO_STRUCT(zero_logon_hours);
42 ZERO_STRUCT(zero_parameters);
44 if (info1->usri1_name) {
45 fields_present |= SAMR_FIELD_FULL_NAME;
47 if (info1->usri1_password) {
48 fields_present |= SAMR_FIELD_PASSWORD;
50 if (info1->usri1_flags) {
51 fields_present |= SAMR_FIELD_ACCT_FLAGS;
53 if (info1->usri1_name) {
54 fields_present |= SAMR_FIELD_FULL_NAME;
56 if (info1->usri1_home_dir) {
57 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
59 if (info1->usri1_script_path) {
60 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
62 if (info1->usri1_comment) {
63 fields_present |= SAMR_FIELD_DESCRIPTION;
65 if (info1->usri1_password_age) {
66 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
69 acct_flags |= info1->usri1_flags | ACB_NORMAL;
71 unix_to_nt_time_abs(&password_age, info1->usri1_password_age);
73 /* TODO: info1->usri1_priv */
74 init_samr_user_info21(&info25->info,
80 password_age,
81 NULL,
82 info1->usri1_name,
83 info1->usri1_home_dir,
84 NULL,
85 info1->usri1_script_path,
86 NULL,
87 info1->usri1_comment,
88 NULL,
89 NULL,
90 &zero_parameters,
93 acct_flags,
94 fields_present,
95 zero_logon_hours,
104 if (info1->usri1_password) {
105 uchar pwbuf[532];
106 struct MD5Context ctx;
107 uint8_t confounder[16];
108 DATA_BLOB confounded_session_key = data_blob(NULL, 16);
110 encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE);
112 generate_random_buffer((uint8_t *)confounder, 16);
114 MD5Init(&ctx);
115 MD5Update(&ctx, confounder, 16);
116 MD5Update(&ctx, user_session_key->data,
117 user_session_key->length);
118 MD5Final(confounded_session_key.data, &ctx);
120 SamOEMhashBlob(pwbuf, 516, &confounded_session_key);
121 memcpy(&pwbuf[516], confounder, 16);
123 memcpy(info25->password.data, pwbuf, sizeof(pwbuf));
124 data_blob_free(&confounded_session_key);
128 /****************************************************************
129 ****************************************************************/
131 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
132 struct NetUserAdd *r)
134 struct cli_state *cli = NULL;
135 struct rpc_pipe_client *pipe_cli = NULL;
136 NTSTATUS status;
137 WERROR werr;
138 uint32_t resume_handle = 0;
139 uint32_t num_entries = 0;
140 POLICY_HND connect_handle, domain_handle, user_handle;
141 struct samr_SamArray *sam = NULL;
142 const char *domain_name = NULL;
143 struct lsa_String lsa_domain_name, lsa_account_name;
144 struct dom_sid2 *domain_sid = NULL;
145 struct samr_UserInfo25 info25;
146 union samr_UserInfo *user_info = NULL;
147 struct samr_PwInfo pw_info;
148 uint32_t access_granted = 0;
149 uint32_t rid = 0;
150 bool domain_found = true;
151 int i;
152 struct USER_INFO_1 *info1;
154 ZERO_STRUCT(connect_handle);
155 ZERO_STRUCT(domain_handle);
156 ZERO_STRUCT(user_handle);
158 if (!r->in.buffer) {
159 return WERR_INVALID_PARAM;
162 switch (r->in.level) {
163 case 1:
164 info1 = (struct USER_INFO_1 *)r->in.buffer;
165 break;
166 case 2:
167 case 3:
168 case 4:
169 default:
170 werr = WERR_NOT_SUPPORTED;
171 goto done;
174 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
175 if (!W_ERROR_IS_OK(werr)) {
176 goto done;
179 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
180 if (!W_ERROR_IS_OK(werr)) {
181 goto done;
184 status = rpccli_try_samr_connects(pipe_cli, ctx,
185 SAMR_ACCESS_ENUM_DOMAINS |
186 SAMR_ACCESS_OPEN_DOMAIN,
187 &connect_handle);
188 if (!NT_STATUS_IS_OK(status)) {
189 werr = ntstatus_to_werror(status);
190 goto done;
193 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
194 &connect_handle,
195 &resume_handle,
196 &sam,
197 0xffffffff,
198 &num_entries);
199 if (!NT_STATUS_IS_OK(status)) {
200 werr = ntstatus_to_werror(status);
201 goto done;
204 for (i=0; i<num_entries; i++) {
206 domain_name = sam->entries[i].name.string;
208 if (strequal(domain_name, builtin_domain_name())) {
209 continue;
212 domain_found = true;
213 break;
216 if (!domain_found) {
217 werr = WERR_NO_SUCH_DOMAIN;
218 goto done;
221 init_lsa_String(&lsa_domain_name, domain_name);
223 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
224 &connect_handle,
225 &lsa_domain_name,
226 &domain_sid);
227 if (!NT_STATUS_IS_OK(status)) {
228 werr = ntstatus_to_werror(status);
229 goto done;
232 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
233 &connect_handle,
234 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
235 SAMR_DOMAIN_ACCESS_CREATE_USER |
236 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
237 domain_sid,
238 &domain_handle);
239 if (!NT_STATUS_IS_OK(status)) {
240 werr = ntstatus_to_werror(status);
241 goto done;
244 init_lsa_String(&lsa_account_name, info1->usri1_name);
246 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
247 &domain_handle,
248 &lsa_account_name,
249 ACB_NORMAL,
250 SEC_STD_WRITE_DAC |
251 SEC_STD_DELETE |
252 SAMR_USER_ACCESS_SET_PASSWORD |
253 SAMR_USER_ACCESS_SET_ATTRIBUTES |
254 SAMR_USER_ACCESS_GET_ATTRIBUTES,
255 &user_handle,
256 &access_granted,
257 &rid);
258 if (!NT_STATUS_IS_OK(status)) {
259 werr = ntstatus_to_werror(status);
260 goto done;
263 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
264 &user_handle,
266 &user_info);
267 if (!NT_STATUS_IS_OK(status)) {
268 werr = ntstatus_to_werror(status);
269 goto done;
272 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
273 werr = WERR_INVALID_PARAM;
274 goto done;
277 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
278 &user_handle,
279 &pw_info);
280 if (!NT_STATUS_IS_OK(status)) {
281 werr = ntstatus_to_werror(status);
282 goto done;
285 ZERO_STRUCTP(user_info);
287 convert_USER_INFO_1_to_samr_user_info25(info1,
288 &cli->user_session_key,
289 &info25);
291 if (info1->usri1_password) {
292 user_info->info25 = info25;
293 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
294 &user_handle,
296 user_info);
297 } else {
298 user_info->info21 = info25.info;
299 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
300 &user_handle,
302 user_info);
305 if (!NT_STATUS_IS_OK(status)) {
306 werr = ntstatus_to_werror(status);
307 goto failed;
310 werr = WERR_OK;
311 goto done;
313 failed:
314 rpccli_samr_DeleteUser(pipe_cli, ctx,
315 &user_handle);
317 done:
318 if (!cli) {
319 return werr;
322 if (is_valid_policy_hnd(&user_handle)) {
323 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
325 if (is_valid_policy_hnd(&domain_handle)) {
326 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
328 if (is_valid_policy_hnd(&connect_handle)) {
329 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
332 return werr;
335 /****************************************************************
336 ****************************************************************/
338 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
339 struct NetUserAdd *r)
341 /* for now just talk to local RPC server */
342 if (!r->in.server_name) {
343 r->in.server_name = "localhost";
346 return NetUserAdd_r(ctx, r);
349 /****************************************************************
350 ****************************************************************/
352 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
353 struct NetUserDel *r)
355 struct cli_state *cli = NULL;
356 struct rpc_pipe_client *pipe_cli = NULL;
357 NTSTATUS status;
358 WERROR werr;
359 uint32_t resume_handle = 0;
360 uint32_t num_entries = 0;
361 POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
362 struct samr_SamArray *sam = NULL;
363 const char *domain_name = NULL;
364 struct lsa_String lsa_domain_name, lsa_account_name;
365 struct samr_Ids user_rids, name_types;
366 struct dom_sid2 *domain_sid = NULL;
367 struct dom_sid2 user_sid;
368 bool domain_found = true;
369 int i;
371 ZERO_STRUCT(connect_handle);
372 ZERO_STRUCT(builtin_handle);
373 ZERO_STRUCT(domain_handle);
374 ZERO_STRUCT(user_handle);
376 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
377 if (!W_ERROR_IS_OK(werr)) {
378 goto done;
381 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
382 if (!W_ERROR_IS_OK(werr)) {
383 goto done;
386 status = rpccli_try_samr_connects(pipe_cli, ctx,
387 SAMR_ACCESS_ENUM_DOMAINS |
388 SAMR_ACCESS_OPEN_DOMAIN,
389 &connect_handle);
390 if (!NT_STATUS_IS_OK(status)) {
391 werr = ntstatus_to_werror(status);
392 goto done;
395 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
396 &connect_handle,
397 &resume_handle,
398 &sam,
399 0xffffffff,
400 &num_entries);
401 if (!NT_STATUS_IS_OK(status)) {
402 werr = ntstatus_to_werror(status);
403 goto done;
406 for (i=0; i<num_entries; i++) {
408 domain_name = sam->entries[i].name.string;
410 if (strequal(domain_name, builtin_domain_name())) {
411 continue;
414 domain_found = true;
415 break;
418 if (!domain_found) {
419 werr = WERR_NO_SUCH_DOMAIN;
420 goto done;
423 init_lsa_String(&lsa_domain_name, domain_name);
425 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
426 &connect_handle,
427 &lsa_domain_name,
428 &domain_sid);
429 if (!NT_STATUS_IS_OK(status)) {
430 werr = ntstatus_to_werror(status);
431 goto done;
434 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
435 &connect_handle,
436 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
437 domain_sid,
438 &domain_handle);
439 if (!NT_STATUS_IS_OK(status)) {
440 werr = ntstatus_to_werror(status);
441 goto done;
444 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
445 &connect_handle,
446 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
447 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
448 &builtin_handle);
449 if (!NT_STATUS_IS_OK(status)) {
450 werr = ntstatus_to_werror(status);
451 goto done;
454 init_lsa_String(&lsa_account_name, r->in.user_name);
456 status = rpccli_samr_LookupNames(pipe_cli, ctx,
457 &domain_handle,
459 &lsa_account_name,
460 &user_rids,
461 &name_types);
462 if (!NT_STATUS_IS_OK(status)) {
463 werr = ntstatus_to_werror(status);
464 goto done;
467 status = rpccli_samr_OpenUser(pipe_cli, ctx,
468 &domain_handle,
469 STD_RIGHT_DELETE_ACCESS,
470 user_rids.ids[0],
471 &user_handle);
472 if (!NT_STATUS_IS_OK(status)) {
473 werr = ntstatus_to_werror(status);
474 goto done;
477 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
479 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
480 &builtin_handle,
481 &user_sid);
482 if (!NT_STATUS_IS_OK(status)) {
483 werr = ntstatus_to_werror(status);
484 goto done;
487 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
488 &user_handle);
489 if (!NT_STATUS_IS_OK(status)) {
490 werr = ntstatus_to_werror(status);
491 goto done;
494 werr = WERR_OK;
496 done:
497 if (!cli) {
498 return werr;
501 if (is_valid_policy_hnd(&user_handle)) {
502 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
504 if (is_valid_policy_hnd(&builtin_handle)) {
505 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
507 if (is_valid_policy_hnd(&domain_handle)) {
508 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
510 if (is_valid_policy_hnd(&connect_handle)) {
511 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
514 return werr;
517 /****************************************************************
518 ****************************************************************/
520 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
521 struct NetUserDel *r)
523 /* for now just talk to local RPC server */
524 if (!r->in.server_name) {
525 r->in.server_name = "localhost";
528 return NetUserDel_r(ctx, r);
531 /****************************************************************
532 ****************************************************************/
534 static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx,
535 struct samr_SamArray *sam_array,
536 uint32_t level,
537 uint8_t **buffer)
539 struct USER_INFO_0 *info0 = NULL;
540 int i;
542 switch (level) {
543 case 0:
544 info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0,
545 sam_array->count);
546 W_ERROR_HAVE_NO_MEMORY(info0);
548 for (i=0; i<sam_array->count; i++) {
549 info0[i].usri0_name = talloc_strdup(mem_ctx,
550 sam_array->entries[i].name.string);
551 W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name);
554 *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0,
555 sizeof(struct USER_INFO_0) * sam_array->count);
556 W_ERROR_HAVE_NO_MEMORY(*buffer);
557 break;
558 default:
559 return WERR_NOT_SUPPORTED;
562 return WERR_OK;
565 /****************************************************************
566 ****************************************************************/
568 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
569 struct NetUserEnum *r)
571 struct cli_state *cli = NULL;
572 struct rpc_pipe_client *pipe_cli = NULL;
573 struct policy_handle connect_handle;
574 struct dom_sid2 *domain_sid = NULL;
575 struct policy_handle domain_handle;
576 struct samr_SamArray *sam = NULL;
577 uint32_t num_entries = 0;
578 int i;
579 const char *domain_name = NULL;
580 bool domain_found = true;
581 uint32_t dom_resume_handle = 0;
582 struct lsa_String lsa_domain_name;
584 NTSTATUS status;
585 WERROR werr;
587 ZERO_STRUCT(connect_handle);
588 ZERO_STRUCT(domain_handle);
590 switch (r->in.level) {
591 case 0:
592 break;
593 case 1:
594 case 2:
595 case 3:
596 case 10:
597 case 11:
598 case 20:
599 case 23:
600 default:
601 return WERR_NOT_SUPPORTED;
604 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
605 if (!W_ERROR_IS_OK(werr)) {
606 goto done;
609 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
610 if (!W_ERROR_IS_OK(werr)) {
611 goto done;
614 status = rpccli_try_samr_connects(pipe_cli, ctx,
615 SAMR_ACCESS_OPEN_DOMAIN |
616 SAMR_ACCESS_ENUM_DOMAINS,
617 &connect_handle);
618 if (!NT_STATUS_IS_OK(status)) {
619 werr = ntstatus_to_werror(status);
620 goto done;
623 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
624 &connect_handle,
625 &dom_resume_handle,
626 &sam,
627 0xffffffff,
628 &num_entries);
629 if (!NT_STATUS_IS_OK(status)) {
630 werr = ntstatus_to_werror(status);
631 goto done;
634 for (i=0; i<num_entries; i++) {
636 domain_name = sam->entries[i].name.string;
638 if (strequal(domain_name, builtin_domain_name())) {
639 continue;
642 domain_found = true;
643 break;
646 if (!domain_found) {
647 werr = WERR_NO_SUCH_DOMAIN;
648 goto done;
651 init_lsa_String(&lsa_domain_name, domain_name);
653 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
654 &connect_handle,
655 &lsa_domain_name,
656 &domain_sid);
657 if (!NT_STATUS_IS_OK(status)) {
658 werr = ntstatus_to_werror(status);
659 goto done;
662 status = rpccli_samr_OpenDomain(pipe_cli,
663 ctx,
664 &connect_handle,
665 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
666 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
667 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
668 domain_sid,
669 &domain_handle);
670 if (!NT_STATUS_IS_OK(status)) {
671 werr = ntstatus_to_werror(status);
672 goto done;
675 status = rpccli_samr_EnumDomainUsers(pipe_cli,
676 ctx,
677 &domain_handle,
678 r->in.resume_handle,
679 r->in.filter,
680 &sam,
681 r->in.prefmaxlen,
682 r->out.entries_read);
683 if (!NT_STATUS_IS_OK(status)) {
684 werr = ntstatus_to_werror(status);
685 goto done;
688 werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
689 r->in.level,
690 r->out.buffer);
692 done:
693 if (!cli) {
694 return werr;
697 if (is_valid_policy_hnd(&domain_handle)) {
698 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
700 if (is_valid_policy_hnd(&connect_handle)) {
701 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
704 return werr;
707 /****************************************************************
708 ****************************************************************/
710 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
711 struct NetUserEnum *r)
713 return WERR_NOT_SUPPORTED;
716 /****************************************************************
717 ****************************************************************/
719 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
720 struct samr_DispInfoGeneral *info,
721 uint32_t *entries_read,
722 void **buffer)
724 struct NET_DISPLAY_USER *user = NULL;
725 int i;
727 user = TALLOC_ZERO_ARRAY(mem_ctx,
728 struct NET_DISPLAY_USER,
729 info->count);
730 W_ERROR_HAVE_NO_MEMORY(user);
732 for (i = 0; i < info->count; i++) {
733 user[i].usri1_name = talloc_strdup(mem_ctx,
734 info->entries[i].account_name.string);
735 user[i].usri1_comment = talloc_strdup(mem_ctx,
736 info->entries[i].description.string);
737 user[i].usri1_flags =
738 info->entries[i].acct_flags;
739 user[i].usri1_full_name = talloc_strdup(mem_ctx,
740 info->entries[i].full_name.string);
741 user[i].usri1_user_id =
742 info->entries[i].rid;
743 user[i].usri1_next_index =
744 info->entries[i].idx;
746 if (!user[i].usri1_name) {
747 return WERR_NOMEM;
751 *buffer = talloc_memdup(mem_ctx, user,
752 sizeof(struct NET_DISPLAY_USER) * info->count);
753 W_ERROR_HAVE_NO_MEMORY(*buffer);
755 *entries_read = info->count;
757 return WERR_OK;
760 /****************************************************************
761 ****************************************************************/
763 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
764 struct samr_DispInfoFull *info,
765 uint32_t *entries_read,
766 void **buffer)
768 struct NET_DISPLAY_MACHINE *machine = NULL;
769 int i;
771 machine = TALLOC_ZERO_ARRAY(mem_ctx,
772 struct NET_DISPLAY_MACHINE,
773 info->count);
774 W_ERROR_HAVE_NO_MEMORY(machine);
776 for (i = 0; i < info->count; i++) {
777 machine[i].usri2_name = talloc_strdup(mem_ctx,
778 info->entries[i].account_name.string);
779 machine[i].usri2_comment = talloc_strdup(mem_ctx,
780 info->entries[i].description.string);
781 machine[i].usri2_flags =
782 info->entries[i].acct_flags;
783 machine[i].usri2_user_id =
784 info->entries[i].rid;
785 machine[i].usri2_next_index =
786 info->entries[i].idx;
788 if (!machine[i].usri2_name) {
789 return WERR_NOMEM;
793 *buffer = talloc_memdup(mem_ctx, machine,
794 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
795 W_ERROR_HAVE_NO_MEMORY(*buffer);
797 *entries_read = info->count;
799 return WERR_OK;
802 /****************************************************************
803 ****************************************************************/
805 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
806 struct samr_DispInfoFullGroups *info,
807 uint32_t *entries_read,
808 void **buffer)
810 struct NET_DISPLAY_GROUP *group = NULL;
811 int i;
813 group = TALLOC_ZERO_ARRAY(mem_ctx,
814 struct NET_DISPLAY_GROUP,
815 info->count);
816 W_ERROR_HAVE_NO_MEMORY(group);
818 for (i = 0; i < info->count; i++) {
819 group[i].grpi3_name = talloc_strdup(mem_ctx,
820 info->entries[i].account_name.string);
821 group[i].grpi3_comment = talloc_strdup(mem_ctx,
822 info->entries[i].description.string);
823 group[i].grpi3_group_id =
824 info->entries[i].rid;
825 group[i].grpi3_attributes =
826 info->entries[i].acct_flags;
827 group[i].grpi3_next_index =
828 info->entries[i].idx;
830 if (!group[i].grpi3_name) {
831 return WERR_NOMEM;
835 *buffer = talloc_memdup(mem_ctx, group,
836 sizeof(struct NET_DISPLAY_GROUP) * info->count);
837 W_ERROR_HAVE_NO_MEMORY(*buffer);
839 *entries_read = info->count;
841 return WERR_OK;
845 /****************************************************************
846 ****************************************************************/
848 WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
849 union samr_DispInfo *info,
850 uint32_t level,
851 uint32_t *entries_read,
852 void **buffer)
854 switch (level) {
855 case 1:
856 return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
857 &info->info1,
858 entries_read,
859 buffer);
860 case 2:
861 return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
862 &info->info2,
863 entries_read,
864 buffer);
865 case 3:
866 return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
867 &info->info3,
868 entries_read,
869 buffer);
870 default:
871 return WERR_UNKNOWN_LEVEL;
874 return WERR_OK;
877 /****************************************************************
878 ****************************************************************/
880 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
881 struct NetQueryDisplayInformation *r)
883 struct cli_state *cli = NULL;
884 struct rpc_pipe_client *pipe_cli = NULL;
885 struct policy_handle connect_handle;
886 struct dom_sid2 *domain_sid = NULL;
887 struct policy_handle domain_handle;
888 union samr_DispInfo info;
889 struct samr_SamArray *sam = NULL;
890 uint32_t num_entries = 0;
891 int i;
892 const char *domain_name = NULL;
893 bool domain_found = true;
894 uint32_t dom_resume_handle = 0;
895 struct lsa_String lsa_domain_name;
897 uint32_t total_size = 0;
898 uint32_t returned_size = 0;
900 NTSTATUS status;
901 WERROR werr;
902 WERROR werr_tmp;
904 *r->out.entries_read = 0;
906 ZERO_STRUCT(connect_handle);
907 ZERO_STRUCT(domain_handle);
909 switch (r->in.level) {
910 case 1:
911 case 2:
912 case 3:
913 break;
914 default:
915 return WERR_UNKNOWN_LEVEL;
918 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
919 if (!W_ERROR_IS_OK(werr)) {
920 goto done;
923 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
924 if (!W_ERROR_IS_OK(werr)) {
925 goto done;
928 status = rpccli_try_samr_connects(pipe_cli, ctx,
929 SAMR_ACCESS_OPEN_DOMAIN |
930 SAMR_ACCESS_ENUM_DOMAINS,
931 &connect_handle);
932 if (!NT_STATUS_IS_OK(status)) {
933 werr = ntstatus_to_werror(status);
934 goto done;
937 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
938 &connect_handle,
939 &dom_resume_handle,
940 &sam,
941 0xffffffff,
942 &num_entries);
943 if (!NT_STATUS_IS_OK(status)) {
944 werr = ntstatus_to_werror(status);
945 goto done;
948 for (i=0; i<num_entries; i++) {
950 domain_name = sam->entries[i].name.string;
952 if (strequal(domain_name, builtin_domain_name())) {
953 continue;
956 domain_found = true;
957 break;
960 if (!domain_found) {
961 werr = WERR_NO_SUCH_DOMAIN;
962 goto done;
965 init_lsa_String(&lsa_domain_name, domain_name);
967 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
968 &connect_handle,
969 &lsa_domain_name,
970 &domain_sid);
971 if (!NT_STATUS_IS_OK(status)) {
972 werr = ntstatus_to_werror(status);
973 goto done;
976 status = rpccli_samr_OpenDomain(pipe_cli,
977 ctx,
978 &connect_handle,
979 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
980 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
981 domain_sid,
982 &domain_handle);
983 if (!NT_STATUS_IS_OK(status)) {
984 werr = ntstatus_to_werror(status);
985 goto done;
988 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
989 ctx,
990 &domain_handle,
991 r->in.level,
992 r->in.idx,
993 r->in.entries_requested,
994 r->in.prefmaxlen,
995 &total_size,
996 &returned_size,
997 &info);
998 werr = ntstatus_to_werror(status);
999 if (NT_STATUS_IS_ERR(status)) {
1000 goto done;
1003 werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1004 r->in.level,
1005 r->out.entries_read,
1006 r->out.buffer);
1007 if (!W_ERROR_IS_OK(werr_tmp)) {
1008 werr = werr_tmp;
1010 done:
1011 if (!cli) {
1012 return werr;
1015 if (is_valid_policy_hnd(&domain_handle)) {
1016 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
1018 if (is_valid_policy_hnd(&connect_handle)) {
1019 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
1022 return werr;
1026 /****************************************************************
1027 ****************************************************************/
1030 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1031 struct NetQueryDisplayInformation *r)
1033 return WERR_NOT_SUPPORTED;