source: vendor/current/source4/rpc_server/samr/samr_password.c@ 740

Last change on this file since 740 was 740, checked in by Silvan Scherrer, 12 years ago

Samba Server: update vendor to 3.6.0

File size: 19.4 KB
Line 
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
33/*
34 samr_ChangePasswordUser
35*/
36NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
37 TALLOC_CTX *mem_ctx,
38 struct samr_ChangePasswordUser *r)
39{
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 };
49
50 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
51
52 a_state = h->data;
53
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;
61 }
62
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), 0);
68 if (sam_ctx == NULL) {
69 return NT_STATUS_INVALID_SYSTEM_SERVICE;
70 }
71
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;
77 }
78
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;
84 }
85
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;
92 }
93 }
94
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;
100 }
101
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;
108 }
109 }
110
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;
117 }
118 }
119
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, 0);
124 if (sam_ctx == NULL) {
125 return NT_STATUS_INVALID_SYSTEM_SERVICE;
126 }
127
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;
133 }
134
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;
148 }
149
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;
157 }
158
159 return NT_STATUS_OK;
160}
161
162/*
163 samr_OemChangePasswordUser2
164*/
165NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
166 TALLOC_CTX *mem_ctx,
167 struct samr_OemChangePasswordUser2 *r)
168{
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;
183
184 if (pwbuf == NULL) {
185 return NT_STATUS_INVALID_PARAMETER;
186 }
187
188 if (r->in.hash == NULL) {
189 return NT_STATUS_INVALID_PARAMETER;
190 }
191
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;
195 }
196
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), 0);
202 if (sam_ctx == NULL) {
203 return NT_STATUS_INVALID_SYSTEM_SERVICE;
204 }
205
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;
216 }
217
218 user_dn = res[0]->dn;
219
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;
224 }
225
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);
230
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;
234 }
235
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;
243 }
244
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;
252 }
253 new_unicode_password.length = unicode_pw_len;
254
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;
259 }
260
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, 0);
265 if (sam_ctx == NULL) {
266 return NT_STATUS_INVALID_SYSTEM_SERVICE;
267 }
268
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;
274 }
275
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;
289 }
290
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;
298 }
299
300 return NT_STATUS_OK;
301}
302
303
304/*
305 samr_ChangePasswordUser3
306*/
307NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
308 TALLOC_CTX *mem_ctx,
309 struct samr_ChangePasswordUser3 *r)
310{
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;
325
326 *r->out.dominfo = NULL;
327 *r->out.reject = NULL;
328
329 if (r->in.nt_password == NULL ||
330 r->in.nt_verifier == NULL) {
331 return NT_STATUS_INVALID_PARAMETER;
332 }
333
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), 0);
339 if (sam_ctx == NULL) {
340 return NT_STATUS_INVALID_SYSTEM_SERVICE;
341 }
342
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;
354 }
355
356 user_dn = res[0]->dn;
357
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;
362 }
363
364 if (!nt_pwd) {
365 status = NT_STATUS_WRONG_PASSWORD;
366 goto failed;
367 }
368
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);
373
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;
378 }
379
380 if (r->in.nt_verifier == NULL) {
381 status = NT_STATUS_WRONG_PASSWORD;
382 goto failed;
383 }
384
385 /* check NT verifier */
386 mdfour(new_nt_hash, new_password.data, new_password.length);
387
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;
392 }
393
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;
409 }
410 }
411 }
412
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, 0);
417 if (sam_ctx == NULL) {
418 return NT_STATUS_INVALID_SYSTEM_SERVICE;
419 }
420
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;
425 }
426
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);
437
438 if (!NT_STATUS_IS_OK(status)) {
439 ldb_transaction_cancel(sam_ctx);
440 goto failed;
441 }
442
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;
451 }
452
453 return NT_STATUS_OK;
454
455failed:
456 reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
457 if (reject != NULL) {
458 reject->extendedFailureReason = reason;
459
460 *r->out.reject = reject;
461 }
462
463 *r->out.dominfo = dominfo;
464
465 return status;
466}
467
468
469/*
470 samr_ChangePasswordUser2
471
472 easy - just a subset of samr_ChangePasswordUser3
473*/
474NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
475 TALLOC_CTX *mem_ctx,
476 struct samr_ChangePasswordUser2 *r)
477{
478 struct samr_ChangePasswordUser3 r2;
479 struct samr_DomInfo1 *dominfo = NULL;
480 struct userPwdChangeFailureInformation *reject = NULL;
481
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;
492
493 return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
494}
495
496
497/*
498 set password via a samr_CryptPassword buffer
499*/
500NTSTATUS 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)
505{
506 NTSTATUS nt_status;
507 DATA_BLOB new_password;
508 DATA_BLOB session_key = data_blob(NULL, 0);
509
510 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
511 if (!NT_STATUS_IS_OK(nt_status)) {
512 return nt_status;
513 }
514
515 arcfour_crypt_blob(pwbuf->data, 516, &session_key);
516
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;
520 }
521
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);
530}
531
532
533/*
534 set password via a samr_CryptPasswordEx buffer
535*/
536NTSTATUS 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)
542{
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;
548
549 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
550 if (!NT_STATUS_IS_OK(nt_status)) {
551 return nt_status;
552 }
553
554 co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
555 if (!co_session_key.data) {
556 return NT_STATUS_NO_MEMORY;
557 }
558
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);
563
564 arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
565
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;
569 }
570
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);
579}
580
581/*
582 set password via encrypted NT and LM hash buffers
583*/
584NTSTATUS 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)
591{
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;
596
597 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
598 if (!NT_STATUS_IS_OK(nt_status)) {
599 return nt_status;
600 }
601
602 if (lm_pwd_hash != NULL) {
603 in = data_blob_const(lm_pwd_hash, 16);
604 out = data_blob_talloc_zero(mem_ctx, 16);
605
606 sess_crypt_blob(&out, &in, &session_key, false);
607
608 d_lm_pwd_hash = (struct samr_Password *) out.data;
609 }
610 if (nt_pwd_hash != NULL) {
611 in = data_blob_const(nt_pwd_hash, 16);
612 out = data_blob_talloc_zero(mem_ctx, 16);
613
614 sess_crypt_blob(&out, &in, &session_key, false);
615
616 d_nt_pwd_hash = (struct samr_Password *) out.data;
617 }
618
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);
625 }
626
627 return nt_status;
628}
Note: See TracBrowser for help on using the repository browser.