s4/heimdal_build: use GetTimeOfDay macro instead of gettimeofday
[Samba/ita.git] / source4 / rpc_server / samr / samr_password.c
blob73ccff48cd430e1c40b2152b458503b0e76f11a9
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"
33 /*
34 samr_ChangePasswordUser
36 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
37 TALLOC_CTX *mem_ctx,
38 struct samr_ChangePasswordUser *r)
40 struct dcesrv_handle *h;
41 struct samr_account_state *a_state;
42 struct ldb_context *sam_ctx;
43 struct ldb_message **res;
44 int ret;
45 struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
46 struct samr_Password *lm_pwd, *nt_pwd;
47 NTSTATUS status = NT_STATUS_OK;
48 const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };
50 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
52 a_state = h->data;
54 /* basic sanity checking on parameters. Do this before any database ops */
55 if (!r->in.lm_present || !r->in.nt_present ||
56 !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
57 !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
58 /* we should really handle a change with lm not
59 present */
60 return NT_STATUS_INVALID_PARAMETER_MIX;
63 /* Connect to a SAMDB with system privileges for fetching the old pw
64 * hashes. */
65 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
66 dce_call->conn->dce_ctx->lp_ctx,
67 system_session(dce_call->conn->dce_ctx->lp_ctx));
68 if (sam_ctx == NULL) {
69 return NT_STATUS_INVALID_SYSTEM_SERVICE;
72 /* fetch the old hashes */
73 ret = gendb_search_dn(sam_ctx, mem_ctx,
74 a_state->account_dn, &res, attrs);
75 if (ret != 1) {
76 return NT_STATUS_WRONG_PASSWORD;
79 status = samdb_result_passwords(mem_ctx,
80 dce_call->conn->dce_ctx->lp_ctx,
81 res[0], &lm_pwd, &nt_pwd);
82 if (!NT_STATUS_IS_OK(status) || !nt_pwd) {
83 return NT_STATUS_WRONG_PASSWORD;
86 /* decrypt and check the new lm hash */
87 if (lm_pwd) {
88 D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
89 D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
90 if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
91 return NT_STATUS_WRONG_PASSWORD;
95 /* decrypt and check the new nt hash */
96 D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
97 D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
98 if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
99 return NT_STATUS_WRONG_PASSWORD;
102 /* The NT Cross is not required by Win2k3 R2, but if present
103 check the nt cross hash */
104 if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
105 D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
106 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
107 return NT_STATUS_WRONG_PASSWORD;
111 /* The LM Cross is not required by Win2k3 R2, but if present
112 check the lm cross hash */
113 if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
114 D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
115 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
116 return NT_STATUS_WRONG_PASSWORD;
120 /* Start a SAM with user privileges for the password change */
121 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
122 dce_call->conn->dce_ctx->lp_ctx,
123 dce_call->conn->auth_state.session_info);
124 if (sam_ctx == NULL) {
125 return NT_STATUS_INVALID_SYSTEM_SERVICE;
128 /* Start transaction */
129 ret = ldb_transaction_start(sam_ctx);
130 if (ret != LDB_SUCCESS) {
131 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
132 return NT_STATUS_TRANSACTION_ABORTED;
135 /* Performs the password modification. We pass the old hashes read out
136 * from the database since they were already checked against the user-
137 * provided ones. */
138 status = samdb_set_password(sam_ctx, mem_ctx,
139 a_state->account_dn,
140 a_state->domain_state->domain_dn,
141 NULL, &new_lmPwdHash, &new_ntPwdHash,
142 lm_pwd, nt_pwd, /* this is a user password change */
143 NULL,
144 NULL);
145 if (!NT_STATUS_IS_OK(status)) {
146 ldb_transaction_cancel(sam_ctx);
147 return status;
150 /* And this confirms it in a transaction commit */
151 ret = ldb_transaction_commit(sam_ctx);
152 if (ret != LDB_SUCCESS) {
153 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
154 ldb_dn_get_linearized(a_state->account_dn),
155 ldb_errstring(sam_ctx)));
156 return NT_STATUS_TRANSACTION_ABORTED;
159 return NT_STATUS_OK;
163 samr_OemChangePasswordUser2
165 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
166 TALLOC_CTX *mem_ctx,
167 struct samr_OemChangePasswordUser2 *r)
169 NTSTATUS status;
170 DATA_BLOB new_password, new_unicode_password;
171 char *new_pass;
172 struct samr_CryptPassword *pwbuf = r->in.password;
173 struct ldb_context *sam_ctx;
174 struct ldb_dn *user_dn;
175 int ret;
176 struct ldb_message **res;
177 const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
178 struct samr_Password *lm_pwd;
179 DATA_BLOB lm_pwd_blob;
180 uint8_t new_lm_hash[16];
181 struct samr_Password lm_verifier;
182 size_t unicode_pw_len;
184 if (pwbuf == NULL) {
185 return NT_STATUS_INVALID_PARAMETER;
188 if (r->in.hash == NULL) {
189 return NT_STATUS_INVALID_PARAMETER;
192 /* this call can only work with lanman auth */
193 if (!lpcfg_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
194 return NT_STATUS_WRONG_PASSWORD;
197 /* Connect to a SAMDB with system privileges for fetching the old pw
198 * hashes. */
199 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
200 dce_call->conn->dce_ctx->lp_ctx,
201 system_session(dce_call->conn->dce_ctx->lp_ctx));
202 if (sam_ctx == NULL) {
203 return NT_STATUS_INVALID_SYSTEM_SERVICE;
206 /* we need the users dn and the domain dn (derived from the
207 user SID). We also need the current lm password hash in
208 order to decrypt the incoming password */
209 ret = gendb_search(sam_ctx,
210 mem_ctx, NULL, &res, attrs,
211 "(&(sAMAccountName=%s)(objectclass=user))",
212 r->in.account->string);
213 if (ret != 1) {
214 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
215 return NT_STATUS_WRONG_PASSWORD;
218 user_dn = res[0]->dn;
220 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
221 res[0], &lm_pwd, NULL);
222 if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
223 return NT_STATUS_WRONG_PASSWORD;
226 /* decrypt the password we have been given */
227 lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
228 arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
229 data_blob_free(&lm_pwd_blob);
231 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
232 DEBUG(3,("samr: failed to decode password buffer\n"));
233 return NT_STATUS_WRONG_PASSWORD;
236 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
237 CH_DOS, CH_UNIX,
238 (const char *)new_password.data,
239 new_password.length,
240 (void **)&new_pass, NULL, false)) {
241 DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
242 return NT_STATUS_WRONG_PASSWORD;
245 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
246 CH_DOS, CH_UTF16,
247 (const char *)new_password.data,
248 new_password.length,
249 (void **)&new_unicode_password.data, &unicode_pw_len, false)) {
250 DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
251 return NT_STATUS_WRONG_PASSWORD;
253 new_unicode_password.length = unicode_pw_len;
255 E_deshash(new_pass, new_lm_hash);
256 E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
257 if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
258 return NT_STATUS_WRONG_PASSWORD;
261 /* Connect to a SAMDB with user privileges for the password change */
262 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
263 dce_call->conn->dce_ctx->lp_ctx,
264 dce_call->conn->auth_state.session_info);
265 if (sam_ctx == NULL) {
266 return NT_STATUS_INVALID_SYSTEM_SERVICE;
269 /* Start transaction */
270 ret = ldb_transaction_start(sam_ctx);
271 if (ret != LDB_SUCCESS) {
272 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
273 return NT_STATUS_TRANSACTION_ABORTED;
276 /* Performs the password modification. We pass the old hashes read out
277 * from the database since they were already checked against the user-
278 * provided ones. */
279 status = samdb_set_password(sam_ctx, mem_ctx,
280 user_dn, NULL,
281 &new_unicode_password,
282 NULL, NULL,
283 lm_pwd, NULL, /* this is a user password change */
284 NULL,
285 NULL);
286 if (!NT_STATUS_IS_OK(status)) {
287 ldb_transaction_cancel(sam_ctx);
288 return status;
291 /* And this confirms it in a transaction commit */
292 ret = ldb_transaction_commit(sam_ctx);
293 if (ret != LDB_SUCCESS) {
294 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
295 ldb_dn_get_linearized(user_dn),
296 ldb_errstring(sam_ctx)));
297 return NT_STATUS_TRANSACTION_ABORTED;
300 return NT_STATUS_OK;
305 samr_ChangePasswordUser3
307 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
308 TALLOC_CTX *mem_ctx,
309 struct samr_ChangePasswordUser3 *r)
311 NTSTATUS status;
312 DATA_BLOB new_password;
313 struct ldb_context *sam_ctx = NULL;
314 struct ldb_dn *user_dn;
315 int ret;
316 struct ldb_message **res;
317 const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
318 struct samr_Password *nt_pwd, *lm_pwd;
319 DATA_BLOB nt_pwd_blob;
320 struct samr_DomInfo1 *dominfo = NULL;
321 struct userPwdChangeFailureInformation *reject = NULL;
322 enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
323 uint8_t new_nt_hash[16], new_lm_hash[16];
324 struct samr_Password nt_verifier, lm_verifier;
326 *r->out.dominfo = NULL;
327 *r->out.reject = NULL;
329 if (r->in.nt_password == NULL ||
330 r->in.nt_verifier == NULL) {
331 return NT_STATUS_INVALID_PARAMETER;
334 /* Connect to a SAMDB with system privileges for fetching the old pw
335 * hashes. */
336 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
337 dce_call->conn->dce_ctx->lp_ctx,
338 system_session(dce_call->conn->dce_ctx->lp_ctx));
339 if (sam_ctx == NULL) {
340 return NT_STATUS_INVALID_SYSTEM_SERVICE;
343 /* we need the users dn and the domain dn (derived from the
344 user SID). We also need the current lm and nt password hashes
345 in order to decrypt the incoming passwords */
346 ret = gendb_search(sam_ctx,
347 mem_ctx, NULL, &res, attrs,
348 "(&(sAMAccountName=%s)(objectclass=user))",
349 r->in.account->string);
350 if (ret != 1) {
351 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
352 status = NT_STATUS_WRONG_PASSWORD;
353 goto failed;
356 user_dn = res[0]->dn;
358 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
359 res[0], &lm_pwd, &nt_pwd);
360 if (!NT_STATUS_IS_OK(status) ) {
361 goto failed;
364 if (!nt_pwd) {
365 status = NT_STATUS_WRONG_PASSWORD;
366 goto failed;
369 /* decrypt the password we have been given */
370 nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
371 arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
372 data_blob_free(&nt_pwd_blob);
374 if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
375 DEBUG(3,("samr: failed to decode password buffer\n"));
376 status = NT_STATUS_WRONG_PASSWORD;
377 goto failed;
380 if (r->in.nt_verifier == NULL) {
381 status = NT_STATUS_WRONG_PASSWORD;
382 goto failed;
385 /* check NT verifier */
386 mdfour(new_nt_hash, new_password.data, new_password.length);
388 E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
389 if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
390 status = NT_STATUS_WRONG_PASSWORD;
391 goto failed;
394 /* check LM verifier (really not needed as we just checked the
395 * much stronger NT hash, but the RPC-SAMR test checks for
396 * this) */
397 if (lm_pwd && r->in.lm_verifier != NULL) {
398 char *new_pass;
399 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
400 CH_UTF16, CH_UNIX,
401 (const char *)new_password.data,
402 new_password.length,
403 (void **)&new_pass, NULL, false)) {
404 E_deshash(new_pass, new_lm_hash);
405 E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
406 if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
407 status = NT_STATUS_WRONG_PASSWORD;
408 goto failed;
413 /* Connect to a SAMDB with user privileges for the password change */
414 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
415 dce_call->conn->dce_ctx->lp_ctx,
416 dce_call->conn->auth_state.session_info);
417 if (sam_ctx == NULL) {
418 return NT_STATUS_INVALID_SYSTEM_SERVICE;
421 ret = ldb_transaction_start(sam_ctx);
422 if (ret != LDB_SUCCESS) {
423 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
424 return NT_STATUS_TRANSACTION_ABORTED;
427 /* Performs the password modification. We pass the old hashes read out
428 * from the database since they were already checked against the user-
429 * provided ones. */
430 status = samdb_set_password(sam_ctx, mem_ctx,
431 user_dn, NULL,
432 &new_password,
433 NULL, NULL,
434 lm_pwd, nt_pwd, /* this is a user password change */
435 &reason,
436 &dominfo);
438 if (!NT_STATUS_IS_OK(status)) {
439 ldb_transaction_cancel(sam_ctx);
440 goto failed;
443 /* And this confirms it in a transaction commit */
444 ret = ldb_transaction_commit(sam_ctx);
445 if (ret != LDB_SUCCESS) {
446 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
447 ldb_dn_get_linearized(user_dn),
448 ldb_errstring(sam_ctx)));
449 status = NT_STATUS_TRANSACTION_ABORTED;
450 goto failed;
453 return NT_STATUS_OK;
455 failed:
456 reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
457 if (reject != NULL) {
458 reject->extendedFailureReason = reason;
460 *r->out.reject = reject;
463 *r->out.dominfo = dominfo;
465 return status;
470 samr_ChangePasswordUser2
472 easy - just a subset of samr_ChangePasswordUser3
474 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
475 TALLOC_CTX *mem_ctx,
476 struct samr_ChangePasswordUser2 *r)
478 struct samr_ChangePasswordUser3 r2;
479 struct samr_DomInfo1 *dominfo = NULL;
480 struct userPwdChangeFailureInformation *reject = NULL;
482 r2.in.server = r->in.server;
483 r2.in.account = r->in.account;
484 r2.in.nt_password = r->in.nt_password;
485 r2.in.nt_verifier = r->in.nt_verifier;
486 r2.in.lm_change = r->in.lm_change;
487 r2.in.lm_password = r->in.lm_password;
488 r2.in.lm_verifier = r->in.lm_verifier;
489 r2.in.password3 = NULL;
490 r2.out.dominfo = &dominfo;
491 r2.out.reject = &reject;
493 return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
498 set password via a samr_CryptPassword buffer
500 NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
501 struct ldb_context *sam_ctx,
502 struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
503 TALLOC_CTX *mem_ctx,
504 struct samr_CryptPassword *pwbuf)
506 NTSTATUS nt_status;
507 DATA_BLOB new_password;
508 DATA_BLOB session_key = data_blob(NULL, 0);
510 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
511 if (!NT_STATUS_IS_OK(nt_status)) {
512 return nt_status;
515 arcfour_crypt_blob(pwbuf->data, 516, &session_key);
517 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
518 DEBUG(3,("samr: failed to decode password buffer\n"));
519 return NT_STATUS_WRONG_PASSWORD;
522 /* set the password - samdb needs to know both the domain and user DNs,
523 so the domain password policy can be used */
524 return samdb_set_password(sam_ctx, mem_ctx,
525 account_dn, domain_dn,
526 &new_password,
527 NULL, NULL,
528 NULL, NULL, /* This is a password set, not change */
529 NULL, NULL);
534 set password via a samr_CryptPasswordEx buffer
536 NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
537 struct ldb_context *sam_ctx,
538 struct ldb_dn *account_dn,
539 struct ldb_dn *domain_dn,
540 TALLOC_CTX *mem_ctx,
541 struct samr_CryptPasswordEx *pwbuf)
543 NTSTATUS nt_status;
544 DATA_BLOB new_password;
545 DATA_BLOB co_session_key;
546 DATA_BLOB session_key = data_blob(NULL, 0);
547 struct MD5Context ctx;
549 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
550 if (!NT_STATUS_IS_OK(nt_status)) {
551 return nt_status;
554 co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
555 if (!co_session_key.data) {
556 return NT_STATUS_NO_MEMORY;
559 MD5Init(&ctx);
560 MD5Update(&ctx, &pwbuf->data[516], 16);
561 MD5Update(&ctx, session_key.data, session_key.length);
562 MD5Final(co_session_key.data, &ctx);
564 arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
566 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
567 DEBUG(3,("samr: failed to decode password buffer\n"));
568 return NT_STATUS_WRONG_PASSWORD;
571 /* set the password - samdb needs to know both the domain and user DNs,
572 so the domain password policy can be used */
573 return samdb_set_password(sam_ctx, mem_ctx,
574 account_dn, domain_dn,
575 &new_password,
576 NULL, NULL,
577 NULL, NULL, /* This is a password set, not change */
578 NULL, NULL);
582 set password via encrypted NT and LM hash buffers
584 NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call,
585 struct ldb_context *sam_ctx,
586 struct ldb_dn *account_dn,
587 struct ldb_dn *domain_dn,
588 TALLOC_CTX *mem_ctx,
589 const uint8_t *lm_pwd_hash,
590 const uint8_t *nt_pwd_hash)
592 struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL;
593 DATA_BLOB session_key = data_blob(NULL, 0);
594 DATA_BLOB in, out;
595 NTSTATUS nt_status = NT_STATUS_OK;
597 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
598 if (!NT_STATUS_IS_OK(nt_status)) {
599 return nt_status;
602 if (lm_pwd_hash != NULL) {
603 in = data_blob_const(lm_pwd_hash, 16);
604 out = data_blob_talloc_zero(mem_ctx, 16);
606 sess_crypt_blob(&out, &in, &session_key, false);
608 d_lm_pwd_hash = (struct samr_Password *) out.data;
610 if (nt_pwd_hash != NULL) {
611 in = data_blob_const(nt_pwd_hash, 16);
612 out = data_blob_talloc_zero(mem_ctx, 16);
614 sess_crypt_blob(&out, &in, &session_key, false);
616 d_nt_pwd_hash = (struct samr_Password *) out.data;
619 if ((d_lm_pwd_hash != NULL) || (d_nt_pwd_hash != NULL)) {
620 nt_status = samdb_set_password(sam_ctx, mem_ctx, account_dn,
621 domain_dn, NULL,
622 d_lm_pwd_hash, d_nt_pwd_hash,
623 NULL, NULL, /* this is a password set */
624 NULL, NULL);
627 return nt_status;