Use libnetapi_open_ipc_connection in libnetapi.
[Samba.git] / source / lib / netapi / user.c
blobd9505bc06796a7c9e54c5726c6fc8c1aded2b2e7
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 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
189 if (!pipe_cli) {
190 werr = ntstatus_to_werror(status);
191 goto done;
194 status = rpccli_try_samr_connects(pipe_cli, ctx,
195 SAMR_ACCESS_ENUM_DOMAINS |
196 SAMR_ACCESS_OPEN_DOMAIN,
197 &connect_handle);
198 if (!NT_STATUS_IS_OK(status)) {
199 werr = ntstatus_to_werror(status);
200 goto done;
203 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
204 &connect_handle,
205 &resume_handle,
206 &sam,
207 0xffffffff,
208 &num_entries);
209 if (!NT_STATUS_IS_OK(status)) {
210 werr = ntstatus_to_werror(status);
211 goto done;
214 for (i=0; i<num_entries; i++) {
216 domain_name = sam->entries[i].name.string;
218 if (strequal(domain_name, builtin_domain_name())) {
219 continue;
222 domain_found = true;
223 break;
226 if (!domain_found) {
227 werr = WERR_NO_SUCH_DOMAIN;
228 goto done;
231 init_lsa_String(&lsa_domain_name, domain_name);
233 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
234 &connect_handle,
235 &lsa_domain_name,
236 &domain_sid);
237 if (!NT_STATUS_IS_OK(status)) {
238 werr = ntstatus_to_werror(status);
239 goto done;
242 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
243 &connect_handle,
244 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
245 SAMR_DOMAIN_ACCESS_CREATE_USER |
246 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
247 domain_sid,
248 &domain_handle);
249 if (!NT_STATUS_IS_OK(status)) {
250 werr = ntstatus_to_werror(status);
251 goto done;
254 init_lsa_String(&lsa_account_name, info1->usri1_name);
256 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
257 &domain_handle,
258 &lsa_account_name,
259 ACB_NORMAL,
260 SEC_STD_WRITE_DAC |
261 SEC_STD_DELETE |
262 SAMR_USER_ACCESS_SET_PASSWORD |
263 SAMR_USER_ACCESS_SET_ATTRIBUTES |
264 SAMR_USER_ACCESS_GET_ATTRIBUTES,
265 &user_handle,
266 &access_granted,
267 &rid);
268 if (!NT_STATUS_IS_OK(status)) {
269 werr = ntstatus_to_werror(status);
270 goto done;
273 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
274 &user_handle,
276 &user_info);
277 if (!NT_STATUS_IS_OK(status)) {
278 werr = ntstatus_to_werror(status);
279 goto done;
282 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
283 werr = WERR_INVALID_PARAM;
284 goto done;
287 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
288 &user_handle,
289 &pw_info);
290 if (!NT_STATUS_IS_OK(status)) {
291 werr = ntstatus_to_werror(status);
292 goto done;
295 ZERO_STRUCTP(user_info);
297 convert_USER_INFO_1_to_samr_user_info25(info1,
298 &cli->user_session_key,
299 &info25);
301 if (info1->usri1_password) {
302 user_info->info25 = info25;
303 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
304 &user_handle,
306 user_info);
307 } else {
308 user_info->info21 = info25.info;
309 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
310 &user_handle,
312 user_info);
315 if (!NT_STATUS_IS_OK(status)) {
316 werr = ntstatus_to_werror(status);
317 goto failed;
320 werr = WERR_OK;
321 goto done;
323 failed:
324 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
325 &user_handle);
326 if (!NT_STATUS_IS_OK(status)) {
327 werr = ntstatus_to_werror(status);
328 goto done;
331 done:
332 if (!cli) {
333 return werr;
336 if (is_valid_policy_hnd(&user_handle)) {
337 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
339 if (is_valid_policy_hnd(&domain_handle)) {
340 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
342 if (is_valid_policy_hnd(&connect_handle)) {
343 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
346 return werr;
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 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
382 if (!pipe_cli) {
383 werr = ntstatus_to_werror(status);
384 goto done;
387 status = rpccli_try_samr_connects(pipe_cli, ctx,
388 SAMR_ACCESS_ENUM_DOMAINS |
389 SAMR_ACCESS_OPEN_DOMAIN,
390 &connect_handle);
391 if (!NT_STATUS_IS_OK(status)) {
392 werr = ntstatus_to_werror(status);
393 goto done;
396 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
397 &connect_handle,
398 &resume_handle,
399 &sam,
400 0xffffffff,
401 &num_entries);
402 if (!NT_STATUS_IS_OK(status)) {
403 werr = ntstatus_to_werror(status);
404 goto done;
407 for (i=0; i<num_entries; i++) {
409 domain_name = sam->entries[i].name.string;
411 if (strequal(domain_name, builtin_domain_name())) {
412 continue;
415 domain_found = true;
416 break;
419 if (!domain_found) {
420 werr = WERR_NO_SUCH_DOMAIN;
421 goto done;
424 init_lsa_String(&lsa_domain_name, domain_name);
426 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
427 &connect_handle,
428 &lsa_domain_name,
429 &domain_sid);
430 if (!NT_STATUS_IS_OK(status)) {
431 werr = ntstatus_to_werror(status);
432 goto done;
435 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
436 &connect_handle,
437 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
438 domain_sid,
439 &domain_handle);
440 if (!NT_STATUS_IS_OK(status)) {
441 werr = ntstatus_to_werror(status);
442 goto done;
445 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
446 &connect_handle,
447 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
448 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
449 &builtin_handle);
450 if (!NT_STATUS_IS_OK(status)) {
451 werr = ntstatus_to_werror(status);
452 goto done;
455 init_lsa_String(&lsa_account_name, r->in.user_name);
457 status = rpccli_samr_LookupNames(pipe_cli, ctx,
458 &domain_handle,
460 &lsa_account_name,
461 &user_rids,
462 &name_types);
463 if (!NT_STATUS_IS_OK(status)) {
464 werr = ntstatus_to_werror(status);
465 goto done;
468 status = rpccli_samr_OpenUser(pipe_cli, ctx,
469 &domain_handle,
470 STD_RIGHT_DELETE_ACCESS,
471 user_rids.ids[0],
472 &user_handle);
473 if (!NT_STATUS_IS_OK(status)) {
474 werr = ntstatus_to_werror(status);
475 goto done;
478 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
480 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
481 &builtin_handle,
482 &user_sid);
483 if (!NT_STATUS_IS_OK(status)) {
484 werr = ntstatus_to_werror(status);
485 goto done;
488 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
489 &user_handle);
490 if (!NT_STATUS_IS_OK(status)) {
491 werr = ntstatus_to_werror(status);
492 goto done;
495 werr = WERR_OK;
497 done:
498 if (!cli) {
499 return werr;
502 if (is_valid_policy_hnd(&user_handle)) {
503 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
505 if (is_valid_policy_hnd(&builtin_handle)) {
506 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
508 if (is_valid_policy_hnd(&domain_handle)) {
509 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
511 if (is_valid_policy_hnd(&connect_handle)) {
512 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
515 return werr;
518 /****************************************************************
519 ****************************************************************/
521 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
522 struct NetUserDel *r)
524 return WERR_NOT_SUPPORTED;
527 /****************************************************************
528 ****************************************************************/
530 static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx,
531 struct samr_SamArray *sam_array,
532 uint32_t level,
533 uint8_t **buffer)
535 struct USER_INFO_0 *info0 = NULL;
536 int i;
538 switch (level) {
539 case 0:
540 info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0,
541 sam_array->count);
542 W_ERROR_HAVE_NO_MEMORY(info0);
544 for (i=0; i<sam_array->count; i++) {
545 info0[i].usri0_name = talloc_strdup(mem_ctx,
546 sam_array->entries[i].name.string);
547 W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name);
550 *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0,
551 sizeof(struct USER_INFO_0) * sam_array->count);
552 W_ERROR_HAVE_NO_MEMORY(*buffer);
553 break;
554 default:
555 return WERR_NOT_SUPPORTED;
558 return WERR_OK;
561 /****************************************************************
562 ****************************************************************/
564 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
565 struct NetUserEnum *r)
567 struct cli_state *cli = NULL;
568 struct rpc_pipe_client *pipe_cli = NULL;
569 struct policy_handle connect_handle;
570 struct dom_sid2 *domain_sid = NULL;
571 struct policy_handle domain_handle;
572 struct samr_SamArray *sam = NULL;
573 uint32_t num_entries = 0;
574 int i;
575 const char *domain_name = NULL;
576 bool domain_found = true;
577 uint32_t dom_resume_handle = 0;
578 struct lsa_String lsa_domain_name;
580 NTSTATUS status;
581 WERROR werr;
583 ZERO_STRUCT(connect_handle);
584 ZERO_STRUCT(domain_handle);
586 switch (r->in.level) {
587 case 0:
588 break;
589 case 1:
590 case 2:
591 case 3:
592 case 10:
593 case 11:
594 case 20:
595 case 23:
596 default:
597 return WERR_NOT_SUPPORTED;
600 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
601 if (!W_ERROR_IS_OK(werr)) {
602 goto done;
605 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
606 if (!pipe_cli) {
607 werr = ntstatus_to_werror(status);
608 goto done;
611 status = rpccli_try_samr_connects(pipe_cli, ctx,
612 SAMR_ACCESS_OPEN_DOMAIN |
613 SAMR_ACCESS_ENUM_DOMAINS,
614 &connect_handle);
615 if (!NT_STATUS_IS_OK(status)) {
616 werr = ntstatus_to_werror(status);
617 goto done;
620 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
621 &connect_handle,
622 &dom_resume_handle,
623 &sam,
624 0xffffffff,
625 &num_entries);
626 if (!NT_STATUS_IS_OK(status)) {
627 werr = ntstatus_to_werror(status);
628 goto done;
631 for (i=0; i<num_entries; i++) {
633 domain_name = sam->entries[i].name.string;
635 if (strequal(domain_name, builtin_domain_name())) {
636 continue;
639 domain_found = true;
640 break;
643 if (!domain_found) {
644 werr = WERR_NO_SUCH_DOMAIN;
645 goto done;
648 init_lsa_String(&lsa_domain_name, domain_name);
650 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
651 &connect_handle,
652 &lsa_domain_name,
653 &domain_sid);
654 if (!NT_STATUS_IS_OK(status)) {
655 werr = ntstatus_to_werror(status);
656 goto done;
659 status = rpccli_samr_OpenDomain(pipe_cli,
660 ctx,
661 &connect_handle,
662 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
663 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
664 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
665 domain_sid,
666 &domain_handle);
667 if (!NT_STATUS_IS_OK(status)) {
668 werr = ntstatus_to_werror(status);
669 goto done;
672 status = rpccli_samr_EnumDomainUsers(pipe_cli,
673 ctx,
674 &domain_handle,
675 r->in.resume_handle,
676 r->in.filter,
677 &sam,
678 r->in.prefmaxlen,
679 r->out.entries_read);
680 if (!NT_STATUS_IS_OK(status)) {
681 werr = ntstatus_to_werror(status);
682 goto done;
685 werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
686 r->in.level,
687 r->out.buffer);
689 done:
690 if (!cli) {
691 return werr;
694 if (is_valid_policy_hnd(&domain_handle)) {
695 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
697 if (is_valid_policy_hnd(&connect_handle)) {
698 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
701 return werr;
704 /****************************************************************
705 ****************************************************************/
707 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
708 struct NetUserEnum *r)
710 return WERR_NOT_SUPPORTED;