s4:libnet_rpc: check for NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE instead of NT_STATUS_NET_...
[Samba/gebeck_regimport.git] / source4 / rpc_server / samr / samr_password.c
blob1a09283ea6b3a62beaf8cb41fe02033f3e66cc56
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, *msg;
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 /* To change a password we need to open as system */
64 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx));
65 if (sam_ctx == NULL) {
66 return NT_STATUS_INVALID_SYSTEM_SERVICE;
69 ret = ldb_transaction_start(sam_ctx);
70 if (ret != LDB_SUCCESS) {
71 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
72 return NT_STATUS_TRANSACTION_ABORTED;
75 /* fetch the old hashes */
76 ret = gendb_search_dn(sam_ctx, mem_ctx,
77 a_state->account_dn, &res, attrs);
78 if (ret != 1) {
79 ldb_transaction_cancel(sam_ctx);
80 return NT_STATUS_WRONG_PASSWORD;
82 msg = res[0];
84 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
85 msg, &lm_pwd, &nt_pwd);
86 if (!NT_STATUS_IS_OK(status) || !nt_pwd) {
87 ldb_transaction_cancel(sam_ctx);
88 return NT_STATUS_WRONG_PASSWORD;
91 /* decrypt and check the new lm hash */
92 if (lm_pwd) {
93 D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
94 D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
95 if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
96 ldb_transaction_cancel(sam_ctx);
97 return NT_STATUS_WRONG_PASSWORD;
101 /* decrypt and check the new nt hash */
102 D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
103 D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
104 if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
105 ldb_transaction_cancel(sam_ctx);
106 return NT_STATUS_WRONG_PASSWORD;
109 /* The NT Cross is not required by Win2k3 R2, but if present
110 check the nt cross hash */
111 if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
112 D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
113 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
114 ldb_transaction_cancel(sam_ctx);
115 return NT_STATUS_WRONG_PASSWORD;
119 /* The LM Cross is not required by Win2k3 R2, but if present
120 check the lm cross hash */
121 if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
122 D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
123 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
124 ldb_transaction_cancel(sam_ctx);
125 return NT_STATUS_WRONG_PASSWORD;
129 msg = ldb_msg_new(mem_ctx);
130 if (msg == NULL) {
131 ldb_transaction_cancel(sam_ctx);
132 return NT_STATUS_NO_MEMORY;
135 msg->dn = ldb_dn_copy(msg, a_state->account_dn);
136 if (!msg->dn) {
137 ldb_transaction_cancel(sam_ctx);
138 return NT_STATUS_NO_MEMORY;
141 /* setup password modify mods on the user DN specified. This may fail
142 * due to password policies. */
143 status = samdb_set_password(sam_ctx, mem_ctx,
144 a_state->account_dn, a_state->domain_state->domain_dn,
145 msg, NULL, &new_lmPwdHash, &new_ntPwdHash,
146 true, /* this is a user password change */
147 NULL,
148 NULL);
149 if (!NT_STATUS_IS_OK(status)) {
150 ldb_transaction_cancel(sam_ctx);
151 return status;
154 /* The above call only setup the modifications, this actually
155 * makes the write to the database. */
156 ret = dsdb_replace(sam_ctx, msg, 0);
157 if (ret != LDB_SUCCESS) {
158 DEBUG(2,("Failed to modify record to change password on %s: %s\n",
159 ldb_dn_get_linearized(a_state->account_dn),
160 ldb_errstring(sam_ctx)));
161 ldb_transaction_cancel(sam_ctx);
162 return NT_STATUS_INTERNAL_DB_CORRUPTION;
165 /* And this confirms it in a transaction commit */
166 ret = ldb_transaction_commit(sam_ctx);
167 if (ret != LDB_SUCCESS) {
168 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
169 ldb_dn_get_linearized(a_state->account_dn),
170 ldb_errstring(sam_ctx)));
171 return NT_STATUS_TRANSACTION_ABORTED;
174 return NT_STATUS_OK;
178 samr_OemChangePasswordUser2
180 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
181 TALLOC_CTX *mem_ctx,
182 struct samr_OemChangePasswordUser2 *r)
184 NTSTATUS status;
185 DATA_BLOB new_password, new_unicode_password;
186 char *new_pass;
187 struct samr_CryptPassword *pwbuf = r->in.password;
188 struct ldb_context *sam_ctx;
189 struct ldb_dn *user_dn;
190 int ret;
191 struct ldb_message **res, *mod;
192 const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
193 struct samr_Password *lm_pwd;
194 DATA_BLOB lm_pwd_blob;
195 uint8_t new_lm_hash[16];
196 struct samr_Password lm_verifier;
197 size_t unicode_pw_len;
199 if (pwbuf == NULL) {
200 return NT_STATUS_INVALID_PARAMETER;
203 if (r->in.hash == NULL) {
204 return NT_STATUS_INVALID_PARAMETER;
207 /* this call can only work with lanman auth */
208 if (!lp_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
209 return NT_STATUS_NOT_SUPPORTED;
212 /* To change a password we need to open as system */
213 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx));
214 if (sam_ctx == NULL) {
215 return NT_STATUS_INVALID_SYSTEM_SERVICE;
218 ret = ldb_transaction_start(sam_ctx);
219 if (ret != LDB_SUCCESS) {
220 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
221 return NT_STATUS_TRANSACTION_ABORTED;
224 /* we need the users dn and the domain dn (derived from the
225 user SID). We also need the current lm password hash in
226 order to decrypt the incoming password */
227 ret = gendb_search(sam_ctx,
228 mem_ctx, NULL, &res, attrs,
229 "(&(sAMAccountName=%s)(objectclass=user))",
230 r->in.account->string);
231 if (ret != 1) {
232 ldb_transaction_cancel(sam_ctx);
233 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
234 return NT_STATUS_WRONG_PASSWORD;
237 user_dn = res[0]->dn;
239 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
240 res[0], &lm_pwd, NULL);
241 if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
242 ldb_transaction_cancel(sam_ctx);
243 return NT_STATUS_WRONG_PASSWORD;
246 /* decrypt the password we have been given */
247 lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
248 arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
249 data_blob_free(&lm_pwd_blob);
251 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
252 ldb_transaction_cancel(sam_ctx);
253 DEBUG(3,("samr: failed to decode password buffer\n"));
254 return NT_STATUS_WRONG_PASSWORD;
257 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(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, NULL, false)) {
262 DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
263 ldb_transaction_cancel(sam_ctx);
264 return NT_STATUS_WRONG_PASSWORD;
267 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
268 CH_DOS, CH_UTF16,
269 (const char *)new_password.data,
270 new_password.length,
271 (void **)&new_unicode_password.data, &unicode_pw_len, false)) {
272 DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
273 ldb_transaction_cancel(sam_ctx);
274 return NT_STATUS_WRONG_PASSWORD;
276 new_unicode_password.length = unicode_pw_len;
278 E_deshash(new_pass, new_lm_hash);
279 E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
280 if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
281 ldb_transaction_cancel(sam_ctx);
282 return NT_STATUS_WRONG_PASSWORD;
285 mod = ldb_msg_new(mem_ctx);
286 if (mod == NULL) {
287 ldb_transaction_cancel(sam_ctx);
288 return NT_STATUS_NO_MEMORY;
291 mod->dn = ldb_dn_copy(mod, user_dn);
292 if (!mod->dn) {
293 ldb_transaction_cancel(sam_ctx);
294 return NT_STATUS_NO_MEMORY;
297 /* set the password on the user DN specified. This may fail
298 * due to password policies */
299 status = samdb_set_password(sam_ctx, mem_ctx,
300 user_dn, NULL,
301 mod, &new_unicode_password,
302 NULL, NULL,
303 true, /* this is a user password change */
304 NULL,
305 NULL);
306 if (!NT_STATUS_IS_OK(status)) {
307 ldb_transaction_cancel(sam_ctx);
308 return status;
311 /* The above call only setup the modifications, this actually
312 * makes the write to the database. */
313 ret = dsdb_replace(sam_ctx, mod, 0);
314 if (ret != LDB_SUCCESS) {
315 DEBUG(2,("Failed to modify record to change password on %s: %s\n",
316 ldb_dn_get_linearized(user_dn),
317 ldb_errstring(sam_ctx)));
318 ldb_transaction_cancel(sam_ctx);
319 return NT_STATUS_INTERNAL_DB_CORRUPTION;
322 /* And this confirms it in a transaction commit */
323 ret = ldb_transaction_commit(sam_ctx);
324 if (ret != LDB_SUCCESS) {
325 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
326 ldb_dn_get_linearized(user_dn),
327 ldb_errstring(sam_ctx)));
328 return NT_STATUS_TRANSACTION_ABORTED;
331 return NT_STATUS_OK;
336 samr_ChangePasswordUser3
338 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
339 TALLOC_CTX *mem_ctx,
340 struct samr_ChangePasswordUser3 *r)
342 NTSTATUS status;
343 DATA_BLOB new_password;
344 struct ldb_context *sam_ctx = NULL;
345 struct ldb_dn *user_dn;
346 int ret;
347 struct ldb_message **res, *mod;
348 const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
349 struct samr_Password *nt_pwd, *lm_pwd;
350 DATA_BLOB nt_pwd_blob;
351 struct samr_DomInfo1 *dominfo = NULL;
352 struct userPwdChangeFailureInformation *reject = NULL;
353 enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
354 uint8_t new_nt_hash[16], new_lm_hash[16];
355 struct samr_Password nt_verifier, lm_verifier;
357 *r->out.dominfo = NULL;
358 *r->out.reject = NULL;
360 if (r->in.nt_password == NULL ||
361 r->in.nt_verifier == NULL) {
362 return NT_STATUS_INVALID_PARAMETER;
365 /* To change a password we need to open as system */
366 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx));
367 if (sam_ctx == NULL) {
368 return NT_STATUS_INVALID_SYSTEM_SERVICE;
371 ret = ldb_transaction_start(sam_ctx);
372 if (ret != LDB_SUCCESS) {
373 talloc_free(sam_ctx);
374 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
375 return NT_STATUS_TRANSACTION_ABORTED;
378 /* we need the users dn and the domain dn (derived from the
379 user SID). We also need the current lm and nt password hashes
380 in order to decrypt the incoming passwords */
381 ret = gendb_search(sam_ctx,
382 mem_ctx, NULL, &res, attrs,
383 "(&(sAMAccountName=%s)(objectclass=user))",
384 r->in.account->string);
385 if (ret != 1) {
386 /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */
387 status = NT_STATUS_WRONG_PASSWORD;
388 goto failed;
391 user_dn = res[0]->dn;
393 status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
394 res[0], &lm_pwd, &nt_pwd);
395 if (!NT_STATUS_IS_OK(status) ) {
396 goto failed;
399 if (!nt_pwd) {
400 status = NT_STATUS_WRONG_PASSWORD;
401 goto failed;
404 /* decrypt the password we have been given */
405 nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
406 arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
407 data_blob_free(&nt_pwd_blob);
409 if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
410 ldb_transaction_cancel(sam_ctx);
411 DEBUG(3,("samr: failed to decode password buffer\n"));
412 return NT_STATUS_WRONG_PASSWORD;
415 if (r->in.nt_verifier == NULL) {
416 status = NT_STATUS_WRONG_PASSWORD;
417 goto failed;
420 /* check NT verifier */
421 mdfour(new_nt_hash, new_password.data, new_password.length);
423 E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
424 if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
425 status = NT_STATUS_WRONG_PASSWORD;
426 goto failed;
429 /* check LM verifier (really not needed as we just checked the
430 * much stronger NT hash, but the RPC-SAMR test checks for
431 * this) */
432 if (lm_pwd && r->in.lm_verifier != NULL) {
433 char *new_pass;
434 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
435 CH_UTF16, CH_UNIX,
436 (const char *)new_password.data,
437 new_password.length,
438 (void **)&new_pass, NULL, false)) {
439 E_deshash(new_pass, new_lm_hash);
440 E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
441 if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
442 status = NT_STATUS_WRONG_PASSWORD;
443 goto failed;
448 mod = ldb_msg_new(mem_ctx);
449 if (mod == NULL) {
450 status = NT_STATUS_NO_MEMORY;
451 goto failed;
454 mod->dn = ldb_dn_copy(mod, user_dn);
455 if (!mod->dn) {
456 status = NT_STATUS_NO_MEMORY;
457 goto failed;
460 /* set the password on the user DN specified. This may fail
461 * due to password policies */
462 status = samdb_set_password(sam_ctx, mem_ctx,
463 user_dn, NULL,
464 mod, &new_password,
465 NULL, NULL,
466 true, /* this is a user password change */
467 &reason,
468 &dominfo);
470 if (!NT_STATUS_IS_OK(status)) {
471 goto failed;
474 /* The above call only setup the modifications, this actually
475 * makes the write to the database. */
476 ret = dsdb_replace(sam_ctx, mod, 0);
477 if (ret != LDB_SUCCESS) {
478 DEBUG(2,("dsdb_replace failed to change password for %s: %s\n",
479 ldb_dn_get_linearized(user_dn),
480 ldb_errstring(sam_ctx)));
481 status = NT_STATUS_UNSUCCESSFUL;
482 goto failed;
485 /* And this confirms it in a transaction commit */
486 ret = ldb_transaction_commit(sam_ctx);
487 if (ret != LDB_SUCCESS) {
488 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
489 ldb_dn_get_linearized(user_dn),
490 ldb_errstring(sam_ctx)));
491 status = NT_STATUS_TRANSACTION_ABORTED;
492 goto failed;
495 return NT_STATUS_OK;
497 failed:
498 ldb_transaction_cancel(sam_ctx);
500 reject = talloc(mem_ctx, struct userPwdChangeFailureInformation);
501 if (reject != NULL) {
502 ZERO_STRUCTP(reject);
503 reject->extendedFailureReason = reason;
505 *r->out.reject = reject;
508 *r->out.dominfo = dominfo;
510 return status;
515 samr_ChangePasswordUser2
517 easy - just a subset of samr_ChangePasswordUser3
519 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
520 TALLOC_CTX *mem_ctx,
521 struct samr_ChangePasswordUser2 *r)
523 struct samr_ChangePasswordUser3 r2;
524 struct samr_DomInfo1 *dominfo = NULL;
525 struct userPwdChangeFailureInformation *reject = NULL;
527 r2.in.server = r->in.server;
528 r2.in.account = r->in.account;
529 r2.in.nt_password = r->in.nt_password;
530 r2.in.nt_verifier = r->in.nt_verifier;
531 r2.in.lm_change = r->in.lm_change;
532 r2.in.lm_password = r->in.lm_password;
533 r2.in.lm_verifier = r->in.lm_verifier;
534 r2.in.password3 = NULL;
535 r2.out.dominfo = &dominfo;
536 r2.out.reject = &reject;
538 return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
543 set password via a samr_CryptPassword buffer
544 this will in the 'msg' with modify operations that will update the user
545 password when applied
547 NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
548 void *sam_ctx,
549 struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
550 TALLOC_CTX *mem_ctx,
551 struct ldb_message *msg,
552 struct samr_CryptPassword *pwbuf)
554 NTSTATUS nt_status;
555 DATA_BLOB new_password;
556 DATA_BLOB session_key = data_blob(NULL, 0);
558 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
559 if (!NT_STATUS_IS_OK(nt_status)) {
560 return nt_status;
563 arcfour_crypt_blob(pwbuf->data, 516, &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 msg, &new_password,
575 NULL, NULL,
576 false, /* This is a password set, not change */
577 NULL, NULL);
582 set password via a samr_CryptPasswordEx buffer
583 this will in the 'msg' with modify operations that will update the user
584 password when applied
586 NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
587 struct ldb_context *sam_ctx,
588 struct ldb_dn *account_dn,
589 struct ldb_dn *domain_dn,
590 TALLOC_CTX *mem_ctx,
591 struct ldb_message *msg,
592 struct samr_CryptPasswordEx *pwbuf)
594 NTSTATUS nt_status;
595 DATA_BLOB new_password;
596 DATA_BLOB co_session_key;
597 DATA_BLOB session_key = data_blob(NULL, 0);
598 struct MD5Context ctx;
600 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
601 if (!NT_STATUS_IS_OK(nt_status)) {
602 return nt_status;
605 co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
606 if (!co_session_key.data) {
607 return NT_STATUS_NO_MEMORY;
610 MD5Init(&ctx);
611 MD5Update(&ctx, &pwbuf->data[516], 16);
612 MD5Update(&ctx, session_key.data, session_key.length);
613 MD5Final(co_session_key.data, &ctx);
615 arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
617 if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
618 DEBUG(3,("samr: failed to decode password buffer\n"));
619 return NT_STATUS_WRONG_PASSWORD;
622 /* set the password - samdb needs to know both the domain and user DNs,
623 so the domain password policy can be used */
624 return samdb_set_password(sam_ctx, mem_ctx,
625 account_dn, domain_dn,
626 msg, &new_password,
627 NULL, NULL,
628 false, /* This is a password set, not change */
629 NULL, NULL);