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/libnetapi.h"
26 /****************************************************************
27 ****************************************************************/
29 WERROR
NetUserAdd_l(struct libnetapi_ctx
*ctx
,
32 return WERR_NOT_SUPPORTED
;
35 /****************************************************************
36 ****************************************************************/
38 static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1
*info1
,
39 DATA_BLOB
*user_session_key
,
40 struct samr_UserInfo25
*info25
)
42 uint32_t fields_present
= SAMR_FIELD_ACCT_FLAGS
;
43 struct samr_LogonHours zero_logon_hours
;
44 struct lsa_BinaryString zero_parameters
;
45 uint32_t acct_flags
= 0;
49 ZERO_STRUCT(zero_logon_hours
);
50 ZERO_STRUCT(zero_parameters
);
52 if (info1
->usri1_name
) {
53 fields_present
|= SAMR_FIELD_FULL_NAME
;
55 if (info1
->usri1_password
) {
56 fields_present
|= SAMR_FIELD_PASSWORD
;
58 if (info1
->usri1_flags
) {
59 fields_present
|= SAMR_FIELD_ACCT_FLAGS
;
61 if (info1
->usri1_name
) {
62 fields_present
|= SAMR_FIELD_FULL_NAME
;
64 if (info1
->usri1_home_dir
) {
65 fields_present
|= SAMR_FIELD_HOME_DIRECTORY
;
67 if (info1
->usri1_script_path
) {
68 fields_present
|= SAMR_FIELD_LOGON_SCRIPT
;
70 if (info1
->usri1_comment
) {
71 fields_present
|= SAMR_FIELD_DESCRIPTION
;
73 if (info1
->usri1_password_age
) {
74 fields_present
|= SAMR_FIELD_FORCE_PWD_CHANGE
;
77 acct_flags
|= info1
->usri1_flags
| ACB_NORMAL
;
79 unix_to_nt_time_abs(&password_age
, info1
->usri1_password_age
);
81 /* TODO: info1->usri1_priv */
82 init_samr_user_info21(&info25
->info
,
91 info1
->usri1_home_dir
,
93 info1
->usri1_script_path
,
112 if (info1
->usri1_password
) {
114 struct MD5Context ctx
;
115 uint8_t confounder
[16];
116 DATA_BLOB confounded_session_key
= data_blob(NULL
, 16);
118 encode_pw_buffer(pwbuf
, info1
->usri1_password
, STR_UNICODE
);
120 generate_random_buffer((uint8_t *)confounder
, 16);
123 MD5Update(&ctx
, confounder
, 16);
124 MD5Update(&ctx
, user_session_key
->data
,
125 user_session_key
->length
);
126 MD5Final(confounded_session_key
.data
, &ctx
);
128 SamOEMhashBlob(pwbuf
, 516, &confounded_session_key
);
129 memcpy(&pwbuf
[516], confounder
, 16);
131 memcpy(info25
->password
.data
, pwbuf
, sizeof(pwbuf
));
132 data_blob_free(&confounded_session_key
);
136 /****************************************************************
137 ****************************************************************/
139 WERROR
NetUserAdd_r(struct libnetapi_ctx
*ctx
,
140 struct NetUserAdd
*r
)
142 struct cli_state
*cli
= NULL
;
143 struct rpc_pipe_client
*pipe_cli
= NULL
;
146 uint32_t resume_handle
= 0;
147 uint32_t num_entries
= 0;
148 POLICY_HND connect_handle
, domain_handle
, user_handle
;
149 struct samr_SamArray
*sam
= NULL
;
150 const char *domain_name
= NULL
;
151 struct lsa_String lsa_domain_name
, lsa_account_name
;
152 struct dom_sid2
*domain_sid
= NULL
;
153 struct samr_UserInfo25 info25
;
154 union samr_UserInfo
*user_info
= NULL
;
155 struct samr_PwInfo pw_info
;
156 uint32_t access_granted
= 0;
158 bool domain_found
= true;
160 struct USER_INFO_1
*info1
;
162 ZERO_STRUCT(connect_handle
);
163 ZERO_STRUCT(domain_handle
);
164 ZERO_STRUCT(user_handle
);
167 return WERR_INVALID_PARAM
;
170 switch (r
->in
.level
) {
172 info1
= (struct USER_INFO_1
*)r
->in
.buffer
;
178 werr
= WERR_NOT_SUPPORTED
;
182 status
= cli_full_connection(&cli
, NULL
, r
->in
.server_name
,
188 CLI_FULL_CONNECTION_USE_KERBEROS
|
189 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
,
192 if (!NT_STATUS_IS_OK(status
)) {
193 werr
= ntstatus_to_werror(status
);
197 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
199 werr
= ntstatus_to_werror(status
);
203 status
= rpccli_try_samr_connects(pipe_cli
, ctx
,
204 SAMR_ACCESS_ENUM_DOMAINS
|
205 SAMR_ACCESS_OPEN_DOMAIN
,
207 if (!NT_STATUS_IS_OK(status
)) {
208 werr
= ntstatus_to_werror(status
);
212 status
= rpccli_samr_EnumDomains(pipe_cli
, ctx
,
218 if (!NT_STATUS_IS_OK(status
)) {
219 werr
= ntstatus_to_werror(status
);
223 for (i
=0; i
<num_entries
; i
++) {
225 domain_name
= sam
->entries
[i
].name
.string
;
227 if (strequal(domain_name
, builtin_domain_name())) {
236 werr
= WERR_NO_SUCH_DOMAIN
;
240 init_lsa_String(&lsa_domain_name
, domain_name
);
242 status
= rpccli_samr_LookupDomain(pipe_cli
, ctx
,
246 if (!NT_STATUS_IS_OK(status
)) {
247 werr
= ntstatus_to_werror(status
);
251 status
= rpccli_samr_OpenDomain(pipe_cli
, ctx
,
253 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
|
254 SAMR_DOMAIN_ACCESS_CREATE_USER
|
255 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
258 if (!NT_STATUS_IS_OK(status
)) {
259 werr
= ntstatus_to_werror(status
);
263 init_lsa_String(&lsa_account_name
, info1
->usri1_name
);
265 status
= rpccli_samr_CreateUser2(pipe_cli
, ctx
,
271 SAMR_USER_ACCESS_SET_PASSWORD
|
272 SAMR_USER_ACCESS_SET_ATTRIBUTES
|
273 SAMR_USER_ACCESS_GET_ATTRIBUTES
,
277 if (!NT_STATUS_IS_OK(status
)) {
278 werr
= ntstatus_to_werror(status
);
282 status
= rpccli_samr_QueryUserInfo(pipe_cli
, ctx
,
286 if (!NT_STATUS_IS_OK(status
)) {
287 werr
= ntstatus_to_werror(status
);
291 if (!(user_info
->info16
.acct_flags
& ACB_NORMAL
)) {
292 werr
= WERR_INVALID_PARAM
;
296 status
= rpccli_samr_GetUserPwInfo(pipe_cli
, ctx
,
299 if (!NT_STATUS_IS_OK(status
)) {
300 werr
= ntstatus_to_werror(status
);
304 ZERO_STRUCTP(user_info
);
306 convert_USER_INFO_1_to_samr_user_info25(info1
,
307 &cli
->user_session_key
,
310 if (info1
->usri1_password
) {
311 user_info
->info25
= info25
;
312 status
= rpccli_samr_SetUserInfo2(pipe_cli
, ctx
,
317 user_info
->info21
= info25
.info
;
318 status
= rpccli_samr_SetUserInfo(pipe_cli
, ctx
,
324 if (!NT_STATUS_IS_OK(status
)) {
325 werr
= ntstatus_to_werror(status
);
333 status
= rpccli_samr_DeleteUser(pipe_cli
, ctx
,
335 if (!NT_STATUS_IS_OK(status
)) {
336 werr
= ntstatus_to_werror(status
);
345 if (is_valid_policy_hnd(&user_handle
)) {
346 rpccli_samr_Close(pipe_cli
, ctx
, &user_handle
);
348 if (is_valid_policy_hnd(&domain_handle
)) {
349 rpccli_samr_Close(pipe_cli
, ctx
, &domain_handle
);
351 if (is_valid_policy_hnd(&connect_handle
)) {
352 rpccli_samr_Close(pipe_cli
, ctx
, &connect_handle
);
360 /****************************************************************
361 ****************************************************************/
363 WERROR
NetUserDel_r(struct libnetapi_ctx
*ctx
,
364 struct NetUserDel
*r
)
366 struct cli_state
*cli
= NULL
;
367 struct rpc_pipe_client
*pipe_cli
= NULL
;
370 uint32_t resume_handle
= 0;
371 uint32_t num_entries
= 0;
372 POLICY_HND connect_handle
, builtin_handle
, domain_handle
, user_handle
;
373 struct samr_SamArray
*sam
= NULL
;
374 const char *domain_name
= NULL
;
375 struct lsa_String lsa_domain_name
, lsa_account_name
;
376 struct samr_Ids user_rids
, name_types
;
377 struct dom_sid2
*domain_sid
= NULL
;
378 struct dom_sid2 user_sid
;
379 bool domain_found
= true;
382 ZERO_STRUCT(connect_handle
);
383 ZERO_STRUCT(builtin_handle
);
384 ZERO_STRUCT(domain_handle
);
385 ZERO_STRUCT(user_handle
);
387 status
= cli_full_connection(&cli
, NULL
, r
->in
.server_name
,
393 CLI_FULL_CONNECTION_USE_KERBEROS
|
394 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
,
397 if (!NT_STATUS_IS_OK(status
)) {
398 werr
= ntstatus_to_werror(status
);
402 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
404 werr
= ntstatus_to_werror(status
);
408 status
= rpccli_try_samr_connects(pipe_cli
, ctx
,
409 SAMR_ACCESS_ENUM_DOMAINS
|
410 SAMR_ACCESS_OPEN_DOMAIN
,
412 if (!NT_STATUS_IS_OK(status
)) {
413 werr
= ntstatus_to_werror(status
);
417 status
= rpccli_samr_EnumDomains(pipe_cli
, ctx
,
423 if (!NT_STATUS_IS_OK(status
)) {
424 werr
= ntstatus_to_werror(status
);
428 for (i
=0; i
<num_entries
; i
++) {
430 domain_name
= sam
->entries
[i
].name
.string
;
432 if (strequal(domain_name
, builtin_domain_name())) {
441 werr
= WERR_NO_SUCH_DOMAIN
;
445 init_lsa_String(&lsa_domain_name
, domain_name
);
447 status
= rpccli_samr_LookupDomain(pipe_cli
, ctx
,
451 if (!NT_STATUS_IS_OK(status
)) {
452 werr
= ntstatus_to_werror(status
);
456 status
= rpccli_samr_OpenDomain(pipe_cli
, ctx
,
458 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
461 if (!NT_STATUS_IS_OK(status
)) {
462 werr
= ntstatus_to_werror(status
);
466 status
= rpccli_samr_OpenDomain(pipe_cli
, ctx
,
468 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
469 CONST_DISCARD(DOM_SID
*, &global_sid_Builtin
),
471 if (!NT_STATUS_IS_OK(status
)) {
472 werr
= ntstatus_to_werror(status
);
476 init_lsa_String(&lsa_account_name
, r
->in
.user_name
);
478 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
484 if (!NT_STATUS_IS_OK(status
)) {
485 werr
= ntstatus_to_werror(status
);
489 status
= rpccli_samr_OpenUser(pipe_cli
, ctx
,
491 STD_RIGHT_DELETE_ACCESS
,
494 if (!NT_STATUS_IS_OK(status
)) {
495 werr
= ntstatus_to_werror(status
);
499 sid_compose(&user_sid
, domain_sid
, user_rids
.ids
[0]);
501 status
= rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli
, ctx
,
504 if (!NT_STATUS_IS_OK(status
)) {
505 werr
= ntstatus_to_werror(status
);
509 status
= rpccli_samr_DeleteUser(pipe_cli
, ctx
,
511 if (!NT_STATUS_IS_OK(status
)) {
512 werr
= ntstatus_to_werror(status
);
523 if (is_valid_policy_hnd(&user_handle
)) {
524 rpccli_samr_Close(pipe_cli
, ctx
, &user_handle
);
526 if (is_valid_policy_hnd(&builtin_handle
)) {
527 rpccli_samr_Close(pipe_cli
, ctx
, &builtin_handle
);
529 if (is_valid_policy_hnd(&domain_handle
)) {
530 rpccli_samr_Close(pipe_cli
, ctx
, &domain_handle
);
532 if (is_valid_policy_hnd(&connect_handle
)) {
533 rpccli_samr_Close(pipe_cli
, ctx
, &connect_handle
);
541 /****************************************************************
542 ****************************************************************/
544 WERROR
NetUserDel_l(struct libnetapi_ctx
*ctx
,
545 struct NetUserDel
*r
)
547 return WERR_NOT_SUPPORTED
;