2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2004
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "libnet/libnet.h"
23 #include "../lib/crypto/crypto.h"
24 #include "libcli/auth/libcli_auth.h"
25 #include "librpc/gen_ndr/ndr_samr_c.h"
28 * do a password change using DCERPC/SAMR calls
29 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
30 * 2. try samr_ChangePasswordUser3
31 * 3. try samr_ChangePasswordUser2
32 * 4. try samr_OemChangePasswordUser2
33 * (not yet: 5. try samr_ChangePasswordUser)
35 static NTSTATUS
libnet_ChangePassword_samr(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_ChangePassword
*r
)
38 struct libnet_RpcConnect c
;
40 struct policy_handle user_handle
;
41 struct samr_Password hash1
, hash2
, hash3
, hash4
, hash5
, hash6
;
42 struct samr_ChangePasswordUser pw
;
44 struct samr_OemChangePasswordUser2 oe2
;
45 struct samr_ChangePasswordUser2 pw2
;
46 struct samr_ChangePasswordUser3 pw3
;
47 struct lsa_String server
, account
;
48 struct lsa_AsciiString a_server
, a_account
;
49 struct samr_CryptPassword nt_pass
, lm_pass
;
50 struct samr_Password nt_verifier
, lm_verifier
;
51 uint8_t old_nt_hash
[16], new_nt_hash
[16];
52 uint8_t old_lm_hash
[16], new_lm_hash
[16];
53 struct samr_DomInfo1
*dominfo
= NULL
;
54 struct userPwdChangeFailureInformation
*reject
= NULL
;
58 /* prepare connect to the SAMR pipe of the users domain PDC */
59 c
.level
= LIBNET_RPC_CONNECT_PDC
;
60 c
.in
.name
= r
->samr
.in
.domain_name
;
61 c
.in
.dcerpc_iface
= &ndr_table_samr
;
62 c
.in
.dcerpc_flags
= DCERPC_ANON_FALLBACK
;
64 /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
65 status
= libnet_RpcConnect(ctx
, mem_ctx
, &c
);
66 if (!NT_STATUS_IS_OK(status
)) {
67 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
68 "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
69 r
->samr
.in
.domain_name
, nt_errstr(status
));
73 /* prepare password change for account */
74 server
.string
= talloc_asprintf(mem_ctx
, "\\\\%s", dcerpc_server_name(c
.out
.dcerpc_pipe
));
75 account
.string
= r
->samr
.in
.account_name
;
77 E_md4hash(r
->samr
.in
.oldpassword
, old_nt_hash
);
78 E_md4hash(r
->samr
.in
.newpassword
, new_nt_hash
);
80 E_deshash(r
->samr
.in
.oldpassword
, old_lm_hash
);
81 E_deshash(r
->samr
.in
.newpassword
, new_lm_hash
);
83 /* prepare samr_ChangePasswordUser3 */
84 encode_pw_buffer(lm_pass
.data
, r
->samr
.in
.newpassword
, STR_UNICODE
);
85 arcfour_crypt(lm_pass
.data
, old_nt_hash
, 516);
86 E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
88 encode_pw_buffer(nt_pass
.data
, r
->samr
.in
.newpassword
, STR_UNICODE
);
89 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
90 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
92 pw3
.in
.server
= &server
;
93 pw3
.in
.account
= &account
;
94 pw3
.in
.nt_password
= &nt_pass
;
95 pw3
.in
.nt_verifier
= &nt_verifier
;
97 pw3
.in
.lm_password
= &lm_pass
;
98 pw3
.in
.lm_verifier
= &lm_verifier
;
99 pw3
.in
.password3
= NULL
;
100 pw3
.out
.dominfo
= &dominfo
;
101 pw3
.out
.reject
= &reject
;
103 /* 2. try samr_ChangePasswordUser3 */
104 status
= dcerpc_samr_ChangePasswordUser3_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &pw3
);
105 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
106 if (!NT_STATUS_IS_OK(status
)) {
107 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
108 "samr_ChangePasswordUser3 failed: %s",
110 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
111 "samr_ChangePasswordUser3 for '%s\\%s' failed: %s",
112 r
->samr
.in
.domain_name
, r
->samr
.in
.account_name
,
118 /* prepare samr_ChangePasswordUser2 */
119 encode_pw_buffer(lm_pass
.data
, r
->samr
.in
.newpassword
, STR_ASCII
|STR_TERMINATE
);
120 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
121 E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
123 encode_pw_buffer(nt_pass
.data
, r
->samr
.in
.newpassword
, STR_UNICODE
);
124 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
125 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
127 pw2
.in
.server
= &server
;
128 pw2
.in
.account
= &account
;
129 pw2
.in
.nt_password
= &nt_pass
;
130 pw2
.in
.nt_verifier
= &nt_verifier
;
131 pw2
.in
.lm_change
= 1;
132 pw2
.in
.lm_password
= &lm_pass
;
133 pw2
.in
.lm_verifier
= &lm_verifier
;
135 /* 3. try samr_ChangePasswordUser2 */
136 status
= dcerpc_samr_ChangePasswordUser2_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &pw2
);
137 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
138 if (!NT_STATUS_IS_OK(status
)) {
139 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
140 "samr_ChangePasswordUser2 for '%s\\%s' failed: %s",
141 r
->samr
.in
.domain_name
, r
->samr
.in
.account_name
,
148 /* prepare samr_OemChangePasswordUser2 */
149 a_server
.string
= talloc_asprintf(mem_ctx
, "\\\\%s", dcerpc_server_name(c
.out
.dcerpc_pipe
));
150 a_account
.string
= r
->samr
.in
.account_name
;
152 encode_pw_buffer(lm_pass
.data
, r
->samr
.in
.newpassword
, STR_ASCII
);
153 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
154 E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
156 oe2
.in
.server
= &a_server
;
157 oe2
.in
.account
= &a_account
;
158 oe2
.in
.password
= &lm_pass
;
159 oe2
.in
.hash
= &lm_verifier
;
161 /* 4. try samr_OemChangePasswordUser2 */
162 status
= dcerpc_samr_OemChangePasswordUser2_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &oe2
);
163 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
164 if (!NT_STATUS_IS_OK(oe2
.out
.result
)) {
165 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
166 "samr_OemChangePasswordUser2 for '%s\\%s' failed: %s",
167 r
->samr
.in
.domain_name
, r
->samr
.in
.account_name
,
174 /* prepare samr_ChangePasswordUser */
175 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
176 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
177 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
178 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
179 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
180 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
182 /* TODO: ask for a user_handle */
183 pw
.in
.handle
= &user_handle
;
184 pw
.in
.lm_present
= 1;
185 pw
.in
.old_lm_crypted
= &hash1
;
186 pw
.in
.new_lm_crypted
= &hash2
;
187 pw
.in
.nt_present
= 1;
188 pw
.in
.old_nt_crypted
= &hash3
;
189 pw
.in
.new_nt_crypted
= &hash4
;
190 pw
.in
.cross1_present
= 1;
191 pw
.in
.nt_cross
= &hash5
;
192 pw
.in
.cross2_present
= 1;
193 pw
.in
.lm_cross
= &hash6
;
195 /* 5. try samr_ChangePasswordUser */
196 status
= dcerpc_samr_ChangePasswordUser_r(c
.pdc
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &pw
);
197 if (!NT_STATUS_IS_OK(status
)) {
198 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
199 "samr_ChangePasswordUser failed: %s",
204 /* check result of samr_ChangePasswordUser */
205 if (!NT_STATUS_IS_OK(pw
.out
.result
)) {
206 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
207 "samr_ChangePasswordUser for '%s\\%s' failed: %s",
208 r
->samr
.in
.domain_name
, r
->samr
.in
.account_name
,
209 nt_errstr(pw
.out
.result
));
210 if (NT_STATUS_EQUAL(pw
.out
.result
, NT_STATUS_PASSWORD_RESTRICTION
)) {
211 status
= pw
.out
.result
;
218 /* close connection */
219 talloc_unlink(ctx
, c
.out
.dcerpc_pipe
);
224 static NTSTATUS
libnet_ChangePassword_generic(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_ChangePassword
*r
)
227 union libnet_ChangePassword r2
;
229 r2
.samr
.level
= LIBNET_CHANGE_PASSWORD_SAMR
;
230 r2
.samr
.in
.account_name
= r
->generic
.in
.account_name
;
231 r2
.samr
.in
.domain_name
= r
->generic
.in
.domain_name
;
232 r2
.samr
.in
.oldpassword
= r
->generic
.in
.oldpassword
;
233 r2
.samr
.in
.newpassword
= r
->generic
.in
.newpassword
;
235 status
= libnet_ChangePassword(ctx
, mem_ctx
, &r2
);
237 r
->generic
.out
.error_string
= r2
.samr
.out
.error_string
;
242 NTSTATUS
libnet_ChangePassword(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_ChangePassword
*r
)
244 switch (r
->generic
.level
) {
245 case LIBNET_CHANGE_PASSWORD_GENERIC
:
246 return libnet_ChangePassword_generic(ctx
, mem_ctx
, r
);
247 case LIBNET_CHANGE_PASSWORD_SAMR
:
248 return libnet_ChangePassword_samr(ctx
, mem_ctx
, r
);
249 case LIBNET_CHANGE_PASSWORD_KRB5
:
250 return NT_STATUS_NOT_IMPLEMENTED
;
251 case LIBNET_CHANGE_PASSWORD_LDAP
:
252 return NT_STATUS_NOT_IMPLEMENTED
;
253 case LIBNET_CHANGE_PASSWORD_RAP
:
254 return NT_STATUS_NOT_IMPLEMENTED
;
257 return NT_STATUS_INVALID_LEVEL
;
260 static NTSTATUS
libnet_SetPassword_samr_handle_26(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
263 struct samr_SetUserInfo2 sui
;
264 union samr_UserInfo u_info
;
265 DATA_BLOB session_key
;
266 DATA_BLOB confounded_session_key
= data_blob_talloc(mem_ctx
, NULL
, 16);
267 uint8_t confounder
[16];
268 struct MD5Context md5
;
270 if (r
->samr_handle
.in
.info21
) {
271 return NT_STATUS_INVALID_PARAMETER_MIX
;
274 /* prepare samr_SetUserInfo2 level 26 */
276 encode_pw_buffer(u_info
.info26
.password
.data
, r
->samr_handle
.in
.newpassword
, STR_UNICODE
);
277 u_info
.info26
.password_expired
= 0;
279 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
280 if (!NT_STATUS_IS_OK(status
)) {
281 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
282 "dcerpc_fetch_session_key failed: %s",
287 generate_random_buffer((uint8_t *)confounder
, 16);
290 MD5Update(&md5
, confounder
, 16);
291 MD5Update(&md5
, session_key
.data
, session_key
.length
);
292 MD5Final(confounded_session_key
.data
, &md5
);
294 arcfour_crypt_blob(u_info
.info26
.password
.data
, 516, &confounded_session_key
);
295 memcpy(&u_info
.info26
.password
.data
[516], confounder
, 16);
297 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
298 sui
.in
.info
= &u_info
;
301 /* 7. try samr_SetUserInfo2 level 26 to set the password */
302 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
303 /* check result of samr_SetUserInfo2 level 26 */
304 if (!NT_STATUS_IS_OK(status
)) {
305 r
->samr_handle
.out
.error_string
306 = talloc_asprintf(mem_ctx
,
307 "SetUserInfo2 level 26 for [%s] failed: %s",
308 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
313 static NTSTATUS
libnet_SetPassword_samr_handle_25(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
316 struct samr_SetUserInfo2 sui
;
317 union samr_UserInfo u_info
;
318 DATA_BLOB session_key
;
319 DATA_BLOB confounded_session_key
= data_blob_talloc(mem_ctx
, NULL
, 16);
320 uint8_t confounder
[16];
321 struct MD5Context md5
;
323 if (!r
->samr_handle
.in
.info21
) {
324 return NT_STATUS_INVALID_PARAMETER_MIX
;
327 /* prepare samr_SetUserInfo2 level 25 */
329 u_info
.info25
.info
= *r
->samr_handle
.in
.info21
;
330 u_info
.info25
.info
.fields_present
|= SAMR_FIELD_NT_PASSWORD_PRESENT
;
331 encode_pw_buffer(u_info
.info25
.password
.data
, r
->samr_handle
.in
.newpassword
, STR_UNICODE
);
333 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
334 if (!NT_STATUS_IS_OK(status
)) {
335 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
336 "dcerpc_fetch_session_key failed: %s",
341 generate_random_buffer((uint8_t *)confounder
, 16);
344 MD5Update(&md5
, confounder
, 16);
345 MD5Update(&md5
, session_key
.data
, session_key
.length
);
346 MD5Final(confounded_session_key
.data
, &md5
);
348 arcfour_crypt_blob(u_info
.info25
.password
.data
, 516, &confounded_session_key
);
349 memcpy(&u_info
.info25
.password
.data
[516], confounder
, 16);
351 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
352 sui
.in
.info
= &u_info
;
355 /* 8. try samr_SetUserInfo2 level 25 to set the password */
356 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
357 if (!NT_STATUS_IS_OK(status
)) {
358 r
->samr_handle
.out
.error_string
359 = talloc_asprintf(mem_ctx
,
360 "SetUserInfo2 level 25 for [%s] failed: %s",
361 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
366 static NTSTATUS
libnet_SetPassword_samr_handle_24(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
369 struct samr_SetUserInfo2 sui
;
370 union samr_UserInfo u_info
;
371 DATA_BLOB session_key
;
373 if (r
->samr_handle
.in
.info21
) {
374 return NT_STATUS_INVALID_PARAMETER_MIX
;
377 /* prepare samr_SetUserInfo2 level 24 */
379 encode_pw_buffer(u_info
.info24
.password
.data
, r
->samr_handle
.in
.newpassword
, STR_UNICODE
);
380 u_info
.info24
.password_expired
= 0;
382 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
383 if (!NT_STATUS_IS_OK(status
)) {
384 r
->samr_handle
.out
.error_string
= talloc_asprintf(mem_ctx
,
385 "dcerpc_fetch_session_key failed: %s",
390 arcfour_crypt_blob(u_info
.info24
.password
.data
, 516, &session_key
);
392 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
393 sui
.in
.info
= &u_info
;
396 /* 9. try samr_SetUserInfo2 level 24 to set the password */
397 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
398 if (!NT_STATUS_IS_OK(status
)) {
399 r
->samr_handle
.out
.error_string
400 = talloc_asprintf(mem_ctx
,
401 "SetUserInfo2 level 24 for [%s] failed: %s",
402 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
407 static NTSTATUS
libnet_SetPassword_samr_handle_23(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
410 struct samr_SetUserInfo2 sui
;
411 union samr_UserInfo u_info
;
412 DATA_BLOB session_key
;
414 if (!r
->samr_handle
.in
.info21
) {
415 return NT_STATUS_INVALID_PARAMETER_MIX
;
418 /* prepare samr_SetUserInfo2 level 23 */
420 u_info
.info23
.info
= *r
->samr_handle
.in
.info21
;
421 u_info
.info23
.info
.fields_present
|= SAMR_FIELD_NT_PASSWORD_PRESENT
;
422 encode_pw_buffer(u_info
.info23
.password
.data
, r
->samr_handle
.in
.newpassword
, STR_UNICODE
);
424 status
= dcerpc_fetch_session_key(r
->samr_handle
.in
.dcerpc_pipe
, &session_key
);
425 if (!NT_STATUS_IS_OK(status
)) {
426 r
->samr_handle
.out
.error_string
427 = talloc_asprintf(mem_ctx
,
428 "dcerpc_fetch_session_key failed: %s",
433 arcfour_crypt_blob(u_info
.info23
.password
.data
, 516, &session_key
);
435 sui
.in
.user_handle
= r
->samr_handle
.in
.user_handle
;
436 sui
.in
.info
= &u_info
;
439 /* 10. try samr_SetUserInfo2 level 23 to set the password */
440 status
= dcerpc_samr_SetUserInfo2_r(r
->samr_handle
.in
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sui
);
441 if (!NT_STATUS_IS_OK(status
)) {
442 r
->samr_handle
.out
.error_string
443 = talloc_asprintf(mem_ctx
,
444 "SetUserInfo2 level 23 for [%s] failed: %s",
445 r
->samr_handle
.in
.account_name
, nt_errstr(status
));
451 * 1. try samr_SetUserInfo2 level 26 to set the password
452 * 2. try samr_SetUserInfo2 level 25 to set the password
453 * 3. try samr_SetUserInfo2 level 24 to set the password
454 * 4. try samr_SetUserInfo2 level 23 to set the password
456 static NTSTATUS
libnet_SetPassword_samr_handle(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
460 enum libnet_SetPassword_level levels
[] = {
461 LIBNET_SET_PASSWORD_SAMR_HANDLE_26
,
462 LIBNET_SET_PASSWORD_SAMR_HANDLE_25
,
463 LIBNET_SET_PASSWORD_SAMR_HANDLE_24
,
464 LIBNET_SET_PASSWORD_SAMR_HANDLE_23
,
468 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
469 r
->generic
.level
= levels
[i
];
470 status
= libnet_SetPassword(ctx
, mem_ctx
, r
);
471 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_INFO_CLASS
)
472 || NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER_MIX
)
473 || NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
474 /* Try another password set mechanism */
483 * set a password with DCERPC/SAMR calls
484 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
485 * is it correct to contact the the pdc of the domain of the user who's password should be set?
486 * 2. do a samr_Connect to get a policy handle
487 * 3. do a samr_LookupDomain to get the domain sid
488 * 4. do a samr_OpenDomain to get a domain handle
489 * 5. do a samr_LookupNames to get the users rid
490 * 6. do a samr_OpenUser to get a user handle
491 * 7 call libnet_SetPassword_samr_handle to set the password
493 static NTSTATUS
libnet_SetPassword_samr(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
496 struct libnet_RpcConnect c
;
497 struct samr_Connect sc
;
498 struct policy_handle p_handle
;
499 struct samr_LookupDomain ld
;
500 struct dom_sid2
*sid
= NULL
;
501 struct lsa_String d_name
;
502 struct samr_OpenDomain od
;
503 struct policy_handle d_handle
;
504 struct samr_LookupNames ln
;
505 struct samr_Ids rids
, types
;
506 struct samr_OpenUser ou
;
507 struct policy_handle u_handle
;
508 union libnet_SetPassword r2
;
511 /* prepare connect to the SAMR pipe of users domain PDC */
512 c
.level
= LIBNET_RPC_CONNECT_PDC
;
513 c
.in
.name
= r
->samr
.in
.domain_name
;
514 c
.in
.dcerpc_iface
= &ndr_table_samr
;
516 /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
517 status
= libnet_RpcConnect(ctx
, mem_ctx
, &c
);
518 if (!NT_STATUS_IS_OK(status
)) {
519 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
520 "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
521 r
->samr
.in
.domain_name
, nt_errstr(status
));
525 /* prepare samr_Connect */
526 ZERO_STRUCT(p_handle
);
527 sc
.in
.system_name
= NULL
;
528 sc
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
529 sc
.out
.connect_handle
= &p_handle
;
531 /* 2. do a samr_Connect to get a policy handle */
532 status
= dcerpc_samr_Connect_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &sc
);
533 if (!NT_STATUS_IS_OK(status
)) {
534 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
535 "samr_Connect failed: %s",
540 /* prepare samr_LookupDomain */
541 d_name
.string
= r
->samr
.in
.domain_name
;
542 ld
.in
.connect_handle
= &p_handle
;
543 ld
.in
.domain_name
= &d_name
;
546 /* 3. do a samr_LookupDomain to get the domain sid */
547 status
= dcerpc_samr_LookupDomain_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &ld
);
548 if (!NT_STATUS_IS_OK(status
)) {
549 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
550 "samr_LookupDomain for [%s] failed: %s",
551 r
->samr
.in
.domain_name
, nt_errstr(status
));
555 /* prepare samr_OpenDomain */
556 ZERO_STRUCT(d_handle
);
557 od
.in
.connect_handle
= &p_handle
;
558 od
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
559 od
.in
.sid
= *ld
.out
.sid
;
560 od
.out
.domain_handle
= &d_handle
;
562 /* 4. do a samr_OpenDomain to get a domain handle */
563 status
= dcerpc_samr_OpenDomain_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &od
);
564 if (!NT_STATUS_IS_OK(status
)) {
565 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
566 "samr_OpenDomain for [%s] failed: %s",
567 r
->samr
.in
.domain_name
, nt_errstr(status
));
571 /* prepare samr_LookupNames */
572 ln
.in
.domain_handle
= &d_handle
;
574 ln
.in
.names
= talloc_array(mem_ctx
, struct lsa_String
, 1);
576 ln
.out
.types
= &types
;
578 r
->samr
.out
.error_string
= "Out of Memory";
579 return NT_STATUS_NO_MEMORY
;
581 ln
.in
.names
[0].string
= r
->samr
.in
.account_name
;
583 /* 5. do a samr_LookupNames to get the users rid */
584 status
= dcerpc_samr_LookupNames_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &ln
);
585 if (!NT_STATUS_IS_OK(status
)) {
586 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
587 "samr_LookupNames for [%s] failed: %s",
588 r
->samr
.in
.account_name
, nt_errstr(status
));
592 /* check if we got one RID for the user */
593 if (ln
.out
.rids
->count
!= 1) {
594 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
595 "samr_LookupNames for [%s] returns %d RIDs",
596 r
->samr
.in
.account_name
, ln
.out
.rids
->count
);
597 status
= NT_STATUS_INVALID_PARAMETER
;
601 /* prepare samr_OpenUser */
602 ZERO_STRUCT(u_handle
);
603 ou
.in
.domain_handle
= &d_handle
;
604 ou
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
605 ou
.in
.rid
= ln
.out
.rids
->ids
[0];
606 ou
.out
.user_handle
= &u_handle
;
608 /* 6. do a samr_OpenUser to get a user handle */
609 status
= dcerpc_samr_OpenUser_r(c
.out
.dcerpc_pipe
->binding_handle
, mem_ctx
, &ou
);
610 if (!NT_STATUS_IS_OK(status
)) {
611 r
->samr
.out
.error_string
= talloc_asprintf(mem_ctx
,
612 "samr_OpenUser for [%s] failed: %s",
613 r
->samr
.in
.account_name
, nt_errstr(status
));
617 r2
.samr_handle
.level
= LIBNET_SET_PASSWORD_SAMR_HANDLE
;
618 r2
.samr_handle
.in
.account_name
= r
->samr
.in
.account_name
;
619 r2
.samr_handle
.in
.newpassword
= r
->samr
.in
.newpassword
;
620 r2
.samr_handle
.in
.user_handle
= &u_handle
;
621 r2
.samr_handle
.in
.dcerpc_pipe
= c
.out
.dcerpc_pipe
;
622 r2
.samr_handle
.in
.info21
= NULL
;
624 status
= libnet_SetPassword(ctx
, mem_ctx
, &r2
);
626 r
->generic
.out
.error_string
= r2
.samr_handle
.out
.error_string
;
629 /* close connection */
630 talloc_unlink(ctx
, c
.out
.dcerpc_pipe
);
635 static NTSTATUS
libnet_SetPassword_generic(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
638 union libnet_SetPassword r2
;
640 r2
.samr
.level
= LIBNET_SET_PASSWORD_SAMR
;
641 r2
.samr
.in
.account_name
= r
->generic
.in
.account_name
;
642 r2
.samr
.in
.domain_name
= r
->generic
.in
.domain_name
;
643 r2
.samr
.in
.newpassword
= r
->generic
.in
.newpassword
;
645 r
->generic
.out
.error_string
= "Unknown Error";
646 status
= libnet_SetPassword(ctx
, mem_ctx
, &r2
);
648 r
->generic
.out
.error_string
= r2
.samr
.out
.error_string
;
653 NTSTATUS
libnet_SetPassword(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, union libnet_SetPassword
*r
)
655 switch (r
->generic
.level
) {
656 case LIBNET_SET_PASSWORD_GENERIC
:
657 return libnet_SetPassword_generic(ctx
, mem_ctx
, r
);
658 case LIBNET_SET_PASSWORD_SAMR
:
659 return libnet_SetPassword_samr(ctx
, mem_ctx
, r
);
660 case LIBNET_SET_PASSWORD_SAMR_HANDLE
:
661 return libnet_SetPassword_samr_handle(ctx
, mem_ctx
, r
);
662 case LIBNET_SET_PASSWORD_SAMR_HANDLE_26
:
663 return libnet_SetPassword_samr_handle_26(ctx
, mem_ctx
, r
);
664 case LIBNET_SET_PASSWORD_SAMR_HANDLE_25
:
665 return libnet_SetPassword_samr_handle_25(ctx
, mem_ctx
, r
);
666 case LIBNET_SET_PASSWORD_SAMR_HANDLE_24
:
667 return libnet_SetPassword_samr_handle_24(ctx
, mem_ctx
, r
);
668 case LIBNET_SET_PASSWORD_SAMR_HANDLE_23
:
669 return libnet_SetPassword_samr_handle_23(ctx
, mem_ctx
, r
);
670 case LIBNET_SET_PASSWORD_KRB5
:
671 return NT_STATUS_NOT_IMPLEMENTED
;
672 case LIBNET_SET_PASSWORD_LDAP
:
673 return NT_STATUS_NOT_IMPLEMENTED
;
674 case LIBNET_SET_PASSWORD_RAP
:
675 return NT_STATUS_NOT_IMPLEMENTED
;
678 return NT_STATUS_INVALID_LEVEL
;