s4:librpc/rpc: don't do async requests if gensec doesn't support async replies (bug...
[Samba/gebeck_regimport.git] / source4 / rpc_server / samr / samr_password.c
blob8963b0436eb484bb4edeb00838a9c6dce897163d
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);
91 if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
92 return NT_STATUS_WRONG_PASSWORD;
96 /* decrypt and check the new nt hash */
97 D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
98 D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
99 if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
100 return NT_STATUS_WRONG_PASSWORD;
103 /* The NT Cross is not required by Win2k3 R2, but if present
104 check the nt cross hash */
105 if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
106 D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
107 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
108 return NT_STATUS_WRONG_PASSWORD;
112 /* The LM Cross is not required by Win2k3 R2, but if present
113 check the lm cross hash */
114 if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
115 D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
116 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
117 return NT_STATUS_WRONG_PASSWORD;
121 /* Start a SAM with user privileges for the password change */
122 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
123 dce_call->conn->dce_ctx->lp_ctx,
124 dce_call->conn->auth_state.session_info, 0);
125 if (sam_ctx == NULL) {
126 return NT_STATUS_INVALID_SYSTEM_SERVICE;
129 /* Start transaction */
130 ret = ldb_transaction_start(sam_ctx);
131 if (ret != LDB_SUCCESS) {
132 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
133 return NT_STATUS_TRANSACTION_ABORTED;
136 /* Performs the password modification. We pass the old hashes read out
137 * from the database since they were already checked against the user-
138 * provided ones. */
139 status = samdb_set_password(sam_ctx, mem_ctx,
140 a_state->account_dn,
141 a_state->domain_state->domain_dn,
142 NULL, &new_lmPwdHash, &new_ntPwdHash,
143 lm_pwd, nt_pwd, /* this is a user password change */
144 NULL,
145 NULL);
146 if (!NT_STATUS_IS_OK(status)) {
147 ldb_transaction_cancel(sam_ctx);
148 return status;
151 /* And this confirms it in a transaction commit */
152 ret = ldb_transaction_commit(sam_ctx);
153 if (ret != LDB_SUCCESS) {
154 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
155 ldb_dn_get_linearized(a_state->account_dn),
156 ldb_errstring(sam_ctx)));
157 return NT_STATUS_TRANSACTION_ABORTED;
160 return NT_STATUS_OK;
164 samr_OemChangePasswordUser2
166 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
167 TALLOC_CTX *mem_ctx,
168 struct samr_OemChangePasswordUser2 *r)
170 NTSTATUS status;
171 DATA_BLOB new_password, new_unicode_password;
172 char *new_pass;
173 struct samr_CryptPassword *pwbuf = r->in.password;
174 struct ldb_context *sam_ctx;
175 struct ldb_dn *user_dn;
176 int ret;
177 struct ldb_message **res;
178 const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
179 struct samr_Password *lm_pwd;
180 DATA_BLOB lm_pwd_blob;
181 uint8_t new_lm_hash[16];
182 struct samr_Password lm_verifier;
183 size_t unicode_pw_len;
184 size_t converted_size = 0;
186 if (pwbuf == NULL) {
187 return NT_STATUS_INVALID_PARAMETER;
190 if (r->in.hash == NULL) {
191 return NT_STATUS_INVALID_PARAMETER;
194 /* this call can only work with lanman auth */
195 if (!lpcfg_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
196 return NT_STATUS_WRONG_PASSWORD;
199 /* Connect to a SAMDB with system privileges for fetching the old pw
200 * hashes. */
201 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
202 dce_call->conn->dce_ctx->lp_ctx,
203 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
204 if (sam_ctx == NULL) {
205 return NT_STATUS_INVALID_SYSTEM_SERVICE;
208 /* we need the users dn and the domain dn (derived from the
209 user SID). We also need the current lm password hash in
210 order to decrypt the incoming password */
211 ret = gendb_search(sam_ctx,
212 mem_ctx, NULL, &res, attrs,
213 "(&(sAMAccountName=%s)(objectclass=user))",
214 r->in.account->string);
215 if (ret != 1) {
216 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
217 return NT_STATUS_WRONG_PASSWORD;
220 user_dn = res[0]->dn;
222 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
223 res[0], &lm_pwd, NULL);
224 if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
225 return NT_STATUS_WRONG_PASSWORD;
228 /* decrypt the password we have been given */
229 lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
230 arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
231 data_blob_free(&lm_pwd_blob);
233 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
234 DEBUG(3,("samr: failed to decode password buffer\n"));
235 return NT_STATUS_WRONG_PASSWORD;
238 if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
239 CH_DOS, CH_UNIX,
240 (const char *)new_password.data,
241 new_password.length,
242 (void **)&new_pass, &converted_size)) {
243 DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
244 return NT_STATUS_WRONG_PASSWORD;
247 if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
248 CH_DOS, CH_UTF16,
249 (const char *)new_password.data,
250 new_password.length,
251 (void **)&new_unicode_password.data, &unicode_pw_len)) {
252 DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
253 return NT_STATUS_WRONG_PASSWORD;
255 new_unicode_password.length = unicode_pw_len;
257 E_deshash(new_pass, new_lm_hash);
258 E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
259 if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
260 return NT_STATUS_WRONG_PASSWORD;
263 /* Connect to a SAMDB with user privileges for the password change */
264 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
265 dce_call->conn->dce_ctx->lp_ctx,
266 dce_call->conn->auth_state.session_info, 0);
267 if (sam_ctx == NULL) {
268 return NT_STATUS_INVALID_SYSTEM_SERVICE;
271 /* Start transaction */
272 ret = ldb_transaction_start(sam_ctx);
273 if (ret != LDB_SUCCESS) {
274 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
275 return NT_STATUS_TRANSACTION_ABORTED;
278 /* Performs the password modification. We pass the old hashes read out
279 * from the database since they were already checked against the user-
280 * provided ones. */
281 status = samdb_set_password(sam_ctx, mem_ctx,
282 user_dn, NULL,
283 &new_unicode_password,
284 NULL, NULL,
285 lm_pwd, NULL, /* this is a user password change */
286 NULL,
287 NULL);
288 if (!NT_STATUS_IS_OK(status)) {
289 ldb_transaction_cancel(sam_ctx);
290 return status;
293 /* And this confirms it in a transaction commit */
294 ret = ldb_transaction_commit(sam_ctx);
295 if (ret != LDB_SUCCESS) {
296 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
297 ldb_dn_get_linearized(user_dn),
298 ldb_errstring(sam_ctx)));
299 return NT_STATUS_TRANSACTION_ABORTED;
302 return NT_STATUS_OK;
307 samr_ChangePasswordUser3
309 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
310 TALLOC_CTX *mem_ctx,
311 struct samr_ChangePasswordUser3 *r)
313 NTSTATUS status;
314 DATA_BLOB new_password;
315 struct ldb_context *sam_ctx = NULL;
316 struct ldb_dn *user_dn;
317 int ret;
318 struct ldb_message **res;
319 const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
320 struct samr_Password *nt_pwd, *lm_pwd;
321 DATA_BLOB nt_pwd_blob;
322 struct samr_DomInfo1 *dominfo = NULL;
323 struct userPwdChangeFailureInformation *reject = NULL;
324 enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
325 uint8_t new_nt_hash[16], new_lm_hash[16];
326 struct samr_Password nt_verifier, lm_verifier;
328 *r->out.dominfo = NULL;
329 *r->out.reject = NULL;
331 if (r->in.nt_password == NULL ||
332 r->in.nt_verifier == NULL) {
333 return NT_STATUS_INVALID_PARAMETER;
336 /* Connect to a SAMDB with system privileges for fetching the old pw
337 * hashes. */
338 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
339 dce_call->conn->dce_ctx->lp_ctx,
340 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
341 if (sam_ctx == NULL) {
342 return NT_STATUS_INVALID_SYSTEM_SERVICE;
345 /* we need the users dn and the domain dn (derived from the
346 user SID). We also need the current lm and nt password hashes
347 in order to decrypt the incoming passwords */
348 ret = gendb_search(sam_ctx,
349 mem_ctx, NULL, &res, attrs,
350 "(&(sAMAccountName=%s)(objectclass=user))",
351 r->in.account->string);
352 if (ret != 1) {
353 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
354 status = NT_STATUS_WRONG_PASSWORD;
355 goto failed;
358 user_dn = res[0]->dn;
360 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
361 res[0], &lm_pwd, &nt_pwd);
362 if (!NT_STATUS_IS_OK(status) ) {
363 goto failed;
366 if (!nt_pwd) {
367 status = NT_STATUS_WRONG_PASSWORD;
368 goto failed;
371 /* decrypt the password we have been given */
372 nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
373 arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
374 data_blob_free(&nt_pwd_blob);
376 if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
377 DEBUG(3,("samr: failed to decode password buffer\n"));
378 status = NT_STATUS_WRONG_PASSWORD;
379 goto failed;
382 if (r->in.nt_verifier == NULL) {
383 status = NT_STATUS_WRONG_PASSWORD;
384 goto failed;
387 /* check NT verifier */
388 mdfour(new_nt_hash, new_password.data, new_password.length);
390 E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
391 if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
392 status = NT_STATUS_WRONG_PASSWORD;
393 goto failed;
396 /* check LM verifier (really not needed as we just checked the
397 * much stronger NT hash, but the RPC-SAMR test checks for
398 * this) */
399 if (lm_pwd && r->in.lm_verifier != NULL) {
400 char *new_pass;
401 size_t converted_size = 0;
403 if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
404 CH_UTF16, CH_UNIX,
405 (const char *)new_password.data,
406 new_password.length,
407 (void **)&new_pass, &converted_size)) {
408 E_deshash(new_pass, new_lm_hash);
409 E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
410 if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
411 status = NT_STATUS_WRONG_PASSWORD;
412 goto failed;
417 /* Connect to a SAMDB with user privileges for the password change */
418 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
419 dce_call->conn->dce_ctx->lp_ctx,
420 dce_call->conn->auth_state.session_info, 0);
421 if (sam_ctx == NULL) {
422 return NT_STATUS_INVALID_SYSTEM_SERVICE;
425 ret = ldb_transaction_start(sam_ctx);
426 if (ret != LDB_SUCCESS) {
427 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
428 return NT_STATUS_TRANSACTION_ABORTED;
431 /* Performs the password modification. We pass the old hashes read out
432 * from the database since they were already checked against the user-
433 * provided ones. */
434 status = samdb_set_password(sam_ctx, mem_ctx,
435 user_dn, NULL,
436 &new_password,
437 NULL, NULL,
438 lm_pwd, nt_pwd, /* this is a user password change */
439 &reason,
440 &dominfo);
442 if (!NT_STATUS_IS_OK(status)) {
443 ldb_transaction_cancel(sam_ctx);
444 goto failed;
447 /* And this confirms it in a transaction commit */
448 ret = ldb_transaction_commit(sam_ctx);
449 if (ret != LDB_SUCCESS) {
450 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
451 ldb_dn_get_linearized(user_dn),
452 ldb_errstring(sam_ctx)));
453 status = NT_STATUS_TRANSACTION_ABORTED;
454 goto failed;
457 return NT_STATUS_OK;
459 failed:
460 reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
461 if (reject != NULL) {
462 reject->extendedFailureReason = reason;
464 *r->out.reject = reject;
467 *r->out.dominfo = dominfo;
469 return status;
474 samr_ChangePasswordUser2
476 easy - just a subset of samr_ChangePasswordUser3
478 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
479 TALLOC_CTX *mem_ctx,
480 struct samr_ChangePasswordUser2 *r)
482 struct samr_ChangePasswordUser3 r2;
483 struct samr_DomInfo1 *dominfo = NULL;
484 struct userPwdChangeFailureInformation *reject = NULL;
486 r2.in.server = r->in.server;
487 r2.in.account = r->in.account;
488 r2.in.nt_password = r->in.nt_password;
489 r2.in.nt_verifier = r->in.nt_verifier;
490 r2.in.lm_change = r->in.lm_change;
491 r2.in.lm_password = r->in.lm_password;
492 r2.in.lm_verifier = r->in.lm_verifier;
493 r2.in.password3 = NULL;
494 r2.out.dominfo = &dominfo;
495 r2.out.reject = &reject;
497 return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
502 set password via a samr_CryptPassword buffer
504 NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
505 struct ldb_context *sam_ctx,
506 struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
507 TALLOC_CTX *mem_ctx,
508 struct samr_CryptPassword *pwbuf)
510 NTSTATUS nt_status;
511 DATA_BLOB new_password;
512 DATA_BLOB session_key = data_blob(NULL, 0);
514 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
515 if (!NT_STATUS_IS_OK(nt_status)) {
516 return nt_status;
519 arcfour_crypt_blob(pwbuf->data, 516, &session_key);
521 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
522 DEBUG(3,("samr: failed to decode password buffer\n"));
523 return NT_STATUS_WRONG_PASSWORD;
526 /* set the password - samdb needs to know both the domain and user DNs,
527 so the domain password policy can be used */
528 return samdb_set_password(sam_ctx, mem_ctx,
529 account_dn, domain_dn,
530 &new_password,
531 NULL, NULL,
532 NULL, NULL, /* This is a password set, not change */
533 NULL, NULL);
538 set password via a samr_CryptPasswordEx buffer
540 NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
541 struct ldb_context *sam_ctx,
542 struct ldb_dn *account_dn,
543 struct ldb_dn *domain_dn,
544 TALLOC_CTX *mem_ctx,
545 struct samr_CryptPasswordEx *pwbuf)
547 NTSTATUS nt_status;
548 DATA_BLOB new_password;
549 DATA_BLOB co_session_key;
550 DATA_BLOB session_key = data_blob(NULL, 0);
551 struct MD5Context ctx;
553 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
554 if (!NT_STATUS_IS_OK(nt_status)) {
555 return nt_status;
558 co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
559 if (!co_session_key.data) {
560 return NT_STATUS_NO_MEMORY;
563 MD5Init(&ctx);
564 MD5Update(&ctx, &pwbuf->data[516], 16);
565 MD5Update(&ctx, session_key.data, session_key.length);
566 MD5Final(co_session_key.data, &ctx);
568 arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
570 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
571 DEBUG(3,("samr: failed to decode password buffer\n"));
572 return NT_STATUS_WRONG_PASSWORD;
575 /* set the password - samdb needs to know both the domain and user DNs,
576 so the domain password policy can be used */
577 return samdb_set_password(sam_ctx, mem_ctx,
578 account_dn, domain_dn,
579 &new_password,
580 NULL, NULL,
581 NULL, NULL, /* This is a password set, not change */
582 NULL, NULL);
586 set password via encrypted NT and LM hash buffers
588 NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call,
589 struct ldb_context *sam_ctx,
590 struct ldb_dn *account_dn,
591 struct ldb_dn *domain_dn,
592 TALLOC_CTX *mem_ctx,
593 const uint8_t *lm_pwd_hash,
594 const uint8_t *nt_pwd_hash)
596 struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL;
597 DATA_BLOB session_key = data_blob(NULL, 0);
598 DATA_BLOB in, out;
599 NTSTATUS nt_status = NT_STATUS_OK;
601 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
602 if (!NT_STATUS_IS_OK(nt_status)) {
603 return nt_status;
606 if (lm_pwd_hash != NULL) {
607 in = data_blob_const(lm_pwd_hash, 16);
608 out = data_blob_talloc_zero(mem_ctx, 16);
610 sess_crypt_blob(&out, &in, &session_key, false);
612 d_lm_pwd_hash = (struct samr_Password *) out.data;
614 if (nt_pwd_hash != NULL) {
615 in = data_blob_const(nt_pwd_hash, 16);
616 out = data_blob_talloc_zero(mem_ctx, 16);
618 sess_crypt_blob(&out, &in, &session_key, false);
620 d_nt_pwd_hash = (struct samr_Password *) out.data;
623 if ((d_lm_pwd_hash != NULL) || (d_nt_pwd_hash != NULL)) {
624 nt_status = samdb_set_password(sam_ctx, mem_ctx, account_dn,
625 domain_dn, NULL,
626 d_lm_pwd_hash, d_nt_pwd_hash,
627 NULL, NULL, /* this is a password set */
628 NULL, NULL);
631 return nt_status;