2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2004
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "libnet/libnet.h"
23 #include "libcli/auth/libcli_auth.h"
24 #include "librpc/gen_ndr/ndr_samr_c.h"
25 #include "source4/librpc/rpc/dcerpc.h"
26 #include "auth/credentials/credentials.h"
27 #include "libcli/smb/smb_constants.h"
28 #include "librpc/rpc/dcerpc_samr.h"
29 #include "source3/rpc_client/init_samr.h"
30 #include "lib/param/loadparm.h"
31 #include "lib/param/param.h"
33 #include "lib/crypto/gnutls_helpers.h"
34 #include <gnutls/gnutls.h>
35 #include <gnutls/crypto.h>
37 static NTSTATUS
libnet_ChangePassword_samr_aes(TALLOC_CTX
*mem_ctx
,
38 struct dcerpc_binding_handle
*h
,
39 struct lsa_String
*server
,
40 struct lsa_String
*account
,
41 const char *old_password
,
42 const char *new_password
,
43 const char **error_string
)
45 #ifdef HAVE_GNUTLS_PBKDF2
46 struct samr_ChangePasswordUser4 r
;
47 uint8_t old_nt_key_data
[16] = {0};
48 gnutls_datum_t old_nt_key
= {
49 .data
= old_nt_key_data
,
50 .size
= sizeof(old_nt_key_data
),
52 uint8_t cek_data
[16] = {0};
55 .length
= sizeof(cek_data
),
57 struct samr_EncryptedPasswordAES pwd_buf
= {
62 .length
= sizeof(pwd_buf
.salt
),
64 gnutls_datum_t salt_datum
= {
66 .size
= sizeof(pwd_buf
.salt
),
68 uint64_t pbkdf2_iterations
= generate_random_u64_range(5000, 1000000);
72 E_md4hash(old_password
, old_nt_key_data
);
74 generate_nonce_buffer(salt
.data
, salt
.length
);
76 rc
= gnutls_pbkdf2(GNUTLS_MAC_SHA512
,
82 BURN_DATA(old_nt_key_data
);
84 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
85 if (!NT_STATUS_IS_OK(status
)) {
90 status
= init_samr_CryptPasswordAES(mem_ctx
,
95 data_blob_clear(&cek
);
96 if (!NT_STATUS_IS_OK(status
)) {
100 pwd_buf
.PBKDF2Iterations
= pbkdf2_iterations
;
102 r
.in
.server
= server
;
103 r
.in
.account
= account
;
104 r
.in
.password
= &pwd_buf
;
106 status
= dcerpc_samr_ChangePasswordUser4_r(h
, mem_ctx
, &r
);
107 if (!NT_STATUS_IS_OK(status
)) {
110 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
111 status
= r
.out
.result
;
112 *error_string
= talloc_asprintf(mem_ctx
,
113 "samr_ChangePasswordUser4 for "
114 "'%s\\%s' failed: %s",
125 #else /* HAVE_GNUTLS_PBKDF2 */
126 return NT_STATUS_NOT_IMPLEMENTED
;
127 #endif /* HAVE_GNUTLS_PBKDF2 */
130 static NTSTATUS
libnet_ChangePassword_samr_rc4(TALLOC_CTX
*mem_ctx
,
131 struct dcerpc_binding_handle
*h
,
132 struct lsa_String
*server
,
133 struct lsa_String
*account
,
134 const char *old_password
,
135 const char *new_password
,
136 const char **error_string
)
138 struct samr_OemChangePasswordUser2 oe2
;
139 struct samr_ChangePasswordUser2 pw2
;
140 struct samr_ChangePasswordUser3 pw3
;
141 struct samr_CryptPassword nt_pass
, lm_pass
;
142 uint8_t old_nt_hash
[16], new_nt_hash
[16];
143 uint8_t old_lm_hash
[16], new_lm_hash
[16];
144 struct samr_Password nt_verifier
, lm_verifier
;
145 struct lsa_AsciiString a_server
, a_account
;
146 gnutls_cipher_hd_t cipher_hnd
= NULL
;
147 gnutls_datum_t nt_session_key
= {
149 .size
= sizeof(old_nt_hash
),
151 gnutls_datum_t lm_session_key
= {
153 .size
= sizeof(old_lm_hash
),
155 struct samr_DomInfo1
*dominfo
= NULL
;
156 struct userPwdChangeFailureInformation
*reject
= NULL
;
160 E_md4hash(old_password
, old_nt_hash
);
161 E_md4hash(new_password
, new_nt_hash
);
163 E_deshash(old_password
, old_lm_hash
);
164 E_deshash(new_password
, new_lm_hash
);
166 /* prepare samr_ChangePasswordUser3 */
167 encode_pw_buffer(lm_pass
.data
, new_password
, STR_UNICODE
);
169 rc
= gnutls_cipher_init(&cipher_hnd
,
170 GNUTLS_CIPHER_ARCFOUR_128
,
174 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
178 rc
= gnutls_cipher_encrypt(cipher_hnd
,
181 gnutls_cipher_deinit(cipher_hnd
);
183 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
187 rc
= E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
189 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
193 encode_pw_buffer(nt_pass
.data
, new_password
, STR_UNICODE
);
195 rc
= gnutls_cipher_init(&cipher_hnd
,
196 GNUTLS_CIPHER_ARCFOUR_128
,
200 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
204 rc
= gnutls_cipher_encrypt(cipher_hnd
,
207 gnutls_cipher_deinit(cipher_hnd
);
209 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
213 rc
= E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
215 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
219 pw3
.in
.server
= server
;
220 pw3
.in
.account
= account
;
221 pw3
.in
.nt_password
= &nt_pass
;
222 pw3
.in
.nt_verifier
= &nt_verifier
;
223 pw3
.in
.lm_change
= 1;
224 pw3
.in
.lm_password
= &lm_pass
;
225 pw3
.in
.lm_verifier
= &lm_verifier
;
226 pw3
.in
.password3
= NULL
;
227 pw3
.out
.dominfo
= &dominfo
;
228 pw3
.out
.reject
= &reject
;
230 /* 2. try samr_ChangePasswordUser3 */
231 status
= dcerpc_samr_ChangePasswordUser3_r(h
, mem_ctx
, &pw3
);
232 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
233 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(pw3
.out
.result
)) {
234 status
= pw3
.out
.result
;
236 if (!NT_STATUS_IS_OK(status
)) {
237 *error_string
= talloc_asprintf(
239 "samr_ChangePasswordUser3 failed: %s",
242 talloc_asprintf(mem_ctx
,
243 "samr_ChangePasswordUser3 for "
244 "'%s\\%s' failed: %s",
252 /* prepare samr_ChangePasswordUser2 */
253 encode_pw_buffer(lm_pass
.data
, new_password
, STR_ASCII
| STR_TERMINATE
);
255 rc
= gnutls_cipher_init(&cipher_hnd
,
256 GNUTLS_CIPHER_ARCFOUR_128
,
260 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
264 rc
= gnutls_cipher_encrypt(cipher_hnd
,
267 gnutls_cipher_deinit(cipher_hnd
);
269 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
273 rc
= E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
275 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
279 encode_pw_buffer(nt_pass
.data
, new_password
, STR_UNICODE
);
281 rc
= gnutls_cipher_init(&cipher_hnd
,
282 GNUTLS_CIPHER_ARCFOUR_128
,
286 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
289 rc
= gnutls_cipher_encrypt(cipher_hnd
,
292 gnutls_cipher_deinit(cipher_hnd
);
294 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
298 rc
= E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
300 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
304 pw2
.in
.server
= server
;
305 pw2
.in
.account
= account
;
306 pw2
.in
.nt_password
= &nt_pass
;
307 pw2
.in
.nt_verifier
= &nt_verifier
;
308 pw2
.in
.lm_change
= 1;
309 pw2
.in
.lm_password
= &lm_pass
;
310 pw2
.in
.lm_verifier
= &lm_verifier
;
312 /* 3. try samr_ChangePasswordUser2 */
313 status
= dcerpc_samr_ChangePasswordUser2_r(h
, mem_ctx
, &pw2
);
314 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
315 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(pw2
.out
.result
)) {
316 status
= pw2
.out
.result
;
318 if (!NT_STATUS_IS_OK(status
)) {
320 talloc_asprintf(mem_ctx
,
321 "samr_ChangePasswordUser2 for "
322 "'%s\\%s' failed: %s",
331 /* prepare samr_OemChangePasswordUser2 */
332 a_server
.string
= server
->string
;
333 a_account
.string
= account
->string
;
335 encode_pw_buffer(lm_pass
.data
, new_password
, STR_ASCII
);
337 rc
= gnutls_cipher_init(&cipher_hnd
,
338 GNUTLS_CIPHER_ARCFOUR_128
,
342 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
346 rc
= gnutls_cipher_encrypt(cipher_hnd
,
349 gnutls_cipher_deinit(cipher_hnd
);
351 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
355 rc
= E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
357 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
361 oe2
.in
.server
= &a_server
;
362 oe2
.in
.account
= &a_account
;
363 oe2
.in
.password
= &lm_pass
;
364 oe2
.in
.hash
= &lm_verifier
;
366 /* 4. try samr_OemChangePasswordUser2 */
367 status
= dcerpc_samr_OemChangePasswordUser2_r(h
, mem_ctx
, &oe2
);
368 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
369 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(oe2
.out
.result
)) {
370 status
= oe2
.out
.result
;
372 if (!NT_STATUS_IS_OK(oe2
.out
.result
)) {
374 talloc_asprintf(mem_ctx
,
375 "samr_OemChangePasswordUser2 "
376 "for '%s\\%s' failed: %s",
384 status
= NT_STATUS_OK
;
390 * do a password change using DCERPC/SAMR calls
391 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
392 * 2. try samr_ChangePasswordUser3
393 * 3. try samr_ChangePasswordUser2
394 * 4. try samr_OemChangePasswordUser2
396 static NTSTATUS
libnet_ChangePassword_samr(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_ChangePassword
*r
)
399 struct libnet_RpcConnect c
;
400 struct lsa_String server
, account
;
404 /* prepare connect to the SAMR pipe of the users domain PDC */
405 c
.level
= LIBNET_RPC_CONNECT_PDC
;
406 c
.in
.name
= r
->samr
.in
.domain_name
;
407 c
.in
.dcerpc_iface
= &ndr_table_samr
;
408 c
.in
.dcerpc_flags
= DCERPC_ANON_FALLBACK
;
410 /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
411 status
= libnet_RpcConnect(ctx
, mem_ctx
, &c
);
412 if (!NT_STATUS_IS_OK(status
)) {
413 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
414 "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
415 r
->samr
.in
.domain_name
, nt_errstr(status
));
419 /* prepare password change for account */
420 server
.string
= talloc_asprintf(mem_ctx
, "\\\\%s", dcerpc_server_name(c
.out
.dcerpc_pipe
));
421 account
.string
= r
->samr
.in
.account_name
;
423 status
= libnet_ChangePassword_samr_aes(
425 c
.out
.dcerpc_pipe
->binding_handle
,
428 r
->samr
.in
.oldpassword
,
429 r
->samr
.in
.newpassword
,
430 &(r
->samr
.out
.error_string
));
431 if (NT_STATUS_IS_OK(status
)) {
433 } else if (NT_STATUS_EQUAL(status
,
434 NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
) ||
435 NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
) ||
436 NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
438 * Don't fallback to RC4 based SAMR if weak crypto is not
441 if (lpcfg_weak_crypto(ctx
->lp_ctx
) ==
442 SAMBA_WEAK_CRYPTO_DISALLOWED
) {
446 /* libnet_ChangePassword_samr_aes is implemented and failed */
450 status
= libnet_ChangePassword_samr_rc4(
452 c
.out
.dcerpc_pipe
->binding_handle
,
455 r
->samr
.in
.oldpassword
,
456 r
->samr
.in
.newpassword
,
457 &(r
->samr
.out
.error_string
));
458 if (!NT_STATUS_IS_OK(status
)) {
463 /* close connection */
464 talloc_unlink(ctx
, c
.out
.dcerpc_pipe
);
469 static NTSTATUS
libnet_ChangePassword_generic(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_ChangePassword
*r
)
472 union libnet_ChangePassword r2
;
474 r2
.samr
.level
= LIBNET_CHANGE_PASSWORD_SAMR
;
475 r2
.samr
.in
.account_name
= r
->generic
.in
.account_name
;
476 r2
.samr
.in
.domain_name
= r
->generic
.in
.domain_name
;
477 r2
.samr
.in
.oldpassword
= r
->generic
.in
.oldpassword
;
478 r2
.samr
.in
.newpassword
= r
->generic
.in
.newpassword
;
480 status
= libnet_ChangePassword(ctx
, mem_ctx
, &r2
);
482 r
->generic
.out
.error_string
= r2
.samr
.out
.error_string
;
487 NTSTATUS
libnet_ChangePassword(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_ChangePassword
*r
)
489 switch (r
->generic
.level
) {
490 case LIBNET_CHANGE_PASSWORD_GENERIC
:
491 return libnet_ChangePassword_generic(ctx
, mem_ctx
, r
);
492 case LIBNET_CHANGE_PASSWORD_SAMR
:
493 return libnet_ChangePassword_samr(ctx
, mem_ctx
, r
);
494 case LIBNET_CHANGE_PASSWORD_KRB5
:
495 return NT_STATUS_NOT_IMPLEMENTED
;
496 case LIBNET_CHANGE_PASSWORD_LDAP
:
497 return NT_STATUS_NOT_IMPLEMENTED
;
498 case LIBNET_CHANGE_PASSWORD_RAP
:
499 return NT_STATUS_NOT_IMPLEMENTED
;
502 return NT_STATUS_INVALID_LEVEL
;
505 static NTSTATUS
libnet_SetPassword_samr_handle_26(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
508 struct samr_SetUserInfo2 sui
;
509 union samr_UserInfo u_info
;
510 DATA_BLOB session_key
;
512 if (r
->samr_handle
.in
.info21
) {
513 return NT_STATUS_INVALID_PARAMETER_MIX
;
516 /* prepare samr_SetUserInfo2 level 26 */
518 u_info
.info26
.password_expired
= 0;
520 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
521 if (!NT_STATUS_IS_OK(status
)) {
522 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
523 "dcerpc_fetch_session_key failed: %s",
528 status
= encode_rc4_passwd_buffer(r
->samr_handle
.in
.newpassword
,
530 &u_info
.info26
.password
);
531 if (!NT_STATUS_IS_OK(status
)) {
532 r
->samr_handle
.out
.error_string
=
533 talloc_asprintf(mem_ctx
,
534 "encode_rc4_passwd_buffer failed: %s",
539 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
540 sui
.in
.info
= &u_info
;
543 /* 7. try samr_SetUserInfo2 level 26 to set the password */
544 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
545 /* check result of samr_SetUserInfo2 level 26 */
546 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(sui
.out
.result
)) {
547 status
= sui
.out
.result
;
549 if (!NT_STATUS_IS_OK(status
)) {
550 r
->samr_handle
.out
.error_string
551 = talloc_asprintf(mem_ctx
,
552 "SetUserInfo2 level 26 for [%s] failed: %s",
553 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
559 static NTSTATUS
libnet_SetPassword_samr_handle_25(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
562 struct samr_SetUserInfo2 sui
;
563 union samr_UserInfo u_info
;
564 DATA_BLOB session_key
;
566 if (!r
->samr_handle
.in
.info21
) {
567 return NT_STATUS_INVALID_PARAMETER_MIX
;
570 /* prepare samr_SetUserInfo2 level 25 */
572 u_info
.info25
.info
= *r
->samr_handle
.in
.info21
;
573 u_info
.info25
.info
.fields_present
|= SAMR_FIELD_NT_PASSWORD_PRESENT
;
575 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
576 if (!NT_STATUS_IS_OK(status
)) {
577 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
578 "dcerpc_fetch_session_key failed: %s",
583 status
= encode_rc4_passwd_buffer(r
->samr_handle
.in
.newpassword
,
585 &u_info
.info25
.password
);
586 if (!NT_STATUS_IS_OK(status
)) {
587 r
->samr_handle
.out
.error_string
=
588 talloc_asprintf(mem_ctx
,
589 "encode_rc4_passwd_buffer failed: %s",
595 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
596 sui
.in
.info
= &u_info
;
599 /* 8. try samr_SetUserInfo2 level 25 to set the password */
600 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
601 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(sui
.out
.result
)) {
602 status
= sui
.out
.result
;
604 if (!NT_STATUS_IS_OK(status
)) {
605 r
->samr_handle
.out
.error_string
606 = talloc_asprintf(mem_ctx
,
607 "SetUserInfo2 level 25 for [%s] failed: %s",
608 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
614 static NTSTATUS
libnet_SetPassword_samr_handle_24(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
617 struct samr_SetUserInfo2 sui
;
618 union samr_UserInfo u_info
;
619 DATA_BLOB session_key
;
620 gnutls_cipher_hd_t cipher_hnd
= NULL
;
621 gnutls_datum_t enc_session_key
;
624 if (r
->samr_handle
.in
.info21
) {
625 return NT_STATUS_INVALID_PARAMETER_MIX
;
628 /* prepare samr_SetUserInfo2 level 24 */
630 encode_pw_buffer(u_info
.info24
.password
.data
, r
->samr_handle
.in
.newpassword
, STR_UNICODE
);
631 u_info
.info24
.password_expired
= 0;
633 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
634 if (!NT_STATUS_IS_OK(status
)) {
635 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
636 "dcerpc_fetch_session_key failed: %s",
641 enc_session_key
= (gnutls_datum_t
) {
642 .data
= session_key
.data
,
643 .size
= session_key
.length
,
646 rc
= gnutls_cipher_init(&cipher_hnd
,
647 GNUTLS_CIPHER_ARCFOUR_128
,
651 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
655 rc
= gnutls_cipher_encrypt(cipher_hnd
,
656 u_info
.info24
.password
.data
,
658 gnutls_cipher_deinit(cipher_hnd
);
660 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
664 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
665 sui
.in
.info
= &u_info
;
668 /* 9. try samr_SetUserInfo2 level 24 to set the password */
669 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
670 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(sui
.out
.result
)) {
671 status
= sui
.out
.result
;
673 if (!NT_STATUS_IS_OK(status
)) {
674 r
->samr_handle
.out
.error_string
675 = talloc_asprintf(mem_ctx
,
676 "SetUserInfo2 level 24 for [%s] failed: %s",
677 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
681 data_blob_clear(&session_key
);
685 static NTSTATUS
libnet_SetPassword_samr_handle_23(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
688 struct samr_SetUserInfo2 sui
;
689 union samr_UserInfo u_info
;
690 DATA_BLOB session_key
;
691 gnutls_cipher_hd_t cipher_hnd
= NULL
;
692 gnutls_datum_t _session_key
;
695 if (!r
->samr_handle
.in
.info21
) {
696 return NT_STATUS_INVALID_PARAMETER_MIX
;
699 /* prepare samr_SetUserInfo2 level 23 */
701 u_info
.info23
.info
= *r
->samr_handle
.in
.info21
;
702 u_info
.info23
.info
.fields_present
|= SAMR_FIELD_NT_PASSWORD_PRESENT
;
703 encode_pw_buffer(u_info
.info23
.password
.data
, r
->samr_handle
.in
.newpassword
, STR_UNICODE
);
705 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
706 if (!NT_STATUS_IS_OK(status
)) {
707 r
->samr_handle
.out
.error_string
708 = talloc_asprintf(mem_ctx
,
709 "dcerpc_fetch_session_key failed: %s",
714 _session_key
= (gnutls_datum_t
) {
715 .data
= session_key
.data
,
716 .size
= session_key
.length
,
719 rc
= gnutls_cipher_init(&cipher_hnd
,
720 GNUTLS_CIPHER_ARCFOUR_128
,
724 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
728 rc
= gnutls_cipher_encrypt(cipher_hnd
,
729 u_info
.info23
.password
.data
,
731 data_blob_clear_free(&session_key
);
732 gnutls_cipher_deinit(cipher_hnd
);
734 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
738 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
739 sui
.in
.info
= &u_info
;
742 /* 10. try samr_SetUserInfo2 level 23 to set the password */
743 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
744 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(sui
.out
.result
)) {
745 status
= sui
.out
.result
;
747 if (!NT_STATUS_IS_OK(status
)) {
748 r
->samr_handle
.out
.error_string
749 = talloc_asprintf(mem_ctx
,
750 "SetUserInfo2 level 23 for [%s] failed: %s",
751 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
758 static NTSTATUS
libnet_SetPassword_samr_handle_18(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
761 struct samr_SetUserInfo2 sui
;
762 union samr_UserInfo u_info
;
763 struct samr_Password ntpwd
;
766 DATA_BLOB session_key
;
769 if (r
->samr_handle
.in
.info21
) {
770 return NT_STATUS_INVALID_PARAMETER_MIX
;
773 /* prepare samr_SetUserInfo2 level 18 (nt_hash) */
775 E_md4hash(r
->samr_handle
.in
.newpassword
, ntpwd
.hash
);
776 ntpwd_in
= data_blob_const(ntpwd
.hash
, sizeof(ntpwd
.hash
));
777 ntpwd_out
= data_blob_const(u_info
.info18
.nt_pwd
.hash
,
778 sizeof(u_info
.info18
.nt_pwd
.hash
));
779 u_info
.info18
.nt_pwd_active
= 1;
780 u_info
.info18
.password_expired
= 0;
782 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
783 if (!NT_STATUS_IS_OK(status
)) {
784 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
785 "dcerpc_fetch_session_key failed: %s",
790 rc
= sess_crypt_blob(&ntpwd_out
, &ntpwd_in
,
791 &session_key
, SAMBA_GNUTLS_ENCRYPT
);
793 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
797 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
798 sui
.in
.info
= &u_info
;
801 /* 9. try samr_SetUserInfo2 level 18 to set the password */
802 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
803 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(sui
.out
.result
)) {
804 status
= sui
.out
.result
;
806 if (!NT_STATUS_IS_OK(status
)) {
807 r
->samr_handle
.out
.error_string
808 = talloc_asprintf(mem_ctx
,
809 "SetUserInfo2 level 18 for [%s] failed: %s",
810 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
814 data_blob_clear(&session_key
);
819 * 1. try samr_SetUserInfo2 level 26 to set the password
820 * 2. try samr_SetUserInfo2 level 25 to set the password
821 * 3. try samr_SetUserInfo2 level 24 to set the password
822 * 4. try samr_SetUserInfo2 level 23 to set the password
824 static NTSTATUS
libnet_SetPassword_samr_handle(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
828 enum libnet_SetPassword_level levels
[] = {
829 LIBNET_SET_PASSWORD_SAMR_HANDLE_26
,
830 LIBNET_SET_PASSWORD_SAMR_HANDLE_25
,
831 LIBNET_SET_PASSWORD_SAMR_HANDLE_24
,
832 LIBNET_SET_PASSWORD_SAMR_HANDLE_23
,
836 if (r
->samr_handle
.samr_level
!= 0) {
837 r
->generic
.level
= r
->samr_handle
.samr_level
;
838 return libnet_SetPassword(ctx
, mem_ctx
, r
);
841 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
842 r
->generic
.level
= levels
[i
];
843 status
= libnet_SetPassword(ctx
, mem_ctx
, r
);
844 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_INFO_CLASS
)
845 || NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER_MIX
)
846 || NT_STATUS_EQUAL(status
, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
)) {
847 /* Try another password set mechanism */
856 * set a password with DCERPC/SAMR calls
857 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
858 * is it correct to contact the the pdc of the domain of the user who's password should be set?
859 * 2. do a samr_Connect to get a policy handle
860 * 3. do a samr_LookupDomain to get the domain sid
861 * 4. do a samr_OpenDomain to get a domain handle
862 * 5. do a samr_LookupNames to get the users rid
863 * 6. do a samr_OpenUser to get a user handle
864 * 7 call libnet_SetPassword_samr_handle to set the password
866 static NTSTATUS
libnet_SetPassword_samr(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
869 struct libnet_RpcConnect c
;
870 struct samr_Connect sc
;
871 struct policy_handle p_handle
;
872 struct samr_LookupDomain ld
;
873 struct dom_sid2
*sid
= NULL
;
874 struct lsa_String d_name
;
875 struct samr_OpenDomain od
;
876 struct policy_handle d_handle
;
877 struct samr_LookupNames ln
;
878 struct samr_Ids rids
, types
;
879 struct samr_OpenUser ou
;
880 struct policy_handle u_handle
;
881 union libnet_SetPassword r2
;
884 /* prepare connect to the SAMR pipe of users domain PDC */
885 c
.level
= LIBNET_RPC_CONNECT_PDC
;
886 c
.in
.name
= r
->samr
.in
.domain_name
;
887 c
.in
.dcerpc_iface
= &ndr_table_samr
;
889 /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
890 status
= libnet_RpcConnect(ctx
, mem_ctx
, &c
);
891 if (!NT_STATUS_IS_OK(status
)) {
892 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
893 "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
894 r
->samr
.in
.domain_name
, nt_errstr(status
));
898 /* prepare samr_Connect */
899 ZERO_STRUCT(p_handle
);
900 sc
.in
.system_name
= NULL
;
901 sc
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
902 sc
.out
.connect_handle
= &p_handle
;
904 /* 2. do a samr_Connect to get a policy handle */
905 status
= dcerpc_samr_Connect_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sc
);
906 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(sc
.out
.result
)) {
907 status
= sc
.out
.result
;
909 if (!NT_STATUS_IS_OK(status
)) {
910 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
911 "samr_Connect failed: %s",
916 /* prepare samr_LookupDomain */
917 d_name
.string
= r
->samr
.in
.domain_name
;
918 ld
.in
.connect_handle
= &p_handle
;
919 ld
.in
.domain_name
= &d_name
;
922 /* 3. do a samr_LookupDomain to get the domain sid */
923 status
= dcerpc_samr_LookupDomain_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &ld
);
924 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(ld
.out
.result
)) {
925 status
= ld
.out
.result
;
927 if (!NT_STATUS_IS_OK(status
)) {
928 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
929 "samr_LookupDomain for [%s] failed: %s",
930 r
->samr
.in
.domain_name
, nt_errstr(status
));
934 /* prepare samr_OpenDomain */
935 ZERO_STRUCT(d_handle
);
936 od
.in
.connect_handle
= &p_handle
;
937 od
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
938 od
.in
.sid
= *ld
.out
.sid
;
939 od
.out
.domain_handle
= &d_handle
;
941 /* 4. do a samr_OpenDomain to get a domain handle */
942 status
= dcerpc_samr_OpenDomain_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &od
);
943 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(od
.out
.result
)) {
944 status
= od
.out
.result
;
946 if (!NT_STATUS_IS_OK(status
)) {
947 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
948 "samr_OpenDomain for [%s] failed: %s",
949 r
->samr
.in
.domain_name
, nt_errstr(status
));
953 /* prepare samr_LookupNames */
954 ln
.in
.domain_handle
= &d_handle
;
956 ln
.in
.names
= talloc_array(mem_ctx
, struct lsa_String
, 1);
958 ln
.out
.types
= &types
;
960 r
->samr
.out
.error_string
= "Out of Memory";
961 return NT_STATUS_NO_MEMORY
;
963 ln
.in
.names
[0].string
= r
->samr
.in
.account_name
;
965 /* 5. do a samr_LookupNames to get the users rid */
966 status
= dcerpc_samr_LookupNames_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &ln
);
967 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(ln
.out
.result
)) {
968 status
= ln
.out
.result
;
970 if (!NT_STATUS_IS_OK(status
)) {
971 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
972 "samr_LookupNames for [%s] failed: %s",
973 r
->samr
.in
.account_name
, nt_errstr(status
));
977 /* check if we got one RID for the user */
978 if (ln
.out
.rids
->count
!= 1) {
979 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
980 "samr_LookupNames for [%s] returns %d RIDs",
981 r
->samr
.in
.account_name
, ln
.out
.rids
->count
);
982 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
986 if (ln
.out
.types
->count
!= 1) {
987 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
988 "samr_LookupNames for [%s] returns %d RID TYPEs",
989 r
->samr
.in
.account_name
, ln
.out
.types
->count
);
990 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
994 /* prepare samr_OpenUser */
995 ZERO_STRUCT(u_handle
);
996 ou
.in
.domain_handle
= &d_handle
;
997 ou
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
998 ou
.in
.rid
= ln
.out
.rids
->ids
[0];
999 ou
.out
.user_handle
= &u_handle
;
1001 /* 6. do a samr_OpenUser to get a user handle */
1002 status
= dcerpc_samr_OpenUser_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &ou
);
1003 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(ou
.out
.result
)) {
1004 status
= ou
.out
.result
;
1006 if (!NT_STATUS_IS_OK(status
)) {
1007 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
1008 "samr_OpenUser for [%s] failed: %s",
1009 r
->samr
.in
.account_name
, nt_errstr(status
));
1014 r2
.samr_handle
.level
= LIBNET_SET_PASSWORD_SAMR_HANDLE
;
1015 r2
.samr_handle
.samr_level
= r
->samr
.samr_level
;
1016 r2
.samr_handle
.in
.account_name
= r
->samr
.in
.account_name
;
1017 r2
.samr_handle
.in
.newpassword
= r
->samr
.in
.newpassword
;
1018 r2
.samr_handle
.in
.user_handle
= &u_handle
;
1019 r2
.samr_handle
.in
.dcerpc_pipe
= c
.out
.dcerpc_pipe
;
1020 r2
.samr_handle
.in
.info21
= NULL
;
1022 status
= libnet_SetPassword(ctx
, mem_ctx
, &r2
);
1024 r
->generic
.out
.error_string
= r2
.samr_handle
.out
.error_string
;
1027 /* close connection */
1028 talloc_unlink(ctx
, c
.out
.dcerpc_pipe
);
1033 static NTSTATUS
libnet_SetPassword_generic(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
1036 union libnet_SetPassword r2
;
1039 r2
.samr
.level
= LIBNET_SET_PASSWORD_SAMR
;
1040 r2
.samr
.samr_level
= r
->generic
.samr_level
;
1041 r2
.samr
.in
.account_name
= r
->generic
.in
.account_name
;
1042 r2
.samr
.in
.domain_name
= r
->generic
.in
.domain_name
;
1043 r2
.samr
.in
.newpassword
= r
->generic
.in
.newpassword
;
1045 r
->generic
.out
.error_string
= "Unknown Error";
1046 status
= libnet_SetPassword(ctx
, mem_ctx
, &r2
);
1048 r
->generic
.out
.error_string
= r2
.samr
.out
.error_string
;
1053 NTSTATUS
libnet_SetPassword(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
1055 enum smb_encryption_setting encryption_state
=
1056 cli_credentials_get_smb_encryption(ctx
->cred
);
1057 NTSTATUS status
= NT_STATUS_INVALID_LEVEL
;
1059 switch (r
->generic
.level
) {
1060 case LIBNET_SET_PASSWORD_GENERIC
:
1061 status
= libnet_SetPassword_generic(ctx
, mem_ctx
, r
);
1063 case LIBNET_SET_PASSWORD_SAMR
:
1064 status
= libnet_SetPassword_samr(ctx
, mem_ctx
, r
);
1066 case LIBNET_SET_PASSWORD_SAMR_HANDLE
:
1067 status
= libnet_SetPassword_samr_handle(ctx
, mem_ctx
, r
);
1069 case LIBNET_SET_PASSWORD_SAMR_HANDLE_26
:
1070 if (encryption_state
== SMB_ENCRYPTION_REQUIRED
) {
1071 GNUTLS_FIPS140_SET_LAX_MODE();
1073 status
= libnet_SetPassword_samr_handle_26(ctx
, mem_ctx
, r
);
1075 case LIBNET_SET_PASSWORD_SAMR_HANDLE_25
:
1076 if (encryption_state
== SMB_ENCRYPTION_REQUIRED
) {
1077 GNUTLS_FIPS140_SET_LAX_MODE();
1079 status
= libnet_SetPassword_samr_handle_25(ctx
, mem_ctx
, r
);
1081 case LIBNET_SET_PASSWORD_SAMR_HANDLE_24
:
1082 if (encryption_state
== SMB_ENCRYPTION_REQUIRED
) {
1083 GNUTLS_FIPS140_SET_LAX_MODE();
1085 status
= libnet_SetPassword_samr_handle_24(ctx
, mem_ctx
, r
);
1087 case LIBNET_SET_PASSWORD_SAMR_HANDLE_23
:
1088 if (encryption_state
== SMB_ENCRYPTION_REQUIRED
) {
1089 GNUTLS_FIPS140_SET_LAX_MODE();
1091 status
= libnet_SetPassword_samr_handle_23(ctx
, mem_ctx
, r
);
1093 case LIBNET_SET_PASSWORD_SAMR_HANDLE_18
:
1094 if (encryption_state
== SMB_ENCRYPTION_REQUIRED
) {
1095 GNUTLS_FIPS140_SET_LAX_MODE();
1097 status
= libnet_SetPassword_samr_handle_18(ctx
, mem_ctx
, r
);
1099 case LIBNET_SET_PASSWORD_KRB5
:
1100 status
= NT_STATUS_NOT_IMPLEMENTED
;
1102 case LIBNET_SET_PASSWORD_LDAP
:
1103 status
= NT_STATUS_NOT_IMPLEMENTED
;
1105 case LIBNET_SET_PASSWORD_RAP
:
1106 status
= NT_STATUS_NOT_IMPLEMENTED
;
1110 GNUTLS_FIPS140_SET_STRICT_MODE();