2 * Unix SMB/CIFS implementation.
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/>.
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
,
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;
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
,
92 info1
->usri1_home_dir
,
94 info1
->usri1_script_path
,
113 if (info1
->usri1_password
) {
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);
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
;
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;
159 bool domain_found
= true;
161 struct USER_INFO_1
*info1
;
163 ZERO_STRUCT(connect_handle
);
164 ZERO_STRUCT(domain_handle
);
165 ZERO_STRUCT(user_handle
);
168 return WERR_INVALID_PARAM
;
171 switch (r
->in
.level
) {
173 info1
= (struct USER_INFO_1
*)r
->in
.buffer
;
179 werr
= WERR_NOT_SUPPORTED
;
183 werr
= libnetapi_open_ipc_connection(ctx
, r
->in
.server_name
, &cli
);
184 if (!W_ERROR_IS_OK(werr
)) {
188 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
190 werr
= ntstatus_to_werror(status
);
194 status
= rpccli_try_samr_connects(pipe_cli
, ctx
,
195 SAMR_ACCESS_ENUM_DOMAINS
|
196 SAMR_ACCESS_OPEN_DOMAIN
,
198 if (!NT_STATUS_IS_OK(status
)) {
199 werr
= ntstatus_to_werror(status
);
203 status
= rpccli_samr_EnumDomains(pipe_cli
, ctx
,
209 if (!NT_STATUS_IS_OK(status
)) {
210 werr
= ntstatus_to_werror(status
);
214 for (i
=0; i
<num_entries
; i
++) {
216 domain_name
= sam
->entries
[i
].name
.string
;
218 if (strequal(domain_name
, builtin_domain_name())) {
227 werr
= WERR_NO_SUCH_DOMAIN
;
231 init_lsa_String(&lsa_domain_name
, domain_name
);
233 status
= rpccli_samr_LookupDomain(pipe_cli
, ctx
,
237 if (!NT_STATUS_IS_OK(status
)) {
238 werr
= ntstatus_to_werror(status
);
242 status
= rpccli_samr_OpenDomain(pipe_cli
, ctx
,
244 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
|
245 SAMR_DOMAIN_ACCESS_CREATE_USER
|
246 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
249 if (!NT_STATUS_IS_OK(status
)) {
250 werr
= ntstatus_to_werror(status
);
254 init_lsa_String(&lsa_account_name
, info1
->usri1_name
);
256 status
= rpccli_samr_CreateUser2(pipe_cli
, ctx
,
262 SAMR_USER_ACCESS_SET_PASSWORD
|
263 SAMR_USER_ACCESS_SET_ATTRIBUTES
|
264 SAMR_USER_ACCESS_GET_ATTRIBUTES
,
268 if (!NT_STATUS_IS_OK(status
)) {
269 werr
= ntstatus_to_werror(status
);
273 status
= rpccli_samr_QueryUserInfo(pipe_cli
, ctx
,
277 if (!NT_STATUS_IS_OK(status
)) {
278 werr
= ntstatus_to_werror(status
);
282 if (!(user_info
->info16
.acct_flags
& ACB_NORMAL
)) {
283 werr
= WERR_INVALID_PARAM
;
287 status
= rpccli_samr_GetUserPwInfo(pipe_cli
, ctx
,
290 if (!NT_STATUS_IS_OK(status
)) {
291 werr
= ntstatus_to_werror(status
);
295 ZERO_STRUCTP(user_info
);
297 convert_USER_INFO_1_to_samr_user_info25(info1
,
298 &cli
->user_session_key
,
301 if (info1
->usri1_password
) {
302 user_info
->info25
= info25
;
303 status
= rpccli_samr_SetUserInfo2(pipe_cli
, ctx
,
308 user_info
->info21
= info25
.info
;
309 status
= rpccli_samr_SetUserInfo(pipe_cli
, ctx
,
315 if (!NT_STATUS_IS_OK(status
)) {
316 werr
= ntstatus_to_werror(status
);
324 status
= rpccli_samr_DeleteUser(pipe_cli
, ctx
,
326 if (!NT_STATUS_IS_OK(status
)) {
327 werr
= ntstatus_to_werror(status
);
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
);
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
;
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;
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
)) {
381 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
383 werr
= ntstatus_to_werror(status
);
387 status
= rpccli_try_samr_connects(pipe_cli
, ctx
,
388 SAMR_ACCESS_ENUM_DOMAINS
|
389 SAMR_ACCESS_OPEN_DOMAIN
,
391 if (!NT_STATUS_IS_OK(status
)) {
392 werr
= ntstatus_to_werror(status
);
396 status
= rpccli_samr_EnumDomains(pipe_cli
, ctx
,
402 if (!NT_STATUS_IS_OK(status
)) {
403 werr
= ntstatus_to_werror(status
);
407 for (i
=0; i
<num_entries
; i
++) {
409 domain_name
= sam
->entries
[i
].name
.string
;
411 if (strequal(domain_name
, builtin_domain_name())) {
420 werr
= WERR_NO_SUCH_DOMAIN
;
424 init_lsa_String(&lsa_domain_name
, domain_name
);
426 status
= rpccli_samr_LookupDomain(pipe_cli
, ctx
,
430 if (!NT_STATUS_IS_OK(status
)) {
431 werr
= ntstatus_to_werror(status
);
435 status
= rpccli_samr_OpenDomain(pipe_cli
, ctx
,
437 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
440 if (!NT_STATUS_IS_OK(status
)) {
441 werr
= ntstatus_to_werror(status
);
445 status
= rpccli_samr_OpenDomain(pipe_cli
, ctx
,
447 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
448 CONST_DISCARD(DOM_SID
*, &global_sid_Builtin
),
450 if (!NT_STATUS_IS_OK(status
)) {
451 werr
= ntstatus_to_werror(status
);
455 init_lsa_String(&lsa_account_name
, r
->in
.user_name
);
457 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
463 if (!NT_STATUS_IS_OK(status
)) {
464 werr
= ntstatus_to_werror(status
);
468 status
= rpccli_samr_OpenUser(pipe_cli
, ctx
,
470 STD_RIGHT_DELETE_ACCESS
,
473 if (!NT_STATUS_IS_OK(status
)) {
474 werr
= ntstatus_to_werror(status
);
478 sid_compose(&user_sid
, domain_sid
, user_rids
.ids
[0]);
480 status
= rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli
, ctx
,
483 if (!NT_STATUS_IS_OK(status
)) {
484 werr
= ntstatus_to_werror(status
);
488 status
= rpccli_samr_DeleteUser(pipe_cli
, ctx
,
490 if (!NT_STATUS_IS_OK(status
)) {
491 werr
= ntstatus_to_werror(status
);
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
);
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
,
535 struct USER_INFO_0
*info0
= NULL
;
540 info0
= TALLOC_ZERO_ARRAY(mem_ctx
, struct USER_INFO_0
,
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
);
555 return WERR_NOT_SUPPORTED
;
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;
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
;
583 ZERO_STRUCT(connect_handle
);
584 ZERO_STRUCT(domain_handle
);
586 switch (r
->in
.level
) {
597 return WERR_NOT_SUPPORTED
;
600 werr
= libnetapi_open_ipc_connection(ctx
, r
->in
.server_name
, &cli
);
601 if (!W_ERROR_IS_OK(werr
)) {
605 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
607 werr
= ntstatus_to_werror(status
);
611 status
= rpccli_try_samr_connects(pipe_cli
, ctx
,
612 SAMR_ACCESS_OPEN_DOMAIN
|
613 SAMR_ACCESS_ENUM_DOMAINS
,
615 if (!NT_STATUS_IS_OK(status
)) {
616 werr
= ntstatus_to_werror(status
);
620 status
= rpccli_samr_EnumDomains(pipe_cli
, ctx
,
626 if (!NT_STATUS_IS_OK(status
)) {
627 werr
= ntstatus_to_werror(status
);
631 for (i
=0; i
<num_entries
; i
++) {
633 domain_name
= sam
->entries
[i
].name
.string
;
635 if (strequal(domain_name
, builtin_domain_name())) {
644 werr
= WERR_NO_SUCH_DOMAIN
;
648 init_lsa_String(&lsa_domain_name
, domain_name
);
650 status
= rpccli_samr_LookupDomain(pipe_cli
, ctx
,
654 if (!NT_STATUS_IS_OK(status
)) {
655 werr
= ntstatus_to_werror(status
);
659 status
= rpccli_samr_OpenDomain(pipe_cli
,
662 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2
|
663 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
|
664 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
667 if (!NT_STATUS_IS_OK(status
)) {
668 werr
= ntstatus_to_werror(status
);
672 status
= rpccli_samr_EnumDomainUsers(pipe_cli
,
679 r
->out
.entries_read
);
680 if (!NT_STATUS_IS_OK(status
)) {
681 werr
= ntstatus_to_werror(status
);
685 werr
= convert_samr_samarray_to_USER_INFO_buffer(ctx
, sam
,
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
);
704 /****************************************************************
705 ****************************************************************/
707 WERROR
NetUserEnum_l(struct libnetapi_ctx
*ctx
,
708 struct NetUserEnum
*r
)
710 return WERR_NOT_SUPPORTED
;