source: branches/samba-3.2.x/source/lib/netapi/user.c

Last change on this file was 233, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.9

File size: 25.0 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 * NetApi User 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
27/****************************************************************
28****************************************************************/
29
30static 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)
33{
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;
39
40 ZERO_STRUCTP(info25);
41 ZERO_STRUCT(zero_logon_hours);
42 ZERO_STRUCT(zero_parameters);
43
44 if (info1->usri1_name) {
45 fields_present |= SAMR_FIELD_FULL_NAME;
46 }
47 if (info1->usri1_password) {
48 fields_present |= SAMR_FIELD_PASSWORD;
49 }
50 if (info1->usri1_flags) {
51 fields_present |= SAMR_FIELD_ACCT_FLAGS;
52 }
53 if (info1->usri1_name) {
54 fields_present |= SAMR_FIELD_FULL_NAME;
55 }
56 if (info1->usri1_home_dir) {
57 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
58 }
59 if (info1->usri1_script_path) {
60 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
61 }
62 if (info1->usri1_comment) {
63 fields_present |= SAMR_FIELD_DESCRIPTION;
64 }
65 if (info1->usri1_password_age) {
66 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
67 }
68
69 acct_flags |= info1->usri1_flags | ACB_NORMAL;
70
71 unix_to_nt_time_abs(&password_age, info1->usri1_password_age);
72
73 /* TODO: info1->usri1_priv */
74 init_samr_user_info21(&info25->info,
75 0,
76 0,
77 0,
78 0,
79 0,
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,
91 0,
92 0,
93 acct_flags,
94 fields_present,
95 zero_logon_hours,
96 0,
97 0,
98 0,
99 0,
100 0,
101 0,
102 0);
103
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);
109
110 encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE);
111
112 generate_random_buffer((uint8_t *)confounder, 16);
113
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);
119
120 SamOEMhashBlob(pwbuf, 516, &confounded_session_key);
121 memcpy(&pwbuf[516], confounder, 16);
122
123 memcpy(info25->password.data, pwbuf, sizeof(pwbuf));
124 data_blob_free(&confounded_session_key);
125 }
126}
127
128/****************************************************************
129****************************************************************/
130
131WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
132 struct NetUserAdd *r)
133{
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;
153
154 ZERO_STRUCT(connect_handle);
155 ZERO_STRUCT(domain_handle);
156 ZERO_STRUCT(user_handle);
157
158 if (!r->in.buffer) {
159 return WERR_INVALID_PARAM;
160 }
161
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;
172 }
173
174 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
175 if (!W_ERROR_IS_OK(werr)) {
176 goto done;
177 }
178
179 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
180 if (!W_ERROR_IS_OK(werr)) {
181 goto done;
182 }
183
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;
191 }
192
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;
202 }
203
204 for (i=0; i<num_entries; i++) {
205
206 domain_name = sam->entries[i].name.string;
207
208 if (strequal(domain_name, builtin_domain_name())) {
209 continue;
210 }
211
212 domain_found = true;
213 break;
214 }
215
216 if (!domain_found) {
217 werr = WERR_NO_SUCH_DOMAIN;
218 goto done;
219 }
220
221 init_lsa_String(&lsa_domain_name, domain_name);
222
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;
230 }
231
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;
242 }
243
244 init_lsa_String(&lsa_account_name, info1->usri1_name);
245
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;
261 }
262
263 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
264 &user_handle,
265 16,
266 &user_info);
267 if (!NT_STATUS_IS_OK(status)) {
268 werr = ntstatus_to_werror(status);
269 goto done;
270 }
271
272 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
273 werr = WERR_INVALID_PARAM;
274 goto done;
275 }
276
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;
283 }
284
285 ZERO_STRUCTP(user_info);
286
287 convert_USER_INFO_1_to_samr_user_info25(info1,
288 &cli->user_session_key,
289 &info25);
290
291 if (info1->usri1_password) {
292 user_info->info25 = info25;
293 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
294 &user_handle,
295 25,
296 user_info);
297 } else {
298 user_info->info21 = info25.info;
299 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
300 &user_handle,
301 21,
302 user_info);
303
304 }
305 if (!NT_STATUS_IS_OK(status)) {
306 werr = ntstatus_to_werror(status);
307 goto failed;
308 }
309
310 werr = WERR_OK;
311 goto done;
312
313 failed:
314 rpccli_samr_DeleteUser(pipe_cli, ctx,
315 &user_handle);
316
317 done:
318 if (!cli) {
319 return werr;
320 }
321
322 if (is_valid_policy_hnd(&user_handle)) {
323 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
324 }
325 if (is_valid_policy_hnd(&domain_handle)) {
326 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
327 }
328 if (is_valid_policy_hnd(&connect_handle)) {
329 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
330 }
331
332 return werr;
333}
334
335/****************************************************************
336****************************************************************/
337
338WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
339 struct NetUserAdd *r)
340{
341 /* for now just talk to local RPC server */
342 if (!r->in.server_name) {
343 r->in.server_name = "localhost";
344 }
345
346 return NetUserAdd_r(ctx, r);
347}
348
349/****************************************************************
350****************************************************************/
351
352WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
353 struct NetUserDel *r)
354{
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;
370
371 ZERO_STRUCT(connect_handle);
372 ZERO_STRUCT(builtin_handle);
373 ZERO_STRUCT(domain_handle);
374 ZERO_STRUCT(user_handle);
375
376 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
377 if (!W_ERROR_IS_OK(werr)) {
378 goto done;
379 }
380
381 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
382 if (!W_ERROR_IS_OK(werr)) {
383 goto done;
384 }
385
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;
393 }
394
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;
404 }
405
406 for (i=0; i<num_entries; i++) {
407
408 domain_name = sam->entries[i].name.string;
409
410 if (strequal(domain_name, builtin_domain_name())) {
411 continue;
412 }
413
414 domain_found = true;
415 break;
416 }
417
418 if (!domain_found) {
419 werr = WERR_NO_SUCH_DOMAIN;
420 goto done;
421 }
422
423 init_lsa_String(&lsa_domain_name, domain_name);
424
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;
432 }
433
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;
442 }
443
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;
452 }
453
454 init_lsa_String(&lsa_account_name, r->in.user_name);
455
456 status = rpccli_samr_LookupNames(pipe_cli, ctx,
457 &domain_handle,
458 1,
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;
465 }
466
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;
475 }
476
477 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
478
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;
485 }
486
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;
492 }
493
494 werr = WERR_OK;
495
496 done:
497 if (!cli) {
498 return werr;
499 }
500
501 if (is_valid_policy_hnd(&user_handle)) {
502 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
503 }
504 if (is_valid_policy_hnd(&builtin_handle)) {
505 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
506 }
507 if (is_valid_policy_hnd(&domain_handle)) {
508 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
509 }
510 if (is_valid_policy_hnd(&connect_handle)) {
511 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
512 }
513
514 return werr;
515}
516
517/****************************************************************
518****************************************************************/
519
520WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
521 struct NetUserDel *r)
522{
523 /* for now just talk to local RPC server */
524 if (!r->in.server_name) {
525 r->in.server_name = "localhost";
526 }
527
528 return NetUserDel_r(ctx, r);
529}
530
531/****************************************************************
532****************************************************************/
533
534static 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)
538{
539 struct USER_INFO_0 *info0 = NULL;
540 int i;
541
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);
547
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);
552 }
553
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;
560 }
561
562 return WERR_OK;
563}
564
565/****************************************************************
566****************************************************************/
567
568WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
569 struct NetUserEnum *r)
570{
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;
583
584 NTSTATUS status;
585 WERROR werr;
586
587 ZERO_STRUCT(connect_handle);
588 ZERO_STRUCT(domain_handle);
589
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;
602 }
603
604 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
605 if (!W_ERROR_IS_OK(werr)) {
606 goto done;
607 }
608
609 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
610 if (!W_ERROR_IS_OK(werr)) {
611 goto done;
612 }
613
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;
621 }
622
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;
632 }
633
634 for (i=0; i<num_entries; i++) {
635
636 domain_name = sam->entries[i].name.string;
637
638 if (strequal(domain_name, builtin_domain_name())) {
639 continue;
640 }
641
642 domain_found = true;
643 break;
644 }
645
646 if (!domain_found) {
647 werr = WERR_NO_SUCH_DOMAIN;
648 goto done;
649 }
650
651 init_lsa_String(&lsa_domain_name, domain_name);
652
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;
660 }
661
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;
673 }
674
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;
686 }
687
688 werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
689 r->in.level,
690 r->out.buffer);
691
692 done:
693 if (!cli) {
694 return werr;
695 }
696
697 if (is_valid_policy_hnd(&domain_handle)) {
698 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
699 }
700 if (is_valid_policy_hnd(&connect_handle)) {
701 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
702 }
703
704 return werr;
705}
706
707/****************************************************************
708****************************************************************/
709
710WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
711 struct NetUserEnum *r)
712{
713 return WERR_NOT_SUPPORTED;
714}
715
716/****************************************************************
717****************************************************************/
718
719static 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)
723{
724 struct NET_DISPLAY_USER *user = NULL;
725 int i;
726
727 user = TALLOC_ZERO_ARRAY(mem_ctx,
728 struct NET_DISPLAY_USER,
729 info->count);
730 W_ERROR_HAVE_NO_MEMORY(user);
731
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;
745
746 if (!user[i].usri1_name) {
747 return WERR_NOMEM;
748 }
749 }
750
751 *buffer = talloc_memdup(mem_ctx, user,
752 sizeof(struct NET_DISPLAY_USER) * info->count);
753 W_ERROR_HAVE_NO_MEMORY(*buffer);
754
755 *entries_read = info->count;
756
757 return WERR_OK;
758}
759
760/****************************************************************
761****************************************************************/
762
763static 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)
767{
768 struct NET_DISPLAY_MACHINE *machine = NULL;
769 int i;
770
771 machine = TALLOC_ZERO_ARRAY(mem_ctx,
772 struct NET_DISPLAY_MACHINE,
773 info->count);
774 W_ERROR_HAVE_NO_MEMORY(machine);
775
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;
787
788 if (!machine[i].usri2_name) {
789 return WERR_NOMEM;
790 }
791 }
792
793 *buffer = talloc_memdup(mem_ctx, machine,
794 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
795 W_ERROR_HAVE_NO_MEMORY(*buffer);
796
797 *entries_read = info->count;
798
799 return WERR_OK;
800}
801
802/****************************************************************
803****************************************************************/
804
805static 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)
809{
810 struct NET_DISPLAY_GROUP *group = NULL;
811 int i;
812
813 group = TALLOC_ZERO_ARRAY(mem_ctx,
814 struct NET_DISPLAY_GROUP,
815 info->count);
816 W_ERROR_HAVE_NO_MEMORY(group);
817
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;
829
830 if (!group[i].grpi3_name) {
831 return WERR_NOMEM;
832 }
833 }
834
835 *buffer = talloc_memdup(mem_ctx, group,
836 sizeof(struct NET_DISPLAY_GROUP) * info->count);
837 W_ERROR_HAVE_NO_MEMORY(*buffer);
838
839 *entries_read = info->count;
840
841 return WERR_OK;
842
843}
844
845/****************************************************************
846****************************************************************/
847
848WERROR 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)
853{
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;
872 }
873
874 return WERR_OK;
875}
876
877/****************************************************************
878****************************************************************/
879
880WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
881 struct NetQueryDisplayInformation *r)
882{
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;
896
897 uint32_t total_size = 0;
898 uint32_t returned_size = 0;
899
900 NTSTATUS status;
901 WERROR werr;
902 WERROR werr_tmp;
903
904 *r->out.entries_read = 0;
905
906 ZERO_STRUCT(connect_handle);
907 ZERO_STRUCT(domain_handle);
908
909 switch (r->in.level) {
910 case 1:
911 case 2:
912 case 3:
913 break;
914 default:
915 return WERR_UNKNOWN_LEVEL;
916 }
917
918 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
919 if (!W_ERROR_IS_OK(werr)) {
920 goto done;
921 }
922
923 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
924 if (!W_ERROR_IS_OK(werr)) {
925 goto done;
926 }
927
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;
935 }
936
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;
946 }
947
948 for (i=0; i<num_entries; i++) {
949
950 domain_name = sam->entries[i].name.string;
951
952 if (strequal(domain_name, builtin_domain_name())) {
953 continue;
954 }
955
956 domain_found = true;
957 break;
958 }
959
960 if (!domain_found) {
961 werr = WERR_NO_SUCH_DOMAIN;
962 goto done;
963 }
964
965 init_lsa_String(&lsa_domain_name, domain_name);
966
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;
974 }
975
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;
986 }
987
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;
1001 }
1002
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;
1009 }
1010 done:
1011 if (!cli) {
1012 return werr;
1013 }
1014
1015 if (is_valid_policy_hnd(&domain_handle)) {
1016 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
1017 }
1018 if (is_valid_policy_hnd(&connect_handle)) {
1019 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
1020 }
1021
1022 return werr;
1023
1024}
1025
1026/****************************************************************
1027****************************************************************/
1028
1029
1030WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1031 struct NetQueryDisplayInformation *r)
1032{
1033 return WERR_NOT_SUPPORTED;
1034}
Note: See TracBrowser for help on using the repository browser.