s4:remove "util_ldb" submodule and integrate the three gendb_* calls in "dsdb/common...
[Samba/gebeck_regimport.git] / source4 / rpc_server / samr / samr_password.c
blobbaea71efe9bb2fc6506498b69923437f7c809067
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"
32 /*
33 samr_ChangePasswordUser
35 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
36 TALLOC_CTX *mem_ctx,
37 struct samr_ChangePasswordUser *r)
39 struct dcesrv_handle *h;
40 struct samr_account_state *a_state;
41 struct ldb_context *sam_ctx;
42 struct ldb_message **res;
43 int ret;
44 struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
45 struct samr_Password *lm_pwd, *nt_pwd;
46 NTSTATUS status = NT_STATUS_OK;
47 const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };
49 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
51 a_state = h->data;
53 /* basic sanity checking on parameters. Do this before any database ops */
54 if (!r->in.lm_present || !r->in.nt_present ||
55 !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
56 !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
57 /* we should really handle a change with lm not
58 present */
59 return NT_STATUS_INVALID_PARAMETER_MIX;
62 /* Connect to a SAMDB with system privileges for fetching the old pw
63 * hashes. */
64 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
65 dce_call->conn->dce_ctx->lp_ctx,
66 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
67 if (sam_ctx == NULL) {
68 return NT_STATUS_INVALID_SYSTEM_SERVICE;
71 /* fetch the old hashes */
72 ret = gendb_search_dn(sam_ctx, mem_ctx,
73 a_state->account_dn, &res, attrs);
74 if (ret != 1) {
75 return NT_STATUS_WRONG_PASSWORD;
78 status = samdb_result_passwords(mem_ctx,
79 dce_call->conn->dce_ctx->lp_ctx,
80 res[0], &lm_pwd, &nt_pwd);
81 if (!NT_STATUS_IS_OK(status) || !nt_pwd) {
82 return NT_STATUS_WRONG_PASSWORD;
85 /* decrypt and check the new lm hash */
86 if (lm_pwd) {
87 D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
88 D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
89 if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
90 return NT_STATUS_WRONG_PASSWORD;
94 /* decrypt and check the new nt hash */
95 D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
96 D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
97 if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
98 return NT_STATUS_WRONG_PASSWORD;
101 /* The NT Cross is not required by Win2k3 R2, but if present
102 check the nt cross hash */
103 if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
104 D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
105 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
106 return NT_STATUS_WRONG_PASSWORD;
110 /* The LM Cross is not required by Win2k3 R2, but if present
111 check the lm cross hash */
112 if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
113 D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
114 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
115 return NT_STATUS_WRONG_PASSWORD;
119 /* Start a SAM with user privileges for the password change */
120 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
121 dce_call->conn->dce_ctx->lp_ctx,
122 dce_call->conn->auth_state.session_info, 0);
123 if (sam_ctx == NULL) {
124 return NT_STATUS_INVALID_SYSTEM_SERVICE;
127 /* Start transaction */
128 ret = ldb_transaction_start(sam_ctx);
129 if (ret != LDB_SUCCESS) {
130 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
131 return NT_STATUS_TRANSACTION_ABORTED;
134 /* Performs the password modification. We pass the old hashes read out
135 * from the database since they were already checked against the user-
136 * provided ones. */
137 status = samdb_set_password(sam_ctx, mem_ctx,
138 a_state->account_dn,
139 a_state->domain_state->domain_dn,
140 NULL, &new_lmPwdHash, &new_ntPwdHash,
141 lm_pwd, nt_pwd, /* this is a user password change */
142 NULL,
143 NULL);
144 if (!NT_STATUS_IS_OK(status)) {
145 ldb_transaction_cancel(sam_ctx);
146 return status;
149 /* And this confirms it in a transaction commit */
150 ret = ldb_transaction_commit(sam_ctx);
151 if (ret != LDB_SUCCESS) {
152 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
153 ldb_dn_get_linearized(a_state->account_dn),
154 ldb_errstring(sam_ctx)));
155 return NT_STATUS_TRANSACTION_ABORTED;
158 return NT_STATUS_OK;
162 samr_OemChangePasswordUser2
164 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
165 TALLOC_CTX *mem_ctx,
166 struct samr_OemChangePasswordUser2 *r)
168 NTSTATUS status;
169 DATA_BLOB new_password, new_unicode_password;
170 char *new_pass;
171 struct samr_CryptPassword *pwbuf = r->in.password;
172 struct ldb_context *sam_ctx;
173 struct ldb_dn *user_dn;
174 int ret;
175 struct ldb_message **res;
176 const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
177 struct samr_Password *lm_pwd;
178 DATA_BLOB lm_pwd_blob;
179 uint8_t new_lm_hash[16];
180 struct samr_Password lm_verifier;
181 size_t unicode_pw_len;
183 if (pwbuf == NULL) {
184 return NT_STATUS_INVALID_PARAMETER;
187 if (r->in.hash == NULL) {
188 return NT_STATUS_INVALID_PARAMETER;
191 /* this call can only work with lanman auth */
192 if (!lpcfg_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
193 return NT_STATUS_WRONG_PASSWORD;
196 /* Connect to a SAMDB with system privileges for fetching the old pw
197 * hashes. */
198 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
199 dce_call->conn->dce_ctx->lp_ctx,
200 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
201 if (sam_ctx == NULL) {
202 return NT_STATUS_INVALID_SYSTEM_SERVICE;
205 /* we need the users dn and the domain dn (derived from the
206 user SID). We also need the current lm password hash in
207 order to decrypt the incoming password */
208 ret = gendb_search(sam_ctx,
209 mem_ctx, NULL, &res, attrs,
210 "(&(sAMAccountName=%s)(objectclass=user))",
211 r->in.account->string);
212 if (ret != 1) {
213 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
214 return NT_STATUS_WRONG_PASSWORD;
217 user_dn = res[0]->dn;
219 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
220 res[0], &lm_pwd, NULL);
221 if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
222 return NT_STATUS_WRONG_PASSWORD;
225 /* decrypt the password we have been given */
226 lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
227 arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
228 data_blob_free(&lm_pwd_blob);
230 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
231 DEBUG(3,("samr: failed to decode password buffer\n"));
232 return NT_STATUS_WRONG_PASSWORD;
235 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
236 CH_DOS, CH_UNIX,
237 (const char *)new_password.data,
238 new_password.length,
239 (void **)&new_pass, NULL, false)) {
240 DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
241 return NT_STATUS_WRONG_PASSWORD;
244 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
245 CH_DOS, CH_UTF16,
246 (const char *)new_password.data,
247 new_password.length,
248 (void **)&new_unicode_password.data, &unicode_pw_len, false)) {
249 DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
250 return NT_STATUS_WRONG_PASSWORD;
252 new_unicode_password.length = unicode_pw_len;
254 E_deshash(new_pass, new_lm_hash);
255 E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
256 if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
257 return NT_STATUS_WRONG_PASSWORD;
260 /* Connect to a SAMDB with user privileges for the password change */
261 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
262 dce_call->conn->dce_ctx->lp_ctx,
263 dce_call->conn->auth_state.session_info, 0);
264 if (sam_ctx == NULL) {
265 return NT_STATUS_INVALID_SYSTEM_SERVICE;
268 /* Start transaction */
269 ret = ldb_transaction_start(sam_ctx);
270 if (ret != LDB_SUCCESS) {
271 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
272 return NT_STATUS_TRANSACTION_ABORTED;
275 /* Performs the password modification. We pass the old hashes read out
276 * from the database since they were already checked against the user-
277 * provided ones. */
278 status = samdb_set_password(sam_ctx, mem_ctx,
279 user_dn, NULL,
280 &new_unicode_password,
281 NULL, NULL,
282 lm_pwd, NULL, /* this is a user password change */
283 NULL,
284 NULL);
285 if (!NT_STATUS_IS_OK(status)) {
286 ldb_transaction_cancel(sam_ctx);
287 return status;
290 /* And this confirms it in a transaction commit */
291 ret = ldb_transaction_commit(sam_ctx);
292 if (ret != LDB_SUCCESS) {
293 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
294 ldb_dn_get_linearized(user_dn),
295 ldb_errstring(sam_ctx)));
296 return NT_STATUS_TRANSACTION_ABORTED;
299 return NT_STATUS_OK;
304 samr_ChangePasswordUser3
306 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
307 TALLOC_CTX *mem_ctx,
308 struct samr_ChangePasswordUser3 *r)
310 NTSTATUS status;
311 DATA_BLOB new_password;
312 struct ldb_context *sam_ctx = NULL;
313 struct ldb_dn *user_dn;
314 int ret;
315 struct ldb_message **res;
316 const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
317 struct samr_Password *nt_pwd, *lm_pwd;
318 DATA_BLOB nt_pwd_blob;
319 struct samr_DomInfo1 *dominfo = NULL;
320 struct userPwdChangeFailureInformation *reject = NULL;
321 enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
322 uint8_t new_nt_hash[16], new_lm_hash[16];
323 struct samr_Password nt_verifier, lm_verifier;
325 *r->out.dominfo = NULL;
326 *r->out.reject = NULL;
328 if (r->in.nt_password == NULL ||
329 r->in.nt_verifier == NULL) {
330 return NT_STATUS_INVALID_PARAMETER;
333 /* Connect to a SAMDB with system privileges for fetching the old pw
334 * hashes. */
335 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
336 dce_call->conn->dce_ctx->lp_ctx,
337 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
338 if (sam_ctx == NULL) {
339 return NT_STATUS_INVALID_SYSTEM_SERVICE;
342 /* we need the users dn and the domain dn (derived from the
343 user SID). We also need the current lm and nt password hashes
344 in order to decrypt the incoming passwords */
345 ret = gendb_search(sam_ctx,
346 mem_ctx, NULL, &res, attrs,
347 "(&(sAMAccountName=%s)(objectclass=user))",
348 r->in.account->string);
349 if (ret != 1) {
350 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
351 status = NT_STATUS_WRONG_PASSWORD;
352 goto failed;
355 user_dn = res[0]->dn;
357 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
358 res[0], &lm_pwd, &nt_pwd);
359 if (!NT_STATUS_IS_OK(status) ) {
360 goto failed;
363 if (!nt_pwd) {
364 status = NT_STATUS_WRONG_PASSWORD;
365 goto failed;
368 /* decrypt the password we have been given */
369 nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
370 arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
371 data_blob_free(&nt_pwd_blob);
373 if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
374 DEBUG(3,("samr: failed to decode password buffer\n"));
375 status = NT_STATUS_WRONG_PASSWORD;
376 goto failed;
379 if (r->in.nt_verifier == NULL) {
380 status = NT_STATUS_WRONG_PASSWORD;
381 goto failed;
384 /* check NT verifier */
385 mdfour(new_nt_hash, new_password.data, new_password.length);
387 E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
388 if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
389 status = NT_STATUS_WRONG_PASSWORD;
390 goto failed;
393 /* check LM verifier (really not needed as we just checked the
394 * much stronger NT hash, but the RPC-SAMR test checks for
395 * this) */
396 if (lm_pwd && r->in.lm_verifier != NULL) {
397 char *new_pass;
398 if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
399 CH_UTF16, CH_UNIX,
400 (const char *)new_password.data,
401 new_password.length,
402 (void **)&new_pass, NULL, false)) {
403 E_deshash(new_pass, new_lm_hash);
404 E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
405 if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
406 status = NT_STATUS_WRONG_PASSWORD;
407 goto failed;
412 /* Connect to a SAMDB with user privileges for the password change */
413 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
414 dce_call->conn->dce_ctx->lp_ctx,
415 dce_call->conn->auth_state.session_info, 0);
416 if (sam_ctx == NULL) {
417 return NT_STATUS_INVALID_SYSTEM_SERVICE;
420 ret = ldb_transaction_start(sam_ctx);
421 if (ret != LDB_SUCCESS) {
422 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
423 return NT_STATUS_TRANSACTION_ABORTED;
426 /* Performs the password modification. We pass the old hashes read out
427 * from the database since they were already checked against the user-
428 * provided ones. */
429 status = samdb_set_password(sam_ctx, mem_ctx,
430 user_dn, NULL,
431 &new_password,
432 NULL, NULL,
433 lm_pwd, nt_pwd, /* this is a user password change */
434 &reason,
435 &dominfo);
437 if (!NT_STATUS_IS_OK(status)) {
438 ldb_transaction_cancel(sam_ctx);
439 goto failed;
442 /* And this confirms it in a transaction commit */
443 ret = ldb_transaction_commit(sam_ctx);
444 if (ret != LDB_SUCCESS) {
445 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
446 ldb_dn_get_linearized(user_dn),
447 ldb_errstring(sam_ctx)));
448 status = NT_STATUS_TRANSACTION_ABORTED;
449 goto failed;
452 return NT_STATUS_OK;
454 failed:
455 reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
456 if (reject != NULL) {
457 reject->extendedFailureReason = reason;
459 *r->out.reject = reject;
462 *r->out.dominfo = dominfo;
464 return status;
469 samr_ChangePasswordUser2
471 easy - just a subset of samr_ChangePasswordUser3
473 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
474 TALLOC_CTX *mem_ctx,
475 struct samr_ChangePasswordUser2 *r)
477 struct samr_ChangePasswordUser3 r2;
478 struct samr_DomInfo1 *dominfo = NULL;
479 struct userPwdChangeFailureInformation *reject = NULL;
481 r2.in.server = r->in.server;
482 r2.in.account = r->in.account;
483 r2.in.nt_password = r->in.nt_password;
484 r2.in.nt_verifier = r->in.nt_verifier;
485 r2.in.lm_change = r->in.lm_change;
486 r2.in.lm_password = r->in.lm_password;
487 r2.in.lm_verifier = r->in.lm_verifier;
488 r2.in.password3 = NULL;
489 r2.out.dominfo = &dominfo;
490 r2.out.reject = &reject;
492 return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
497 set password via a samr_CryptPassword buffer
499 NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
500 struct ldb_context *sam_ctx,
501 struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
502 TALLOC_CTX *mem_ctx,
503 struct samr_CryptPassword *pwbuf)
505 NTSTATUS nt_status;
506 DATA_BLOB new_password;
507 DATA_BLOB session_key = data_blob(NULL, 0);
509 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
510 if (!NT_STATUS_IS_OK(nt_status)) {
511 return nt_status;
514 arcfour_crypt_blob(pwbuf->data, 516, &session_key);
516 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
517 DEBUG(3,("samr: failed to decode password buffer\n"));
518 return NT_STATUS_WRONG_PASSWORD;
521 /* set the password - samdb needs to know both the domain and user DNs,
522 so the domain password policy can be used */
523 return samdb_set_password(sam_ctx, mem_ctx,
524 account_dn, domain_dn,
525 &new_password,
526 NULL, NULL,
527 NULL, NULL, /* This is a password set, not change */
528 NULL, NULL);
533 set password via a samr_CryptPasswordEx buffer
535 NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
536 struct ldb_context *sam_ctx,
537 struct ldb_dn *account_dn,
538 struct ldb_dn *domain_dn,
539 TALLOC_CTX *mem_ctx,
540 struct samr_CryptPasswordEx *pwbuf)
542 NTSTATUS nt_status;
543 DATA_BLOB new_password;
544 DATA_BLOB co_session_key;
545 DATA_BLOB session_key = data_blob(NULL, 0);
546 struct MD5Context ctx;
548 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
549 if (!NT_STATUS_IS_OK(nt_status)) {
550 return nt_status;
553 co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
554 if (!co_session_key.data) {
555 return NT_STATUS_NO_MEMORY;
558 MD5Init(&ctx);
559 MD5Update(&ctx, &pwbuf->data[516], 16);
560 MD5Update(&ctx, session_key.data, session_key.length);
561 MD5Final(co_session_key.data, &ctx);
563 arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
565 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
566 DEBUG(3,("samr: failed to decode password buffer\n"));
567 return NT_STATUS_WRONG_PASSWORD;
570 /* set the password - samdb needs to know both the domain and user DNs,
571 so the domain password policy can be used */
572 return samdb_set_password(sam_ctx, mem_ctx,
573 account_dn, domain_dn,
574 &new_password,
575 NULL, NULL,
576 NULL, NULL, /* This is a password set, not change */
577 NULL, NULL);
581 set password via encrypted NT and LM hash buffers
583 NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call,
584 struct ldb_context *sam_ctx,
585 struct ldb_dn *account_dn,
586 struct ldb_dn *domain_dn,
587 TALLOC_CTX *mem_ctx,
588 const uint8_t *lm_pwd_hash,
589 const uint8_t *nt_pwd_hash)
591 struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL;
592 DATA_BLOB session_key = data_blob(NULL, 0);
593 DATA_BLOB in, out;
594 NTSTATUS nt_status = NT_STATUS_OK;
596 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
597 if (!NT_STATUS_IS_OK(nt_status)) {
598 return nt_status;
601 if (lm_pwd_hash != NULL) {
602 in = data_blob_const(lm_pwd_hash, 16);
603 out = data_blob_talloc_zero(mem_ctx, 16);
605 sess_crypt_blob(&out, &in, &session_key, false);
607 d_lm_pwd_hash = (struct samr_Password *) out.data;
609 if (nt_pwd_hash != NULL) {
610 in = data_blob_const(nt_pwd_hash, 16);
611 out = data_blob_talloc_zero(mem_ctx, 16);
613 sess_crypt_blob(&out, &in, &session_key, false);
615 d_nt_pwd_hash = (struct samr_Password *) out.data;
618 if ((d_lm_pwd_hash != NULL) || (d_nt_pwd_hash != NULL)) {
619 nt_status = samdb_set_password(sam_ctx, mem_ctx, account_dn,
620 domain_dn, NULL,
621 d_lm_pwd_hash, d_nt_pwd_hash,
622 NULL, NULL, /* this is a password set */
623 NULL, NULL);
626 return nt_status;