2 Unix SMB/CIFS implementation.
4 samr server password set/change handling
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "rpc_server/dcerpc_server.h"
25 #include "rpc_server/common/common.h"
26 #include "rpc_server/samr/dcesrv_samr.h"
27 #include "system/time.h"
28 #include "lib/crypto/md4.h"
29 #include "dsdb/common/util.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "auth/auth.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "../lib/util/util_ldb.h"
34 #include "rpc_server/samr/proto.h"
35 #include "auth/auth_sam.h"
36 #include "lib/param/loadparm.h"
37 #include "librpc/rpc/dcerpc_helper.h"
38 #include "librpc/rpc/dcerpc_samr.h"
40 #include "lib/crypto/gnutls_helpers.h"
41 #include <gnutls/gnutls.h>
42 #include <gnutls/crypto.h>
44 static void log_password_change_event(struct imessaging_context
*msg_ctx
,
45 struct loadparm_context
*lp_ctx
,
46 const struct tsocket_address
*remote_client_address
,
47 const struct tsocket_address
*local_server_address
,
48 const char *auth_description
,
49 const char *password_type
,
50 const char *original_client_name
,
51 const char *account_name_from_db
,
56 * Forcing this via the NTLM auth structure is not ideal, but
57 * it is the most practical option right now, and ensures the
58 * logs are consistent, even if some elements are always NULL.
60 struct auth_usersupplied_info ui
= {
63 .account_name
= original_client_name
,
64 .domain_name
= lpcfg_sam_name(lp_ctx
),
67 .account_name
= account_name_from_db
,
68 .domain_name
= lpcfg_sam_name(lp_ctx
),
70 .remote_host
= remote_client_address
,
71 .local_host
= local_server_address
,
72 .service_description
= "SAMR Password Change",
73 .auth_description
= auth_description
,
74 .password_type
= password_type
,
77 log_authentication_event(msg_ctx
,
82 ui
.mapped
.domain_name
,
83 ui
.mapped
.account_name
,
87 samr_ChangePasswordUser
89 So old it is just not worth implementing
90 because it does not supply a plaintext and so we can't do password
91 complexity checking and cannot update all the other password hashes.
94 NTSTATUS
dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state
*dce_call
,
96 struct samr_ChangePasswordUser
*r
)
98 return NT_STATUS_NOT_IMPLEMENTED
;
102 samr_OemChangePasswordUser2
104 No longer implemented as it requires the LM hash
106 NTSTATUS
dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state
*dce_call
,
108 struct samr_OemChangePasswordUser2
*r
)
110 return NT_STATUS_NOT_IMPLEMENTED
;
114 samr_ChangePasswordUser4
116 NTSTATUS
dcesrv_samr_ChangePasswordUser4(struct dcesrv_call_state
*dce_call
,
118 struct samr_ChangePasswordUser4
*r
)
120 #ifdef HAVE_GNUTLS_PBKDF2
121 struct ldb_context
*sam_ctx
= NULL
;
122 struct ldb_message
**ldb_res
= NULL
;
123 const char *const attrs
[] = {"unicodePwd",
125 "userAccountControl",
127 "msDS-User-Account-Control-Computed",
132 struct ldb_dn
*dn
= NULL
;
133 const char *samAccountName
= NULL
;
134 struct dom_sid
*objectSid
= NULL
;
135 struct samr_Password
*nt_pwd
= NULL
;
136 gnutls_datum_t nt_key
;
137 gnutls_datum_t salt
= {
138 .data
= r
->in
.password
->salt
,
139 .size
= sizeof(r
->in
.password
->salt
),
141 uint8_t cdk_data
[16] = {0};
144 .length
= sizeof(cdk_data
),
146 NTSTATUS status
= NT_STATUS_WRONG_PASSWORD
;
149 r
->out
.result
= NT_STATUS_WRONG_PASSWORD
;
151 if (r
->in
.password
== NULL
) {
152 return NT_STATUS_INVALID_PARAMETER
;
155 if (r
->in
.password
->PBKDF2Iterations
< 5000 ||
156 r
->in
.password
->PBKDF2Iterations
> 1000000) {
157 return NT_STATUS_INVALID_PARAMETER
;
160 * Connect to a SAMDB with system privileges for fetching the old
163 sam_ctx
= samdb_connect(mem_ctx
,
165 dce_call
->conn
->dce_ctx
->lp_ctx
,
166 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
),
167 dce_call
->conn
->remote_address
,
169 if (sam_ctx
== NULL
) {
170 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
173 rc
= ldb_transaction_start(sam_ctx
);
174 if (rc
!= LDB_SUCCESS
) {
175 DBG_WARNING("Failed to start transaction: %s\n",
176 ldb_errstring(sam_ctx
));
177 return NT_STATUS_TRANSACTION_ABORTED
;
181 * We need the users dn and the domain dn (derived from the user SID).
182 * We also need the current lm and nt password hashes in order to
183 * decrypt the incoming passwords.
191 "(&(sAMAccountName=%s)(objectclass=user))",
192 ldb_binary_encode_string(mem_ctx
, r
->in
.account
->string
));
194 /* Will be converted to WRONG_PASSWORD below */
195 ldb_transaction_cancel(sam_ctx
);
196 DBG_WARNING("Unable to find account: %s",
197 r
->in
.account
->string
);
198 status
= NT_STATUS_NO_SUCH_USER
;
204 ldb_msg_find_attr_as_string(ldb_res
[0], "samAccountName", NULL
);
205 objectSid
= samdb_result_dom_sid(ldb_res
, ldb_res
[0], "objectSid");
207 status
= samdb_result_passwords(mem_ctx
,
208 dce_call
->conn
->dce_ctx
->lp_ctx
,
211 if (!NT_STATUS_IS_OK(status
)) {
212 ldb_transaction_cancel(sam_ctx
);
216 if (nt_pwd
== NULL
) {
217 ldb_transaction_cancel(sam_ctx
);
218 status
= NT_STATUS_WRONG_PASSWORD
;
222 nt_key
= (gnutls_datum_t
){
223 .data
= nt_pwd
->hash
,
224 .size
= sizeof(nt_pwd
->hash
),
227 rc
= gnutls_pbkdf2(GNUTLS_MAC_SHA512
,
230 r
->in
.password
->PBKDF2Iterations
,
234 ldb_transaction_cancel(sam_ctx
);
235 status
= NT_STATUS_WRONG_PASSWORD
;
239 status
= samr_set_password_aes(dce_call
,
247 if (!NT_STATUS_IS_OK(status
)) {
248 ldb_transaction_cancel(sam_ctx
);
249 status
= NT_STATUS_WRONG_PASSWORD
;
253 /* And this confirms it in a transaction commit */
254 rc
= ldb_transaction_commit(sam_ctx
);
255 if (rc
!= LDB_SUCCESS
) {
256 DBG_WARNING("Failed to commit transaction to change password "
258 ldb_dn_get_linearized(dn
),
259 ldb_errstring(sam_ctx
));
260 status
= NT_STATUS_TRANSACTION_ABORTED
;
264 status
= NT_STATUS_OK
;
267 struct imessaging_context
*imsg_ctx
=
268 dcesrv_imessaging_context(dce_call
->conn
);
270 log_password_change_event(imsg_ctx
,
271 dce_call
->conn
->dce_ctx
->lp_ctx
,
272 dce_call
->conn
->remote_address
,
273 dce_call
->conn
->local_address
,
274 "samr_ChangePasswordUser4",
275 "AES using NTLM-hash",
276 r
->in
.account
->string
,
282 /* Only update the badPwdCount if we found the user */
283 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
284 authsam_update_bad_pwd_count(sam_ctx
,
286 ldb_get_default_basedn(sam_ctx
));
287 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
289 * Don't give the game away: (don't allow anonymous users to
290 * prove the existence of usernames)
292 status
= NT_STATUS_WRONG_PASSWORD
;
296 #else /* HAVE_GNUTLS_PBKDF2 */
297 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
298 #endif /* HAVE_GNUTLS_PBKDF2 */
302 samr_ChangePasswordUser3
304 NTSTATUS
dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state
*dce_call
,
306 struct samr_ChangePasswordUser3
*r
)
308 struct imessaging_context
*imsg_ctx
=
309 dcesrv_imessaging_context(dce_call
->conn
);
310 NTSTATUS status
= NT_STATUS_WRONG_PASSWORD
;
311 DATA_BLOB new_password
;
312 struct ldb_context
*sam_ctx
= NULL
;
313 struct ldb_dn
*user_dn
= NULL
;
315 struct ldb_message
*msg
= NULL
;
316 struct samr_Password
*nt_pwd
;
317 struct samr_DomInfo1
*dominfo
= NULL
;
318 struct userPwdChangeFailureInformation
*reject
= NULL
;
319 enum samPwdChangeReason reason
= SAM_PWD_CHANGE_NO_ERROR
;
320 uint8_t new_nt_hash
[16];
321 struct samr_Password nt_verifier
;
322 const char *user_samAccountName
= NULL
;
323 struct dom_sid
*user_objectSid
= NULL
;
324 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
325 enum ntlm_auth_level ntlm_auth_level
326 = lpcfg_ntlm_auth(lp_ctx
);
327 gnutls_cipher_hd_t cipher_hnd
= NULL
;
328 gnutls_datum_t nt_session_key
;
331 *r
->out
.dominfo
= NULL
;
332 *r
->out
.reject
= NULL
;
334 /* this call should be disabled without NTLM auth */
335 if (ntlm_auth_level
== NTLM_AUTH_DISABLED
) {
336 DBG_WARNING("NTLM password changes not"
337 "permitted by configuration.\n");
338 return NT_STATUS_NTLM_BLOCKED
;
341 if (r
->in
.nt_password
== NULL
||
342 r
->in
.nt_verifier
== NULL
) {
343 return NT_STATUS_INVALID_PARAMETER
;
346 /* Connect to a SAMDB with system privileges for fetching the old pw
348 sam_ctx
= dcesrv_samdb_connect_as_system(mem_ctx
, dce_call
);
349 if (sam_ctx
== NULL
) {
350 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
354 * We use authsam_search_account() to be consistent with the
355 * other callers in the bad password and audit log handling
356 * systems. It ensures we get DSDB_SEARCH_SHOW_EXTENDED_DN.
358 status
= authsam_search_account(mem_ctx
,
360 r
->in
.account
->string
,
361 ldb_get_default_basedn(sam_ctx
),
363 if (!NT_STATUS_IS_OK(status
)) {
368 user_samAccountName
= ldb_msg_find_attr_as_string(msg
, "samAccountName", NULL
);
369 user_objectSid
= samdb_result_dom_sid(mem_ctx
, msg
, "objectSid");
371 status
= samdb_result_passwords(mem_ctx
, lp_ctx
,
373 if (!NT_STATUS_IS_OK(status
) ) {
378 status
= NT_STATUS_WRONG_PASSWORD
;
382 /* decrypt the password we have been given */
383 nt_session_key
= (gnutls_datum_t
) {
384 .data
= nt_pwd
->hash
,
385 .size
= sizeof(nt_pwd
->hash
),
388 rc
= gnutls_cipher_init(&cipher_hnd
,
389 GNUTLS_CIPHER_ARCFOUR_128
,
393 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
397 rc
= gnutls_cipher_decrypt(cipher_hnd
,
398 r
->in
.nt_password
->data
,
400 gnutls_cipher_deinit(cipher_hnd
);
402 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
406 if (!extract_pw_from_buffer(mem_ctx
, r
->in
.nt_password
->data
, &new_password
)) {
407 DEBUG(3,("samr: failed to decode password buffer\n"));
408 status
= NT_STATUS_WRONG_PASSWORD
;
412 if (r
->in
.nt_verifier
== NULL
) {
413 status
= NT_STATUS_WRONG_PASSWORD
;
417 /* check NT verifier */
418 mdfour(new_nt_hash
, new_password
.data
, new_password
.length
);
420 rc
= E_old_pw_hash(new_nt_hash
, nt_pwd
->hash
, nt_verifier
.hash
);
422 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
425 if (!mem_equal_const_time(nt_verifier
.hash
, r
->in
.nt_verifier
->hash
, 16)) {
426 status
= NT_STATUS_WRONG_PASSWORD
;
430 /* Connect to a SAMDB with user privileges for the password change */
431 sam_ctx
= dcesrv_samdb_connect_as_user(mem_ctx
, dce_call
);
432 if (sam_ctx
== NULL
) {
433 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
436 ret
= ldb_transaction_start(sam_ctx
);
437 if (ret
!= LDB_SUCCESS
) {
438 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx
)));
439 return NT_STATUS_TRANSACTION_ABORTED
;
442 /* Performs the password modification. We pass the old hashes read out
443 * from the database since they were already checked against the user-
445 status
= samdb_set_password(sam_ctx
, mem_ctx
,
449 DSDB_PASSWORD_CHECKED_AND_CORRECT
,
453 if (!NT_STATUS_IS_OK(status
)) {
454 ldb_transaction_cancel(sam_ctx
);
458 /* And this confirms it in a transaction commit */
459 ret
= ldb_transaction_commit(sam_ctx
);
460 if (ret
!= LDB_SUCCESS
) {
461 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
462 ldb_dn_get_linearized(user_dn
),
463 ldb_errstring(sam_ctx
)));
464 status
= NT_STATUS_TRANSACTION_ABORTED
;
468 status
= NT_STATUS_OK
;
472 log_password_change_event(imsg_ctx
,
474 dce_call
->conn
->remote_address
,
475 dce_call
->conn
->local_address
,
476 "samr_ChangePasswordUser3",
477 "RC4/DES using NTLM-hash",
478 r
->in
.account
->string
,
482 if (NT_STATUS_IS_OK(status
)) {
486 /* Only update the badPwdCount if we found the user */
487 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
488 NTSTATUS bad_pwd_status
= authsam_update_bad_pwd_count(
489 sam_ctx
, msg
, ldb_get_default_basedn(sam_ctx
));
490 if (NT_STATUS_EQUAL(bad_pwd_status
, NT_STATUS_ACCOUNT_LOCKED_OUT
)) {
491 status
= bad_pwd_status
;
493 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
494 /* Don't give the game away: (don't allow anonymous users to prove the existence of usernames) */
495 status
= NT_STATUS_WRONG_PASSWORD
;
498 reject
= talloc_zero(mem_ctx
, struct userPwdChangeFailureInformation
);
499 if (reject
!= NULL
) {
500 reject
->extendedFailureReason
= reason
;
502 *r
->out
.reject
= reject
;
505 *r
->out
.dominfo
= dominfo
;
511 samr_ChangePasswordUser2
513 easy - just a subset of samr_ChangePasswordUser3
515 NTSTATUS
dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state
*dce_call
,
517 struct samr_ChangePasswordUser2
*r
)
519 struct samr_ChangePasswordUser3 r2
;
520 struct samr_DomInfo1
*dominfo
= NULL
;
521 struct userPwdChangeFailureInformation
*reject
= NULL
;
523 r2
.in
.server
= r
->in
.server
;
524 r2
.in
.account
= r
->in
.account
;
525 r2
.in
.nt_password
= r
->in
.nt_password
;
526 r2
.in
.nt_verifier
= r
->in
.nt_verifier
;
527 r2
.in
.lm_change
= r
->in
.lm_change
;
528 r2
.in
.lm_password
= r
->in
.lm_password
;
529 r2
.in
.lm_verifier
= r
->in
.lm_verifier
;
530 r2
.in
.password3
= NULL
;
531 r2
.out
.dominfo
= &dominfo
;
532 r2
.out
.reject
= &reject
;
534 return dcesrv_samr_ChangePasswordUser3(dce_call
, mem_ctx
, &r2
);
539 set password via a samr_CryptPassword buffer
541 NTSTATUS
samr_set_password(struct dcesrv_call_state
*dce_call
,
542 struct ldb_context
*sam_ctx
,
543 struct ldb_dn
*account_dn
, struct ldb_dn
*domain_dn
,
545 struct samr_CryptPassword
*pwbuf
)
548 DATA_BLOB new_password
;
549 DATA_BLOB session_key
= data_blob(NULL
, 0);
550 gnutls_cipher_hd_t cipher_hnd
= NULL
;
551 gnutls_datum_t _session_key
;
552 struct auth_session_info
*session_info
=
553 dcesrv_call_session_info(dce_call
);
554 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
558 encrypted
= dcerpc_is_transport_encrypted(session_info
);
559 if (lpcfg_weak_crypto(lp_ctx
) == SAMBA_WEAK_CRYPTO_DISALLOWED
&&
561 return NT_STATUS_ACCESS_DENIED
;
564 nt_status
= dcesrv_transport_session_key(dce_call
, &session_key
);
565 if (!NT_STATUS_IS_OK(nt_status
)) {
566 DBG_NOTICE("samr: failed to get session key: %s\n",
567 nt_errstr(nt_status
));
571 _session_key
= (gnutls_datum_t
) {
572 .data
= session_key
.data
,
573 .size
= session_key
.length
,
577 * This is safe to support as we only have a session key
578 * over a SMB connection which we force to be encrypted.
580 GNUTLS_FIPS140_SET_LAX_MODE();
581 rc
= gnutls_cipher_init(&cipher_hnd
,
582 GNUTLS_CIPHER_ARCFOUR_128
,
586 GNUTLS_FIPS140_SET_STRICT_MODE();
587 nt_status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
591 rc
= gnutls_cipher_decrypt(cipher_hnd
,
594 gnutls_cipher_deinit(cipher_hnd
);
595 GNUTLS_FIPS140_SET_STRICT_MODE();
597 nt_status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
601 if (!extract_pw_from_buffer(mem_ctx
, pwbuf
->data
, &new_password
)) {
602 DEBUG(3,("samr: failed to decode password buffer\n"));
603 return NT_STATUS_WRONG_PASSWORD
;
606 /* set the password - samdb needs to know both the domain and user DNs,
607 so the domain password policy can be used */
608 nt_status
= samdb_set_password(sam_ctx
,
623 set password via a samr_CryptPasswordEx buffer
625 NTSTATUS
samr_set_password_ex(struct dcesrv_call_state
*dce_call
,
626 struct ldb_context
*sam_ctx
,
627 struct ldb_dn
*account_dn
,
628 struct ldb_dn
*domain_dn
,
630 struct samr_CryptPasswordEx
*pwbuf
)
632 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
633 struct auth_session_info
*session_info
=
634 dcesrv_call_session_info(dce_call
);
636 DATA_BLOB new_password
;
638 /* The confounder is in the last 16 bytes of the buffer */
639 DATA_BLOB confounder
= data_blob_const(&pwbuf
->data
[516], 16);
640 DATA_BLOB pw_data
= data_blob_const(pwbuf
->data
, 516);
641 DATA_BLOB session_key
= data_blob(NULL
, 0);
645 nt_status
= dcesrv_transport_session_key(dce_call
, &session_key
);
646 if (!NT_STATUS_IS_OK(nt_status
)) {
647 DEBUG(3,("samr: failed to get session key: %s "
648 "=> NT_STATUS_WRONG_PASSWORD\n",
649 nt_errstr(nt_status
)));
650 return NT_STATUS_WRONG_PASSWORD
;
653 encrypted
= dcerpc_is_transport_encrypted(session_info
);
654 if (lpcfg_weak_crypto(lp_ctx
) == SAMBA_WEAK_CRYPTO_DISALLOWED
&&
656 return NT_STATUS_ACCESS_DENIED
;
659 GNUTLS_FIPS140_SET_LAX_MODE();
660 rc
= samba_gnutls_arcfour_confounded_md5(&confounder
,
663 SAMBA_GNUTLS_DECRYPT
);
664 GNUTLS_FIPS140_SET_STRICT_MODE();
666 nt_status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
670 if (!extract_pw_from_buffer(mem_ctx
, pwbuf
->data
, &new_password
)) {
671 DEBUG(3,("samr: failed to decode password buffer\n"));
672 nt_status
= NT_STATUS_WRONG_PASSWORD
;
676 /* set the password - samdb needs to know both the domain and user DNs,
677 so the domain password policy can be used */
678 nt_status
= samdb_set_password(sam_ctx
,
687 ZERO_ARRAY_LEN(new_password
.data
,
688 new_password
.length
);
695 set password via encrypted NT and LM hash buffers
697 NTSTATUS
samr_set_password_buffers(struct dcesrv_call_state
*dce_call
,
698 struct ldb_context
*sam_ctx
,
699 struct ldb_dn
*account_dn
,
700 struct ldb_dn
*domain_dn
,
702 const uint8_t *lm_pwd_hash
,
703 const uint8_t *nt_pwd_hash
)
705 struct samr_Password
*d_lm_pwd_hash
= NULL
, *d_nt_pwd_hash
= NULL
;
706 uint8_t random_session_key
[16] = { 0, };
707 DATA_BLOB session_key
= data_blob(NULL
, 0);
709 NTSTATUS nt_status
= NT_STATUS_OK
;
712 nt_status
= dcesrv_transport_session_key(dce_call
, &session_key
);
713 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_USER_SESSION_KEY
)) {
714 DEBUG(3,("samr: failed to get session key: %s "
715 "=> use a random session key\n",
716 nt_errstr(nt_status
)));
719 * Windows just uses a random key
721 generate_random_buffer(random_session_key
,
722 sizeof(random_session_key
));
723 session_key
= data_blob_const(random_session_key
,
724 sizeof(random_session_key
));
725 nt_status
= NT_STATUS_OK
;
727 if (!NT_STATUS_IS_OK(nt_status
)) {
731 if (nt_pwd_hash
!= NULL
) {
732 in
= data_blob_const(nt_pwd_hash
, 16);
733 out
= data_blob_talloc_zero(mem_ctx
, 16);
735 rc
= sess_crypt_blob(&out
, &in
, &session_key
, SAMBA_GNUTLS_DECRYPT
);
737 return gnutls_error_to_ntstatus(rc
,
738 NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
741 d_nt_pwd_hash
= (struct samr_Password
*) out
.data
;
744 if ((d_lm_pwd_hash
!= NULL
) || (d_nt_pwd_hash
!= NULL
)) {
745 nt_status
= samdb_set_password(sam_ctx
, mem_ctx
, account_dn
,
755 NTSTATUS
samr_set_password_aes(struct dcesrv_call_state
*dce_call
,
757 const DATA_BLOB
*cdk
,
758 struct ldb_context
*sam_ctx
,
759 struct ldb_dn
*account_dn
,
760 struct ldb_dn
*domain_dn
,
761 struct samr_EncryptedPasswordAES
*pwbuf
)
763 DATA_BLOB pw_data
= data_blob_null
;
764 DATA_BLOB new_password
= data_blob_null
;
765 const DATA_BLOB ciphertext
=
766 data_blob_const(pwbuf
->cipher
, pwbuf
->cipher_len
);
767 DATA_BLOB iv
= data_blob_const(pwbuf
->salt
, sizeof(pwbuf
->salt
));
768 NTSTATUS nt_status
= NT_STATUS_OK
;
771 nt_status
= samba_gnutls_aead_aes_256_cbc_hmac_sha512_decrypt(
775 &samr_aes256_enc_key_salt
,
776 &samr_aes256_mac_key_salt
,
780 if (!NT_STATUS_IS_OK(nt_status
)) {
781 return NT_STATUS_WRONG_PASSWORD
;
784 ok
= extract_pwd_blob_from_buffer514(mem_ctx
,
787 TALLOC_FREE(pw_data
.data
);
789 DBG_NOTICE("samr: failed to decode password buffer\n");
790 return NT_STATUS_WRONG_PASSWORD
;
793 nt_status
= samdb_set_password(sam_ctx
,
802 TALLOC_FREE(new_password
.data
);