2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2004
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * do a password change using DCERPC/SAMR calls
25 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
26 * 2. try samr_ChangePasswordUser3
27 * 3. try samr_ChangePasswordUser2
28 * 4. try samr_OemChangePasswordUser2
29 * (not yet: 5. try samr_ChangePasswordUser)
31 static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
34 union libnet_rpc_connect c;
36 struct policy_handle user_handle;
37 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
38 struct samr_ChangePasswordUser pw;
40 struct samr_OemChangePasswordUser2 oe2;
41 struct samr_ChangePasswordUser2 pw2;
42 struct samr_ChangePasswordUser3 pw3;
43 struct samr_Name server, account;
44 struct samr_AsciiName a_server, a_account;
45 struct samr_CryptPassword nt_pass, lm_pass;
46 struct samr_Password nt_verifier, lm_verifier;
47 uint8_t old_nt_hash[16], new_nt_hash[16];
48 uint8_t old_lm_hash[16], new_lm_hash[16];
50 /* prepare connect to the SAMR pipe of the users domain PDC */
51 c.pdc.level = LIBNET_RPC_CONNECT_PDC;
52 c.pdc.in.domain_name = r->samr.in.domain_name;
53 c.pdc.in.dcerpc_iface_name = DCERPC_SAMR_NAME;
54 c.pdc.in.dcerpc_iface_uuid = DCERPC_SAMR_UUID;
55 c.pdc.in.dcerpc_iface_version = DCERPC_SAMR_VERSION;
57 /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
58 status = libnet_rpc_connect(ctx, mem_ctx, &c);
59 if (!NT_STATUS_IS_OK(status)) {
60 r->samr.out.error_string = talloc_asprintf(mem_ctx,
61 "Connection to SAMR pipe of PDC of domain '%s' failed: %s\n",
62 r->samr.in.domain_name, nt_errstr(status));
66 /* prepare password change for account */
67 server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.pdc.out.dcerpc_pipe));
68 account.name = r->samr.in.account_name;
70 E_md4hash(r->samr.in.oldpassword, old_nt_hash);
71 E_md4hash(r->samr.in.newpassword, new_nt_hash);
73 E_deshash(r->samr.in.oldpassword, old_lm_hash);
74 E_deshash(r->samr.in.newpassword, new_lm_hash);
76 /* prepare samr_ChangePasswordUser3 */
77 encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_UNICODE);
78 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
79 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
81 encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
82 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
83 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
85 pw3.in.server = &server;
86 pw3.in.account = &account;
87 pw3.in.nt_password = &nt_pass;
88 pw3.in.nt_verifier = &nt_verifier;
90 pw3.in.lm_password = &lm_pass;
91 pw3.in.lm_verifier = &lm_verifier;
92 pw3.in.password3 = NULL;
94 /* 2. try samr_ChangePasswordUser3 */
95 status = dcerpc_samr_ChangePasswordUser3(c.pdc.out.dcerpc_pipe, mem_ctx, &pw3);
96 if (!NT_STATUS_IS_OK(status)) {
97 r->samr.out.error_string = talloc_asprintf(mem_ctx,
98 "samr_ChangePasswordUser3 failed: %s\n",
100 goto ChangePasswordUser2;
103 /* check result of samr_ChangePasswordUser3 */
104 if (!NT_STATUS_IS_OK(pw3.out.result)) {
105 r->samr.out.error_string = talloc_asprintf(mem_ctx,
106 "samr_ChangePasswordUser3 for '%s\\%s' failed: %s\n",
107 r->samr.in.domain_name, r->samr.in.account_name,
108 nt_errstr(pw3.out.result));
109 /* TODO: give the reason of the reject */
110 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
113 goto ChangePasswordUser2;
119 /* prepare samr_ChangePasswordUser2 */
120 encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII|STR_TERMINATE);
121 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
122 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
124 encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
125 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
126 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
128 pw2.in.server = &server;
129 pw2.in.account = &account;
130 pw2.in.nt_password = &nt_pass;
131 pw2.in.nt_verifier = &nt_verifier;
132 pw2.in.lm_change = 1;
133 pw2.in.lm_password = &lm_pass;
134 pw2.in.lm_verifier = &lm_verifier;
136 /* 3. try samr_ChangePasswordUser2 */
137 status = dcerpc_samr_ChangePasswordUser2(c.pdc.out.dcerpc_pipe, mem_ctx, &pw2);
138 if (!NT_STATUS_IS_OK(status)) {
139 r->samr.out.error_string = talloc_asprintf(mem_ctx,
140 "samr_ChangePasswordUser2 failed: %s\n",
142 goto OemChangePasswordUser2;
145 /* check result of samr_ChangePasswordUser2 */
146 if (!NT_STATUS_IS_OK(pw2.out.result)) {
147 r->samr.out.error_string = talloc_asprintf(mem_ctx,
148 "samr_ChangePasswordUser2 for '%s\\%s' failed: %s\n",
149 r->samr.in.domain_name, r->samr.in.account_name,
150 nt_errstr(pw2.out.result));
151 goto OemChangePasswordUser2;
156 OemChangePasswordUser2:
157 /* prepare samr_OemChangePasswordUser2 */
158 a_server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.pdc.out.dcerpc_pipe));
159 a_account.name = r->samr.in.account_name;
161 encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII);
162 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
163 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
165 oe2.in.server = &a_server;
166 oe2.in.account = &a_account;
167 oe2.in.password = &lm_pass;
168 oe2.in.hash = &lm_verifier;
170 /* 4. try samr_OemChangePasswordUser2 */
171 status = dcerpc_samr_OemChangePasswordUser2(c.pdc.out.dcerpc_pipe, mem_ctx, &oe2);
172 if (!NT_STATUS_IS_OK(status)) {
173 r->samr.out.error_string = talloc_asprintf(mem_ctx,
174 "samr_OemChangePasswordUser2 failed: %s\n",
176 goto ChangePasswordUser;
179 /* check result of samr_OemChangePasswordUser2 */
180 if (!NT_STATUS_IS_OK(oe2.out.result)) {
181 r->samr.out.error_string = talloc_asprintf(mem_ctx,
182 "samr_OemChangePasswordUser2 for '%s\\%s' failed: %s\n",
183 r->samr.in.domain_name, r->samr.in.account_name,
184 nt_errstr(oe2.out.result));
185 goto ChangePasswordUser;
192 /* prepare samr_ChangePasswordUser */
193 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
194 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
195 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
196 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
197 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
198 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
200 /* TODO: ask for a user_handle */
201 pw.in.handle = &user_handle;
202 pw.in.lm_present = 1;
203 pw.in.old_lm_crypted = &hash1;
204 pw.in.new_lm_crypted = &hash2;
205 pw.in.nt_present = 1;
206 pw.in.old_nt_crypted = &hash3;
207 pw.in.new_nt_crypted = &hash4;
208 pw.in.cross1_present = 1;
209 pw.in.nt_cross = &hash5;
210 pw.in.cross2_present = 1;
211 pw.in.lm_cross = &hash6;
213 /* 5. try samr_ChangePasswordUser */
214 status = dcerpc_samr_ChangePasswordUser(c.pdc.out.dcerpc_pipe, mem_ctx, &pw);
215 if (!NT_STATUS_IS_OK(status)) {
216 r->samr.out.error_string = talloc_asprintf(mem_ctx,
217 "samr_ChangePasswordUser failed: %s\n",
222 /* check result of samr_ChangePasswordUser */
223 if (!NT_STATUS_IS_OK(pw.out.result)) {
224 r->samr.out.error_string = talloc_asprintf(mem_ctx,
225 "samr_ChangePasswordUser for '%s\\%s' failed: %s\n",
226 r->samr.in.domain_name, r->samr.in.account_name,
227 nt_errstr(pw.out.result));
232 /* close connection */
233 dcerpc_pipe_close(c.pdc.out.dcerpc_pipe);
238 static NTSTATUS libnet_ChangePassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
241 union libnet_ChangePassword r2;
243 r2.samr.level = LIBNET_CHANGE_PASSWORD_SAMR;
244 r2.samr.in.account_name = r->generic.in.account_name;
245 r2.samr.in.domain_name = r->generic.in.domain_name;
246 r2.samr.in.oldpassword = r->generic.in.oldpassword;
247 r2.samr.in.newpassword = r->generic.in.newpassword;
249 status = libnet_ChangePassword(ctx, mem_ctx, &r2);
251 r->generic.out.error_string = r2.samr.out.error_string;
256 NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
258 switch (r->generic.level) {
259 case LIBNET_CHANGE_PASSWORD_GENERIC:
260 return libnet_ChangePassword_generic(ctx, mem_ctx, r);
261 case LIBNET_CHANGE_PASSWORD_SAMR:
262 return libnet_ChangePassword_samr(ctx, mem_ctx, r);
263 case LIBNET_CHANGE_PASSWORD_KRB5:
264 return NT_STATUS_NOT_IMPLEMENTED;
265 case LIBNET_CHANGE_PASSWORD_LDAP:
266 return NT_STATUS_NOT_IMPLEMENTED;
267 case LIBNET_CHANGE_PASSWORD_RAP:
268 return NT_STATUS_NOT_IMPLEMENTED;
271 return NT_STATUS_INVALID_LEVEL;
275 * set a password with DCERPC/SAMR calls
276 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
277 * is it correct to contact the the pdc of the domain of the user who's password should be set?
278 * 2. do a samr_Connect to get a policy handle
279 * 3. do a samr_LookupDomain to get the domain sid
280 * 4. do a samr_OpenDomain to get a domain handle
281 * 5. do a samr_LookupNames to get the users rid
282 * 6. do a samr_OpenUser to get a user handle
283 * 7. try samr_SetUserInfo level 26 to set the password
284 * 8. try samr_SetUserInfo level 25 to set the password
285 * 8. try samr_SetUserInfo level 24 to set the password
286 *10. try samr_SetUserInfo level 23 to set the password
288 static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
291 union libnet_rpc_connect c;
292 struct samr_Connect sc;
293 struct policy_handle p_handle;
294 struct samr_LookupDomain ld;
295 struct samr_Name d_name;
296 struct samr_OpenDomain od;
297 struct policy_handle d_handle;
298 struct samr_LookupNames ln;
299 struct samr_OpenUser ou;
300 struct policy_handle u_handle;
301 struct samr_SetUserInfo sui;
302 union samr_UserInfo u_info;
303 DATA_BLOB session_key;
304 DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
305 uint8_t confounder[16];
306 struct MD5Context md5;
308 /* prepare connect to the SAMR pipe of users domain PDC */
309 c.pdc.level = LIBNET_RPC_CONNECT_PDC;
310 c.pdc.in.domain_name = r->samr.in.domain_name;
311 c.pdc.in.dcerpc_iface_name = DCERPC_SAMR_NAME;
312 c.pdc.in.dcerpc_iface_uuid = DCERPC_SAMR_UUID;
313 c.pdc.in.dcerpc_iface_version = DCERPC_SAMR_VERSION;
315 /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
316 status = libnet_rpc_connect(ctx, mem_ctx, &c);
317 if (!NT_STATUS_IS_OK(status)) {
318 r->samr.out.error_string = talloc_asprintf(mem_ctx,
319 "Connection to SAMR pipe of PDC of domain '%s' failed: %s\n",
320 r->samr.in.domain_name, nt_errstr(status));
324 /* prepare samr_Connect */
325 ZERO_STRUCT(p_handle);
326 sc.in.system_name = 0;
327 sc.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
328 sc.out.handle = &p_handle;
330 /* 2. do a samr_Connect to get a policy handle */
331 status = dcerpc_samr_Connect(c.pdc.out.dcerpc_pipe, mem_ctx, &sc);
332 if (!NT_STATUS_IS_OK(status)) {
333 r->samr.out.error_string = talloc_asprintf(mem_ctx,
334 "samr_Connect failed: %s\n",
339 /* check result of samr_Connect */
340 if (!NT_STATUS_IS_OK(sc.out.result)) {
341 r->samr.out.error_string = talloc_asprintf(mem_ctx,
342 "samr_Connect failed: %s\n",
343 nt_errstr(sc.out.result));
347 /* prepare samr_LookupDomain */
348 d_name.name = r->samr.in.domain_name;
349 ld.in.handle = &p_handle;
350 ld.in.domain = &d_name;
352 /* 3. do a samr_LookupDomain to get the domain sid */
353 status = dcerpc_samr_LookupDomain(c.pdc.out.dcerpc_pipe, mem_ctx, &ld);
354 if (!NT_STATUS_IS_OK(status)) {
355 r->samr.out.error_string = talloc_asprintf(mem_ctx,
356 "samr_LookupDomain for [%s] failed: %s\n",
357 r->samr.in.domain_name, nt_errstr(status));
361 /* check result of samr_LookupDomain */
362 if (!NT_STATUS_IS_OK(ld.out.result)) {
363 r->samr.out.error_string = talloc_asprintf(mem_ctx,
364 "samr_LookupDomain for [%s] failed: %s\n",
365 r->samr.in.domain_name, nt_errstr(ld.out.result));
369 /* prepare samr_OpenDomain */
370 ZERO_STRUCT(d_handle);
371 od.in.handle = &p_handle;
372 od.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
373 od.in.sid = ld.out.sid;
374 od.out.domain_handle = &d_handle;
376 /* 4. do a samr_OpenDomain to get a domain handle */
377 status = dcerpc_samr_OpenDomain(c.pdc.out.dcerpc_pipe, mem_ctx, &od);
378 if (!NT_STATUS_IS_OK(status)) {
379 r->samr.out.error_string = talloc_asprintf(mem_ctx,
380 "samr_OpenDomain for [%s] failed: %s\n",
381 r->samr.in.domain_name, nt_errstr(status));
385 /* check result of samr_OpenDomain */
386 if (!NT_STATUS_IS_OK(od.out.result)) {
387 r->samr.out.error_string = talloc_asprintf(mem_ctx,
388 "samr_OpenDomain for [%s] failed: %s\n",
389 r->samr.in.domain_name, nt_errstr(od.out.result));
393 /* prepare samr_LookupNames */
394 ln.in.handle = &d_handle;
396 ln.in.names = talloc_array_p(mem_ctx, struct samr_Name, 1);
398 r->samr.out.error_string = "Out of Memory";
399 return NT_STATUS_NO_MEMORY;
401 ln.in.names[0].name = r->samr.in.account_name;
403 /* 5. do a samr_LookupNames to get the users rid */
404 status = dcerpc_samr_LookupNames(c.pdc.out.dcerpc_pipe, mem_ctx, &ln);
405 if (!NT_STATUS_IS_OK(status)) {
406 r->samr.out.error_string = talloc_asprintf(mem_ctx,
407 "samr_LookupNames for [%s] failed: %s\n",
408 r->samr.in.account_name, nt_errstr(status));
412 /* check result of samr_LookupNames */
413 if (!NT_STATUS_IS_OK(ln.out.result)) {
414 r->samr.out.error_string = talloc_asprintf(mem_ctx,
415 "samr_LookupNames for [%s] failed: %s\n",
416 r->samr.in.account_name, nt_errstr(ln.out.result));
420 /* check if we got one RID for the user */
421 if (ln.out.rids.count != 1) {
422 r->samr.out.error_string = talloc_asprintf(mem_ctx,
423 "samr_LookupNames for [%s] returns %d RIDs\n",
424 r->samr.in.account_name, ln.out.rids.count);
428 /* prepare samr_OpenUser */
429 ZERO_STRUCT(u_handle);
430 ou.in.handle = &d_handle;
431 ou.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
432 ou.in.rid = ln.out.rids.ids[0];
433 ou.out.acct_handle = &u_handle;
435 /* 6. do a samr_OpenUser to get a user handle */
436 status = dcerpc_samr_OpenUser(c.pdc.out.dcerpc_pipe, mem_ctx, &ou);
437 if (!NT_STATUS_IS_OK(status)) {
438 r->samr.out.error_string = talloc_asprintf(mem_ctx,
439 "samr_OpenUser for [%s] failed: %s\n",
440 r->samr.in.account_name, nt_errstr(status));
444 /* check result of samr_OpenUser */
445 if (!NT_STATUS_IS_OK(ou.out.result)) {
446 r->samr.out.error_string = talloc_asprintf(mem_ctx,
447 "samr_OpenUser for [%s] failed: %s\n",
448 r->samr.in.account_name, nt_errstr(ou.out.result));
452 /* prepare samr_SetUserInfo level 26 */
454 encode_pw_buffer(u_info.info26.password.data, r->samr.in.newpassword, STR_UNICODE);
455 u_info.info26.pw_len = strlen(r->samr.in.newpassword);
457 status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key);
458 if (!NT_STATUS_IS_OK(status)) {
459 r->samr.out.error_string = talloc_asprintf(mem_ctx,
460 "dcerpc_fetch_session_key failed: %s\n",
465 generate_random_buffer((uint8_t *)confounder, 16);
468 MD5Update(&md5, confounder, 16);
469 MD5Update(&md5, session_key.data, session_key.length);
470 MD5Final(confounded_session_key.data, &md5);
472 arcfour_crypt_blob(u_info.info26.password.data, 516, &confounded_session_key);
473 memcpy(&u_info.info26.password.data[516], confounder, 16);
475 sui.in.handle = &u_handle;
476 sui.in.info = &u_info;
479 /* 7. try samr_SetUserInfo level 26 to set the password */
480 status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui);
481 if (!NT_STATUS_IS_OK(status)) {
482 r->samr.out.error_string = talloc_asprintf(mem_ctx,
483 "SetUserInfo level 26 for [%s] failed: %s\n",
484 r->samr.in.account_name, nt_errstr(status));
488 /* check result of samr_SetUserInfo level 26 */
489 if (!NT_STATUS_IS_OK(sui.out.result)) {
490 r->samr.out.error_string = talloc_asprintf(mem_ctx,
491 "SetUserInfo level 26 for [%s] failed: %s\n",
492 r->samr.in.account_name, nt_errstr(sui.out.result));
499 /* prepare samr_SetUserInfo level 25 */
501 u_info.info25.info.fields_present = SAMR_FIELD_PASSWORD;
502 encode_pw_buffer(u_info.info25.password.data, r->samr.in.newpassword, STR_UNICODE);
504 status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key);
505 if (!NT_STATUS_IS_OK(status)) {
506 r->samr.out.error_string = talloc_asprintf(mem_ctx,
507 "dcerpc_fetch_session_key failed: %s\n",
512 generate_random_buffer((uint8_t *)confounder, 16);
515 MD5Update(&md5, confounder, 16);
516 MD5Update(&md5, session_key.data, session_key.length);
517 MD5Final(confounded_session_key.data, &md5);
519 arcfour_crypt_blob(u_info.info25.password.data, 516, &confounded_session_key);
520 memcpy(&u_info.info25.password.data[516], confounder, 16);
522 sui.in.handle = &u_handle;
523 sui.in.info = &u_info;
526 /* 8. try samr_SetUserInfo level 25 to set the password */
527 status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui);
528 if (!NT_STATUS_IS_OK(status)) {
529 r->samr.out.error_string = talloc_asprintf(mem_ctx,
530 "SetUserInfo level 25 for [%s] failed: %s\n",
531 r->samr.in.account_name, nt_errstr(status));
535 /* check result of samr_SetUserInfo level 25 */
536 if (!NT_STATUS_IS_OK(sui.out.result)) {
537 r->samr.out.error_string = talloc_asprintf(mem_ctx,
538 "SetUserInfo level 25 for [%s] failed: %s\n",
539 r->samr.in.account_name, nt_errstr(sui.out.result));
546 /* prepare samr_SetUserInfo level 24 */
548 encode_pw_buffer(u_info.info24.password.data, r->samr.in.newpassword, STR_UNICODE);
549 /* w2k3 ignores this length */
550 u_info.info24.pw_len = str_charnum(r->samr.in.newpassword)*2;
552 status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key);
553 if (!NT_STATUS_IS_OK(status)) {
554 r->samr.out.error_string = talloc_asprintf(mem_ctx,
555 "dcerpc_fetch_session_key failed: %s\n",
560 arcfour_crypt_blob(u_info.info24.password.data, 516, &session_key);
562 sui.in.handle = &u_handle;
563 sui.in.info = &u_info;
566 /* 9. try samr_SetUserInfo level 24 to set the password */
567 status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui);
568 if (!NT_STATUS_IS_OK(status)) {
569 r->samr.out.error_string = talloc_asprintf(mem_ctx,
570 "SetUserInfo level 24 for [%s] failed: %s\n",
571 r->samr.in.account_name, nt_errstr(status));
575 /* check result of samr_SetUserInfo level 24 */
576 if (!NT_STATUS_IS_OK(sui.out.result)) {
577 r->samr.out.error_string = talloc_asprintf(mem_ctx,
578 "SetUserInfo level 24 for [%s] failed: %s\n",
579 r->samr.in.account_name, nt_errstr(sui.out.result));
586 /* prepare samr_SetUserInfo level 23 */
588 u_info.info23.info.fields_present = SAMR_FIELD_PASSWORD;
589 encode_pw_buffer(u_info.info23.password.data, r->samr.in.newpassword, STR_UNICODE);
591 status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key);
592 if (!NT_STATUS_IS_OK(status)) {
593 r->samr.out.error_string = talloc_asprintf(mem_ctx,
594 "dcerpc_fetch_session_key failed: %s\n",
599 arcfour_crypt_blob(u_info.info23.password.data, 516, &session_key);
601 sui.in.handle = &u_handle;
602 sui.in.info = &u_info;
605 /* 10. try samr_SetUserInfo level 23 to set the password */
606 status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui);
607 if (!NT_STATUS_IS_OK(status)) {
608 r->samr.out.error_string = talloc_asprintf(mem_ctx,
609 "SetUserInfo level 23 for [%s] failed: %s\n",
610 r->samr.in.account_name, nt_errstr(status));
614 /* check result of samr_SetUserInfo level 23 */
615 if (!NT_STATUS_IS_OK(sui.out.result)) {
616 r->samr.out.error_string = talloc_asprintf(mem_ctx,
617 "SetUserInfo level 23 for [%s] failed: %s\n",
618 r->samr.in.account_name, nt_errstr(sui.out.result));
625 /* close connection */
626 dcerpc_pipe_close(c.pdc.out.dcerpc_pipe);
631 static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
634 union libnet_SetPassword r2;
636 r2.samr.level = LIBNET_SET_PASSWORD_SAMR;
637 r2.samr.in.account_name = r->generic.in.account_name;
638 r2.samr.in.domain_name = r->generic.in.domain_name;
639 r2.samr.in.newpassword = r->generic.in.newpassword;
641 status = libnet_SetPassword(ctx, mem_ctx, &r2);
643 r->generic.out.error_string = r2.samr.out.error_string;
648 NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
650 switch (r->generic.level) {
651 case LIBNET_SET_PASSWORD_GENERIC:
652 return libnet_SetPassword_generic(ctx, mem_ctx, r);
653 case LIBNET_SET_PASSWORD_SAMR:
654 return libnet_SetPassword_samr(ctx, mem_ctx, r);
655 case LIBNET_SET_PASSWORD_KRB5:
656 return NT_STATUS_NOT_IMPLEMENTED;
657 case LIBNET_SET_PASSWORD_LDAP:
658 return NT_STATUS_NOT_IMPLEMENTED;
659 case LIBNET_SET_PASSWORD_RAP:
660 return NT_STATUS_NOT_IMPLEMENTED;
663 return NT_STATUS_INVALID_LEVEL;