librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/vl.git] / source4 / rpc_server / samr / samr_password.c
blob5caf4b9e97e0d2c68af53feb8f73645472de229c
1 /*
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/>.
23 #include "includes.h"
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,
38 TALLOC_CTX *mem_ctx,
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;
45 int ret;
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);
53 a_state = h->data;
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
60 present */
61 return NT_STATUS_INVALID_PARAMETER_MIX;
64 /* Connect to a SAMDB with system privileges for fetching the old pw
65 * hashes. */
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);
76 if (ret != 1) {
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 */
88 if (lm_pwd) {
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-
126 * provided ones. */
127 status = samdb_set_password(sam_ctx, mem_ctx,
128 a_state->account_dn,
129 a_state->domain_state->domain_dn,
130 NULL, &new_lmPwdHash, &new_ntPwdHash,
131 lm_pwd, nt_pwd, /* this is a user password change */
132 NULL,
133 NULL);
134 if (!NT_STATUS_IS_OK(status)) {
135 ldb_transaction_cancel(sam_ctx);
136 return status;
139 /* decrypt and check the new lm hash */
140 if (lm_pwd) {
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;
179 return NT_STATUS_OK;
183 samr_OemChangePasswordUser2
185 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
186 TALLOC_CTX *mem_ctx,
187 struct samr_OemChangePasswordUser2 *r)
189 NTSTATUS status;
190 DATA_BLOB new_password, new_unicode_password;
191 char *new_pass;
192 struct samr_CryptPassword *pwbuf = r->in.password;
193 struct ldb_context *sam_ctx;
194 struct ldb_dn *user_dn;
195 int ret;
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;
205 if (pwbuf == NULL) {
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
219 * hashes. */
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);
234 if (ret != 1) {
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),
258 CH_DOS, CH_UNIX,
259 (const char *)new_password.data,
260 new_password.length,
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),
267 CH_DOS, CH_UTF16,
268 (const char *)new_password.data,
269 new_password.length,
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-
296 * provided ones. */
297 status = samdb_set_password(sam_ctx, mem_ctx,
298 user_dn, NULL,
299 &new_unicode_password,
300 NULL, NULL,
301 lm_pwd, NULL, /* this is a user password change */
302 NULL,
303 NULL);
304 if (!NT_STATUS_IS_OK(status)) {
305 ldb_transaction_cancel(sam_ctx);
306 return status;
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;
323 return NT_STATUS_OK;
328 samr_ChangePasswordUser3
330 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
331 TALLOC_CTX *mem_ctx,
332 struct samr_ChangePasswordUser3 *r)
334 NTSTATUS status;
335 DATA_BLOB new_password;
336 struct ldb_context *sam_ctx = NULL;
337 struct ldb_dn *user_dn;
338 int ret;
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
358 * hashes. */
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);
373 if (ret != 1) {
374 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
375 status = NT_STATUS_WRONG_PASSWORD;
376 goto failed;
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) ) {
384 goto failed;
387 if (!nt_pwd) {
388 status = NT_STATUS_WRONG_PASSWORD;
389 goto failed;
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;
400 goto failed;
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-
419 * provided ones. */
420 status = samdb_set_password(sam_ctx, mem_ctx,
421 user_dn, NULL,
422 &new_password,
423 NULL, NULL,
424 lm_pwd, nt_pwd, /* this is a user password change */
425 &reason,
426 &dominfo);
428 if (!NT_STATUS_IS_OK(status)) {
429 ldb_transaction_cancel(sam_ctx);
430 goto failed;
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;
440 goto failed;
443 /* check LM verifier (really not needed as we just checked the
444 * much stronger NT hash, but the RPC-SAMR test checks for
445 * this) */
446 if (lm_pwd && r->in.lm_verifier != NULL) {
447 char *new_pass;
448 size_t converted_size = 0;
450 if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
451 CH_UTF16, CH_UNIX,
452 (const char *)new_password.data,
453 new_password.length,
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;
460 goto failed;
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;
472 goto failed;
475 return NT_STATUS_OK;
477 failed:
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;
487 return status;
492 samr_ChangePasswordUser2
494 easy - just a subset of samr_ChangePasswordUser3
496 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
497 TALLOC_CTX *mem_ctx,
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,
525 TALLOC_CTX *mem_ctx,
526 struct samr_CryptPassword *pwbuf)
528 NTSTATUS nt_status;
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)) {
534 return 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,
548 &new_password,
549 NULL, NULL,
550 NULL, NULL, /* This is a password set, not change */
551 NULL, NULL);
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,
562 TALLOC_CTX *mem_ctx,
563 struct samr_CryptPasswordEx *pwbuf)
565 NTSTATUS nt_status;
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)) {
573 return 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;
581 MD5Init(&ctx);
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,
597 &new_password,
598 NULL, NULL,
599 NULL, NULL, /* This is a password set, not change */
600 NULL, NULL);
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,
610 TALLOC_CTX *mem_ctx,
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);
616 DATA_BLOB in, out;
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)) {
621 return 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,
643 domain_dn, NULL,
644 d_lm_pwd_hash, d_nt_pwd_hash,
645 NULL, NULL, /* this is a password set */
646 NULL, NULL);
649 return nt_status;