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/samr/dcesrv_samr.h"
26 #include "system/time.h"
27 #include "../lib/crypto/crypto.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "auth/auth.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "../lib/util/util_ldb.h"
32 #include "rpc_server/samr/proto.h"
35 samr_ChangePasswordUser
37 NTSTATUS
dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state
*dce_call
,
39 struct samr_ChangePasswordUser
*r
)
41 struct dcesrv_handle
*h
;
42 struct samr_account_state
*a_state
;
43 struct ldb_context
*sam_ctx
;
44 struct ldb_message
**res
;
46 struct samr_Password new_lmPwdHash
, new_ntPwdHash
, checkHash
;
47 struct samr_Password
*lm_pwd
, *nt_pwd
;
48 NTSTATUS status
= NT_STATUS_OK
;
49 const char * const attrs
[] = { "dBCSPwd", "unicodePwd" , NULL
};
51 DCESRV_PULL_HANDLE(h
, r
->in
.user_handle
, SAMR_HANDLE_USER
);
55 /* basic sanity checking on parameters. Do this before any database ops */
56 if (!r
->in
.lm_present
|| !r
->in
.nt_present
||
57 !r
->in
.old_lm_crypted
|| !r
->in
.new_lm_crypted
||
58 !r
->in
.old_nt_crypted
|| !r
->in
.new_nt_crypted
) {
59 /* we should really handle a change with lm not
61 return NT_STATUS_INVALID_PARAMETER_MIX
;
64 /* Connect to a SAMDB with system privileges for fetching the old pw
66 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
67 dce_call
->conn
->dce_ctx
->lp_ctx
,
68 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
69 if (sam_ctx
== NULL
) {
70 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
73 /* fetch the old hashes */
74 ret
= gendb_search_dn(sam_ctx
, mem_ctx
,
75 a_state
->account_dn
, &res
, attrs
);
77 return NT_STATUS_WRONG_PASSWORD
;
80 status
= samdb_result_passwords(mem_ctx
,
81 dce_call
->conn
->dce_ctx
->lp_ctx
,
82 res
[0], &lm_pwd
, &nt_pwd
);
83 if (!NT_STATUS_IS_OK(status
) || !nt_pwd
) {
84 return NT_STATUS_WRONG_PASSWORD
;
87 /* decrypt and check the new lm hash */
89 D_P16(lm_pwd
->hash
, r
->in
.new_lm_crypted
->hash
, new_lmPwdHash
.hash
);
90 D_P16(new_lmPwdHash
.hash
, r
->in
.old_lm_crypted
->hash
, checkHash
.hash
);
93 /* decrypt and check the new nt hash */
94 D_P16(nt_pwd
->hash
, r
->in
.new_nt_crypted
->hash
, new_ntPwdHash
.hash
);
95 D_P16(new_ntPwdHash
.hash
, r
->in
.old_nt_crypted
->hash
, checkHash
.hash
);
97 /* The NT Cross is not required by Win2k3 R2, but if present
98 check the nt cross hash */
99 if (r
->in
.cross1_present
&& r
->in
.nt_cross
&& lm_pwd
) {
100 D_P16(lm_pwd
->hash
, r
->in
.nt_cross
->hash
, checkHash
.hash
);
103 /* The LM Cross is not required by Win2k3 R2, but if present
104 check the lm cross hash */
105 if (r
->in
.cross2_present
&& r
->in
.lm_cross
&& lm_pwd
) {
106 D_P16(nt_pwd
->hash
, r
->in
.lm_cross
->hash
, checkHash
.hash
);
109 /* Start a SAM with user privileges for the password change */
110 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
111 dce_call
->conn
->dce_ctx
->lp_ctx
,
112 dce_call
->conn
->auth_state
.session_info
, 0);
113 if (sam_ctx
== NULL
) {
114 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
117 /* Start transaction */
118 ret
= ldb_transaction_start(sam_ctx
);
119 if (ret
!= LDB_SUCCESS
) {
120 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx
)));
121 return NT_STATUS_TRANSACTION_ABORTED
;
124 /* Performs the password modification. We pass the old hashes read out
125 * from the database since they were already checked against the user-
127 status
= samdb_set_password(sam_ctx
, mem_ctx
,
129 a_state
->domain_state
->domain_dn
,
130 NULL
, &new_lmPwdHash
, &new_ntPwdHash
,
131 lm_pwd
, nt_pwd
, /* this is a user password change */
134 if (!NT_STATUS_IS_OK(status
)) {
135 ldb_transaction_cancel(sam_ctx
);
139 /* decrypt and check the new lm hash */
141 if (memcmp(checkHash
.hash
, lm_pwd
, 16) != 0) {
142 ldb_transaction_cancel(sam_ctx
);
143 return NT_STATUS_WRONG_PASSWORD
;
147 if (memcmp(checkHash
.hash
, nt_pwd
, 16) != 0) {
148 ldb_transaction_cancel(sam_ctx
);
149 return NT_STATUS_WRONG_PASSWORD
;
152 /* The NT Cross is not required by Win2k3 R2, but if present
153 check the nt cross hash */
154 if (r
->in
.cross1_present
&& r
->in
.nt_cross
&& lm_pwd
) {
155 if (memcmp(checkHash
.hash
, new_ntPwdHash
.hash
, 16) != 0) {
156 ldb_transaction_cancel(sam_ctx
);
157 return NT_STATUS_WRONG_PASSWORD
;
161 /* The LM Cross is not required by Win2k3 R2, but if present
162 check the lm cross hash */
163 if (r
->in
.cross2_present
&& r
->in
.lm_cross
&& lm_pwd
) {
164 if (memcmp(checkHash
.hash
, new_lmPwdHash
.hash
, 16) != 0) {
165 ldb_transaction_cancel(sam_ctx
);
166 return NT_STATUS_WRONG_PASSWORD
;
170 /* And this confirms it in a transaction commit */
171 ret
= ldb_transaction_commit(sam_ctx
);
172 if (ret
!= LDB_SUCCESS
) {
173 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
174 ldb_dn_get_linearized(a_state
->account_dn
),
175 ldb_errstring(sam_ctx
)));
176 return NT_STATUS_TRANSACTION_ABORTED
;
183 samr_OemChangePasswordUser2
185 NTSTATUS
dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state
*dce_call
,
187 struct samr_OemChangePasswordUser2
*r
)
190 DATA_BLOB new_password
, new_unicode_password
;
192 struct samr_CryptPassword
*pwbuf
= r
->in
.password
;
193 struct ldb_context
*sam_ctx
;
194 struct ldb_dn
*user_dn
;
196 struct ldb_message
**res
;
197 const char * const attrs
[] = { "objectSid", "dBCSPwd", NULL
};
198 struct samr_Password
*lm_pwd
;
199 DATA_BLOB lm_pwd_blob
;
200 uint8_t new_lm_hash
[16];
201 struct samr_Password lm_verifier
;
202 size_t unicode_pw_len
;
203 size_t converted_size
= 0;
206 return NT_STATUS_INVALID_PARAMETER
;
209 if (r
->in
.hash
== NULL
) {
210 return NT_STATUS_INVALID_PARAMETER
;
213 /* this call can only work with lanman auth */
214 if (!lpcfg_lanman_auth(dce_call
->conn
->dce_ctx
->lp_ctx
)) {
215 return NT_STATUS_WRONG_PASSWORD
;
218 /* Connect to a SAMDB with system privileges for fetching the old pw
220 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
221 dce_call
->conn
->dce_ctx
->lp_ctx
,
222 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
223 if (sam_ctx
== NULL
) {
224 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
227 /* we need the users dn and the domain dn (derived from the
228 user SID). We also need the current lm password hash in
229 order to decrypt the incoming password */
230 ret
= gendb_search(sam_ctx
,
231 mem_ctx
, NULL
, &res
, attrs
,
232 "(&(sAMAccountName=%s)(objectclass=user))",
233 r
->in
.account
->string
);
235 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
236 return NT_STATUS_WRONG_PASSWORD
;
239 user_dn
= res
[0]->dn
;
241 status
= samdb_result_passwords(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
,
242 res
[0], &lm_pwd
, NULL
);
243 if (!NT_STATUS_IS_OK(status
) || !lm_pwd
) {
244 return NT_STATUS_WRONG_PASSWORD
;
247 /* decrypt the password we have been given */
248 lm_pwd_blob
= data_blob(lm_pwd
->hash
, sizeof(lm_pwd
->hash
));
249 arcfour_crypt_blob(pwbuf
->data
, 516, &lm_pwd_blob
);
250 data_blob_free(&lm_pwd_blob
);
252 if (!extract_pw_from_buffer(mem_ctx
, pwbuf
->data
, &new_password
)) {
253 DEBUG(3,("samr: failed to decode password buffer\n"));
254 return NT_STATUS_WRONG_PASSWORD
;
257 if (!convert_string_talloc_handle(mem_ctx
, lpcfg_iconv_handle(dce_call
->conn
->dce_ctx
->lp_ctx
),
259 (const char *)new_password
.data
,
261 (void **)&new_pass
, &converted_size
)) {
262 DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
263 return NT_STATUS_WRONG_PASSWORD
;
266 if (!convert_string_talloc_handle(mem_ctx
, lpcfg_iconv_handle(dce_call
->conn
->dce_ctx
->lp_ctx
),
268 (const char *)new_password
.data
,
270 (void **)&new_unicode_password
.data
, &unicode_pw_len
)) {
271 DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
272 return NT_STATUS_WRONG_PASSWORD
;
274 new_unicode_password
.length
= unicode_pw_len
;
276 E_deshash(new_pass
, new_lm_hash
);
277 E_old_pw_hash(new_lm_hash
, lm_pwd
->hash
, lm_verifier
.hash
);
279 /* Connect to a SAMDB with user privileges for the password change */
280 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
281 dce_call
->conn
->dce_ctx
->lp_ctx
,
282 dce_call
->conn
->auth_state
.session_info
, 0);
283 if (sam_ctx
== NULL
) {
284 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
287 /* Start transaction */
288 ret
= ldb_transaction_start(sam_ctx
);
289 if (ret
!= LDB_SUCCESS
) {
290 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx
)));
291 return NT_STATUS_TRANSACTION_ABORTED
;
294 /* Performs the password modification. We pass the old hashes read out
295 * from the database since they were already checked against the user-
297 status
= samdb_set_password(sam_ctx
, mem_ctx
,
299 &new_unicode_password
,
301 lm_pwd
, NULL
, /* this is a user password change */
304 if (!NT_STATUS_IS_OK(status
)) {
305 ldb_transaction_cancel(sam_ctx
);
309 if (memcmp(lm_verifier
.hash
, r
->in
.hash
->hash
, 16) != 0) {
310 ldb_transaction_cancel(sam_ctx
);
311 return NT_STATUS_WRONG_PASSWORD
;
314 /* And this confirms it in a transaction commit */
315 ret
= ldb_transaction_commit(sam_ctx
);
316 if (ret
!= LDB_SUCCESS
) {
317 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
318 ldb_dn_get_linearized(user_dn
),
319 ldb_errstring(sam_ctx
)));
320 return NT_STATUS_TRANSACTION_ABORTED
;
328 samr_ChangePasswordUser3
330 NTSTATUS
dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state
*dce_call
,
332 struct samr_ChangePasswordUser3
*r
)
335 DATA_BLOB new_password
;
336 struct ldb_context
*sam_ctx
= NULL
;
337 struct ldb_dn
*user_dn
;
339 struct ldb_message
**res
;
340 const char * const attrs
[] = { "unicodePwd", "dBCSPwd", NULL
};
341 struct samr_Password
*nt_pwd
, *lm_pwd
;
342 DATA_BLOB nt_pwd_blob
;
343 struct samr_DomInfo1
*dominfo
= NULL
;
344 struct userPwdChangeFailureInformation
*reject
= NULL
;
345 enum samPwdChangeReason reason
= SAM_PWD_CHANGE_NO_ERROR
;
346 uint8_t new_nt_hash
[16], new_lm_hash
[16];
347 struct samr_Password nt_verifier
, lm_verifier
;
349 *r
->out
.dominfo
= NULL
;
350 *r
->out
.reject
= NULL
;
352 if (r
->in
.nt_password
== NULL
||
353 r
->in
.nt_verifier
== NULL
) {
354 return NT_STATUS_INVALID_PARAMETER
;
357 /* Connect to a SAMDB with system privileges for fetching the old pw
359 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
360 dce_call
->conn
->dce_ctx
->lp_ctx
,
361 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
362 if (sam_ctx
== NULL
) {
363 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
366 /* we need the users dn and the domain dn (derived from the
367 user SID). We also need the current lm and nt password hashes
368 in order to decrypt the incoming passwords */
369 ret
= gendb_search(sam_ctx
,
370 mem_ctx
, NULL
, &res
, attrs
,
371 "(&(sAMAccountName=%s)(objectclass=user))",
372 r
->in
.account
->string
);
374 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
375 status
= NT_STATUS_WRONG_PASSWORD
;
379 user_dn
= res
[0]->dn
;
381 status
= samdb_result_passwords(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
,
382 res
[0], &lm_pwd
, &nt_pwd
);
383 if (!NT_STATUS_IS_OK(status
) ) {
388 status
= NT_STATUS_WRONG_PASSWORD
;
392 /* decrypt the password we have been given */
393 nt_pwd_blob
= data_blob(nt_pwd
->hash
, sizeof(nt_pwd
->hash
));
394 arcfour_crypt_blob(r
->in
.nt_password
->data
, 516, &nt_pwd_blob
);
395 data_blob_free(&nt_pwd_blob
);
397 if (!extract_pw_from_buffer(mem_ctx
, r
->in
.nt_password
->data
, &new_password
)) {
398 DEBUG(3,("samr: failed to decode password buffer\n"));
399 status
= NT_STATUS_WRONG_PASSWORD
;
403 /* Connect to a SAMDB with user privileges for the password change */
404 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
405 dce_call
->conn
->dce_ctx
->lp_ctx
,
406 dce_call
->conn
->auth_state
.session_info
, 0);
407 if (sam_ctx
== NULL
) {
408 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
411 ret
= ldb_transaction_start(sam_ctx
);
412 if (ret
!= LDB_SUCCESS
) {
413 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx
)));
414 return NT_STATUS_TRANSACTION_ABORTED
;
417 /* Performs the password modification. We pass the old hashes read out
418 * from the database since they were already checked against the user-
420 status
= samdb_set_password(sam_ctx
, mem_ctx
,
424 lm_pwd
, nt_pwd
, /* this is a user password change */
428 if (!NT_STATUS_IS_OK(status
)) {
429 ldb_transaction_cancel(sam_ctx
);
433 /* check NT verifier */
434 mdfour(new_nt_hash
, new_password
.data
, new_password
.length
);
436 E_old_pw_hash(new_nt_hash
, nt_pwd
->hash
, nt_verifier
.hash
);
437 if (memcmp(nt_verifier
.hash
, r
->in
.nt_verifier
->hash
, 16) != 0) {
438 ldb_transaction_cancel(sam_ctx
);
439 status
= NT_STATUS_WRONG_PASSWORD
;
443 /* check LM verifier (really not needed as we just checked the
444 * much stronger NT hash, but the RPC-SAMR test checks for
446 if (lm_pwd
&& r
->in
.lm_verifier
!= NULL
) {
448 size_t converted_size
= 0;
450 if (!convert_string_talloc_handle(mem_ctx
, lpcfg_iconv_handle(dce_call
->conn
->dce_ctx
->lp_ctx
),
452 (const char *)new_password
.data
,
454 (void **)&new_pass
, &converted_size
)) {
455 E_deshash(new_pass
, new_lm_hash
);
456 E_old_pw_hash(new_nt_hash
, lm_pwd
->hash
, lm_verifier
.hash
);
457 if (memcmp(lm_verifier
.hash
, r
->in
.lm_verifier
->hash
, 16) != 0) {
458 ldb_transaction_cancel(sam_ctx
);
459 status
= NT_STATUS_WRONG_PASSWORD
;
465 /* And this confirms it in a transaction commit */
466 ret
= ldb_transaction_commit(sam_ctx
);
467 if (ret
!= LDB_SUCCESS
) {
468 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
469 ldb_dn_get_linearized(user_dn
),
470 ldb_errstring(sam_ctx
)));
471 status
= NT_STATUS_TRANSACTION_ABORTED
;
478 reject
= talloc_zero(mem_ctx
, struct userPwdChangeFailureInformation
);
479 if (reject
!= NULL
) {
480 reject
->extendedFailureReason
= reason
;
482 *r
->out
.reject
= reject
;
485 *r
->out
.dominfo
= dominfo
;
492 samr_ChangePasswordUser2
494 easy - just a subset of samr_ChangePasswordUser3
496 NTSTATUS
dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state
*dce_call
,
498 struct samr_ChangePasswordUser2
*r
)
500 struct samr_ChangePasswordUser3 r2
;
501 struct samr_DomInfo1
*dominfo
= NULL
;
502 struct userPwdChangeFailureInformation
*reject
= NULL
;
504 r2
.in
.server
= r
->in
.server
;
505 r2
.in
.account
= r
->in
.account
;
506 r2
.in
.nt_password
= r
->in
.nt_password
;
507 r2
.in
.nt_verifier
= r
->in
.nt_verifier
;
508 r2
.in
.lm_change
= r
->in
.lm_change
;
509 r2
.in
.lm_password
= r
->in
.lm_password
;
510 r2
.in
.lm_verifier
= r
->in
.lm_verifier
;
511 r2
.in
.password3
= NULL
;
512 r2
.out
.dominfo
= &dominfo
;
513 r2
.out
.reject
= &reject
;
515 return dcesrv_samr_ChangePasswordUser3(dce_call
, mem_ctx
, &r2
);
520 set password via a samr_CryptPassword buffer
522 NTSTATUS
samr_set_password(struct dcesrv_call_state
*dce_call
,
523 struct ldb_context
*sam_ctx
,
524 struct ldb_dn
*account_dn
, struct ldb_dn
*domain_dn
,
526 struct samr_CryptPassword
*pwbuf
)
529 DATA_BLOB new_password
;
530 DATA_BLOB session_key
= data_blob(NULL
, 0);
532 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
533 if (!NT_STATUS_IS_OK(nt_status
)) {
537 arcfour_crypt_blob(pwbuf
->data
, 516, &session_key
);
539 if (!extract_pw_from_buffer(mem_ctx
, pwbuf
->data
, &new_password
)) {
540 DEBUG(3,("samr: failed to decode password buffer\n"));
541 return NT_STATUS_WRONG_PASSWORD
;
544 /* set the password - samdb needs to know both the domain and user DNs,
545 so the domain password policy can be used */
546 return samdb_set_password(sam_ctx
, mem_ctx
,
547 account_dn
, domain_dn
,
550 NULL
, NULL
, /* This is a password set, not change */
556 set password via a samr_CryptPasswordEx buffer
558 NTSTATUS
samr_set_password_ex(struct dcesrv_call_state
*dce_call
,
559 struct ldb_context
*sam_ctx
,
560 struct ldb_dn
*account_dn
,
561 struct ldb_dn
*domain_dn
,
563 struct samr_CryptPasswordEx
*pwbuf
)
566 DATA_BLOB new_password
;
567 DATA_BLOB co_session_key
;
568 DATA_BLOB session_key
= data_blob(NULL
, 0);
569 struct MD5Context ctx
;
571 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
572 if (!NT_STATUS_IS_OK(nt_status
)) {
576 co_session_key
= data_blob_talloc(mem_ctx
, NULL
, 16);
577 if (!co_session_key
.data
) {
578 return NT_STATUS_NO_MEMORY
;
582 MD5Update(&ctx
, &pwbuf
->data
[516], 16);
583 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
584 MD5Final(co_session_key
.data
, &ctx
);
586 arcfour_crypt_blob(pwbuf
->data
, 516, &co_session_key
);
588 if (!extract_pw_from_buffer(mem_ctx
, pwbuf
->data
, &new_password
)) {
589 DEBUG(3,("samr: failed to decode password buffer\n"));
590 return NT_STATUS_WRONG_PASSWORD
;
593 /* set the password - samdb needs to know both the domain and user DNs,
594 so the domain password policy can be used */
595 return samdb_set_password(sam_ctx
, mem_ctx
,
596 account_dn
, domain_dn
,
599 NULL
, NULL
, /* This is a password set, not change */
604 set password via encrypted NT and LM hash buffers
606 NTSTATUS
samr_set_password_buffers(struct dcesrv_call_state
*dce_call
,
607 struct ldb_context
*sam_ctx
,
608 struct ldb_dn
*account_dn
,
609 struct ldb_dn
*domain_dn
,
611 const uint8_t *lm_pwd_hash
,
612 const uint8_t *nt_pwd_hash
)
614 struct samr_Password
*d_lm_pwd_hash
= NULL
, *d_nt_pwd_hash
= NULL
;
615 DATA_BLOB session_key
= data_blob(NULL
, 0);
617 NTSTATUS nt_status
= NT_STATUS_OK
;
619 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
620 if (!NT_STATUS_IS_OK(nt_status
)) {
624 if (lm_pwd_hash
!= NULL
) {
625 in
= data_blob_const(lm_pwd_hash
, 16);
626 out
= data_blob_talloc_zero(mem_ctx
, 16);
628 sess_crypt_blob(&out
, &in
, &session_key
, false);
630 d_lm_pwd_hash
= (struct samr_Password
*) out
.data
;
632 if (nt_pwd_hash
!= NULL
) {
633 in
= data_blob_const(nt_pwd_hash
, 16);
634 out
= data_blob_talloc_zero(mem_ctx
, 16);
636 sess_crypt_blob(&out
, &in
, &session_key
, false);
638 d_nt_pwd_hash
= (struct samr_Password
*) out
.data
;
641 if ((d_lm_pwd_hash
!= NULL
) || (d_nt_pwd_hash
!= NULL
)) {
642 nt_status
= samdb_set_password(sam_ctx
, mem_ctx
, account_dn
,
644 d_lm_pwd_hash
, d_nt_pwd_hash
,
645 NULL
, NULL
, /* this is a password set */