Ensure convert_string_XXX is always called with a valid converted_size pointer.
[samba.git] / source4 / rpc_server / samr / samr_password.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    samr server password set/change handling
5
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
8
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.
13
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.
18
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/>.
21 */
22
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"
33
34 /*
35   samr_ChangePasswordUser
36 */
37 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
38                                         TALLOC_CTX *mem_ctx,
39                                         struct samr_ChangePasswordUser *r)
40 {
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 };
50
51         DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
52
53         a_state = h->data;
54
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;
62         }
63
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;
71         }
72
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;
78         }
79
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;
85         }
86
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;
93                 }
94         }
95
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;
101         }
102
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;
109                 }
110         }
111
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;
118                 }
119         }
120
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;
127         }
128
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;
134         }
135
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;
149         }
150
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;
158         }
159
160         return NT_STATUS_OK;
161 }
162
163 /*
164   samr_OemChangePasswordUser2
165 */
166 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
167                                             TALLOC_CTX *mem_ctx,
168                                             struct samr_OemChangePasswordUser2 *r)
169 {
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;
185
186         if (pwbuf == NULL) {
187                 return NT_STATUS_INVALID_PARAMETER;
188         }
189
190         if (r->in.hash == NULL) {
191                 return NT_STATUS_INVALID_PARAMETER;
192         }
193
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;
197         }
198
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;
206         }
207
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;
218         }
219
220         user_dn = res[0]->dn;
221
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;
226         }
227
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);
232
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;
236         }
237
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;
245         }
246
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;
254         }
255         new_unicode_password.length = unicode_pw_len;
256
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;
261         }
262
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;
269         }
270
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;
276         }
277
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;
291         }
292
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;
300         }
301
302         return NT_STATUS_OK;
303 }
304
305
306 /*
307   samr_ChangePasswordUser3
308 */
309 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
310                                          TALLOC_CTX *mem_ctx,
311                                          struct samr_ChangePasswordUser3 *r)
312 {
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;
327
328         *r->out.dominfo = NULL;
329         *r->out.reject = NULL;
330
331         if (r->in.nt_password == NULL ||
332             r->in.nt_verifier == NULL) {
333                 return NT_STATUS_INVALID_PARAMETER;
334         }
335
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;
343         }
344
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;
356         }
357
358         user_dn = res[0]->dn;
359
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;
364         }
365
366         if (!nt_pwd) {
367                 status = NT_STATUS_WRONG_PASSWORD;
368                 goto failed;
369         }
370
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);
375
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;
380         }
381
382         if (r->in.nt_verifier == NULL) {
383                 status = NT_STATUS_WRONG_PASSWORD;
384                 goto failed;
385         }
386
387         /* check NT verifier */
388         mdfour(new_nt_hash, new_password.data, new_password.length);
389
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;
394         }
395
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;
402
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;
413                         }
414                 }
415         }
416
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;
423         }
424
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;
429         }
430
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);
441
442         if (!NT_STATUS_IS_OK(status)) {
443                 ldb_transaction_cancel(sam_ctx);
444                 goto failed;
445         }
446
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;
455         }
456
457         return NT_STATUS_OK;
458
459 failed:
460         reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
461         if (reject != NULL) {
462                 reject->extendedFailureReason = reason;
463
464                 *r->out.reject = reject;
465         }
466
467         *r->out.dominfo = dominfo;
468
469         return status;
470 }
471
472
473 /*
474   samr_ChangePasswordUser2
475
476   easy - just a subset of samr_ChangePasswordUser3
477 */
478 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
479                                          TALLOC_CTX *mem_ctx,
480                                          struct samr_ChangePasswordUser2 *r)
481 {
482         struct samr_ChangePasswordUser3 r2;
483         struct samr_DomInfo1 *dominfo = NULL;
484         struct userPwdChangeFailureInformation *reject = NULL;
485
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;
496
497         return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
498 }
499
500
501 /*
502   set password via a samr_CryptPassword buffer
503 */
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)
509 {
510         NTSTATUS nt_status;
511         DATA_BLOB new_password;
512         DATA_BLOB session_key = data_blob(NULL, 0);
513
514         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
515         if (!NT_STATUS_IS_OK(nt_status)) {
516                 return nt_status;
517         }
518
519         arcfour_crypt_blob(pwbuf->data, 516, &session_key);
520
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;
524         }
525
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);
534 }
535
536
537 /*
538   set password via a samr_CryptPasswordEx buffer
539 */
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)
546 {
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;
552
553         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
554         if (!NT_STATUS_IS_OK(nt_status)) {
555                 return nt_status;
556         }
557
558         co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
559         if (!co_session_key.data) {
560                 return NT_STATUS_NO_MEMORY;
561         }
562
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);
567
568         arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
569
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;
573         }
574
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);
583 }
584
585 /*
586   set password via encrypted NT and LM hash buffers
587 */
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)
595 {
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;
600
601         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
602         if (!NT_STATUS_IS_OK(nt_status)) {
603                 return nt_status;
604         }
605
606         if (lm_pwd_hash != NULL) {
607                 in = data_blob_const(lm_pwd_hash, 16);
608                 out = data_blob_talloc_zero(mem_ctx, 16);
609
610                 sess_crypt_blob(&out, &in, &session_key, false);
611
612                 d_lm_pwd_hash = (struct samr_Password *) out.data;
613         }
614         if (nt_pwd_hash != NULL) {
615                 in = data_blob_const(nt_pwd_hash, 16);
616                 out = data_blob_talloc_zero(mem_ctx, 16);
617
618                 sess_crypt_blob(&out, &in, &session_key, false);
619
620                 d_nt_pwd_hash = (struct samr_Password *) out.data;
621         }
622
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);
629         }
630
631         return nt_status;
632 }