Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2004
5 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "libnet/libnet.h"
23 : #include "libcli/auth/libcli_auth.h"
24 : #include "librpc/gen_ndr/ndr_samr_c.h"
25 : #include "source4/librpc/rpc/dcerpc.h"
26 : #include "auth/credentials/credentials.h"
27 : #include "libcli/smb/smb_constants.h"
28 :
29 : #include "lib/crypto/gnutls_helpers.h"
30 : #include <gnutls/gnutls.h>
31 : #include <gnutls/crypto.h>
32 :
33 : /*
34 : * do a password change using DCERPC/SAMR calls
35 : * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
36 : * 2. try samr_ChangePasswordUser3
37 : * 3. try samr_ChangePasswordUser2
38 : * 4. try samr_OemChangePasswordUser2
39 : * (not yet: 5. try samr_ChangePasswordUser)
40 : */
41 42 : static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
42 : {
43 2 : NTSTATUS status;
44 2 : struct libnet_RpcConnect c;
45 : #if 0
46 : struct policy_handle user_handle;
47 : struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
48 : struct samr_ChangePasswordUser pw;
49 : #endif
50 2 : struct samr_OemChangePasswordUser2 oe2;
51 2 : struct samr_ChangePasswordUser2 pw2;
52 2 : struct samr_ChangePasswordUser3 pw3;
53 2 : struct lsa_String server, account;
54 2 : struct lsa_AsciiString a_server, a_account;
55 2 : struct samr_CryptPassword nt_pass, lm_pass;
56 2 : struct samr_Password nt_verifier, lm_verifier;
57 2 : uint8_t old_nt_hash[16], new_nt_hash[16];
58 2 : uint8_t old_lm_hash[16], new_lm_hash[16];
59 42 : struct samr_DomInfo1 *dominfo = NULL;
60 42 : struct userPwdChangeFailureInformation *reject = NULL;
61 42 : gnutls_cipher_hd_t cipher_hnd = NULL;
62 42 : gnutls_datum_t nt_session_key = {
63 : .data = old_nt_hash,
64 : .size = sizeof(old_nt_hash),
65 : };
66 42 : gnutls_datum_t lm_session_key = {
67 : .data = old_lm_hash,
68 : .size = sizeof(old_lm_hash),
69 : };
70 2 : int rc;
71 :
72 42 : ZERO_STRUCT(c);
73 :
74 : /* prepare connect to the SAMR pipe of the users domain PDC */
75 42 : c.level = LIBNET_RPC_CONNECT_PDC;
76 42 : c.in.name = r->samr.in.domain_name;
77 42 : c.in.dcerpc_iface = &ndr_table_samr;
78 42 : c.in.dcerpc_flags = DCERPC_ANON_FALLBACK;
79 :
80 : /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
81 42 : status = libnet_RpcConnect(ctx, mem_ctx, &c);
82 42 : if (!NT_STATUS_IS_OK(status)) {
83 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
84 : "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
85 : r->samr.in.domain_name, nt_errstr(status));
86 0 : return status;
87 : }
88 :
89 : /* prepare password change for account */
90 42 : server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
91 42 : account.string = r->samr.in.account_name;
92 :
93 42 : E_md4hash(r->samr.in.oldpassword, old_nt_hash);
94 42 : E_md4hash(r->samr.in.newpassword, new_nt_hash);
95 :
96 42 : E_deshash(r->samr.in.oldpassword, old_lm_hash);
97 42 : E_deshash(r->samr.in.newpassword, new_lm_hash);
98 :
99 : /* prepare samr_ChangePasswordUser3 */
100 42 : encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_UNICODE);
101 :
102 42 : rc = gnutls_cipher_init(&cipher_hnd,
103 : GNUTLS_CIPHER_ARCFOUR_128,
104 : &nt_session_key,
105 : NULL);
106 42 : if (rc < 0) {
107 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
108 0 : goto disconnect;
109 : }
110 :
111 42 : rc = gnutls_cipher_encrypt(cipher_hnd,
112 : lm_pass.data,
113 : 516);
114 42 : gnutls_cipher_deinit(cipher_hnd);
115 42 : if (rc < 0) {
116 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
117 0 : goto disconnect;
118 : }
119 :
120 42 : rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
121 42 : if (rc != 0) {
122 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
123 0 : goto disconnect;
124 : }
125 :
126 42 : encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
127 :
128 42 : rc = gnutls_cipher_init(&cipher_hnd,
129 : GNUTLS_CIPHER_ARCFOUR_128,
130 : &nt_session_key,
131 : NULL);
132 42 : if (rc < 0) {
133 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
134 0 : goto disconnect;
135 : }
136 :
137 42 : rc = gnutls_cipher_encrypt(cipher_hnd,
138 : nt_pass.data,
139 : 516);
140 42 : gnutls_cipher_deinit(cipher_hnd);
141 42 : if (rc < 0) {
142 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
143 0 : goto disconnect;
144 : }
145 :
146 42 : rc = E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
147 42 : if (rc != 0) {
148 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
149 0 : goto disconnect;
150 : }
151 :
152 42 : pw3.in.server = &server;
153 42 : pw3.in.account = &account;
154 42 : pw3.in.nt_password = &nt_pass;
155 42 : pw3.in.nt_verifier = &nt_verifier;
156 42 : pw3.in.lm_change = 1;
157 42 : pw3.in.lm_password = &lm_pass;
158 42 : pw3.in.lm_verifier = &lm_verifier;
159 42 : pw3.in.password3 = NULL;
160 42 : pw3.out.dominfo = &dominfo;
161 42 : pw3.out.reject = &reject;
162 :
163 : /* 2. try samr_ChangePasswordUser3 */
164 42 : status = dcerpc_samr_ChangePasswordUser3_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &pw3);
165 42 : if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
166 42 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pw3.out.result)) {
167 21 : status = pw3.out.result;
168 : }
169 42 : if (!NT_STATUS_IS_OK(status)) {
170 21 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
171 : "samr_ChangePasswordUser3 failed: %s",
172 : nt_errstr(status));
173 21 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
174 : "samr_ChangePasswordUser3 for '%s\\%s' failed: %s",
175 : r->samr.in.domain_name, r->samr.in.account_name,
176 : nt_errstr(status));
177 : }
178 2 : goto disconnect;
179 : }
180 :
181 : /* prepare samr_ChangePasswordUser2 */
182 0 : encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII|STR_TERMINATE);
183 :
184 0 : rc = gnutls_cipher_init(&cipher_hnd,
185 : GNUTLS_CIPHER_ARCFOUR_128,
186 : &lm_session_key,
187 : NULL);
188 0 : if (rc < 0) {
189 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
190 0 : goto disconnect;
191 : }
192 :
193 0 : rc = gnutls_cipher_encrypt(cipher_hnd,
194 : lm_pass.data,
195 : 516);
196 0 : gnutls_cipher_deinit(cipher_hnd);
197 0 : if (rc < 0) {
198 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
199 0 : goto disconnect;
200 : }
201 :
202 0 : rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
203 0 : if (rc != 0) {
204 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
205 0 : goto disconnect;
206 : }
207 :
208 0 : encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
209 :
210 0 : rc = gnutls_cipher_init(&cipher_hnd,
211 : GNUTLS_CIPHER_ARCFOUR_128,
212 : &nt_session_key,
213 : NULL);
214 0 : if (rc < 0) {
215 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
216 0 : goto disconnect;
217 : }
218 0 : rc = gnutls_cipher_encrypt(cipher_hnd,
219 : nt_pass.data,
220 : 516);
221 0 : gnutls_cipher_deinit(cipher_hnd);
222 0 : if (rc < 0) {
223 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
224 0 : goto disconnect;
225 : }
226 :
227 0 : rc = E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
228 0 : if (rc != 0) {
229 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
230 0 : goto disconnect;
231 : }
232 :
233 0 : pw2.in.server = &server;
234 0 : pw2.in.account = &account;
235 0 : pw2.in.nt_password = &nt_pass;
236 0 : pw2.in.nt_verifier = &nt_verifier;
237 0 : pw2.in.lm_change = 1;
238 0 : pw2.in.lm_password = &lm_pass;
239 0 : pw2.in.lm_verifier = &lm_verifier;
240 :
241 : /* 3. try samr_ChangePasswordUser2 */
242 0 : status = dcerpc_samr_ChangePasswordUser2_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &pw2);
243 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
244 0 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pw2.out.result)) {
245 0 : status = pw2.out.result;
246 : }
247 0 : if (!NT_STATUS_IS_OK(status)) {
248 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
249 : "samr_ChangePasswordUser2 for '%s\\%s' failed: %s",
250 : r->samr.in.domain_name, r->samr.in.account_name,
251 : nt_errstr(status));
252 : }
253 0 : goto disconnect;
254 : }
255 :
256 :
257 : /* prepare samr_OemChangePasswordUser2 */
258 0 : a_server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
259 0 : a_account.string = r->samr.in.account_name;
260 :
261 0 : encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII);
262 :
263 0 : rc = gnutls_cipher_init(&cipher_hnd,
264 : GNUTLS_CIPHER_ARCFOUR_128,
265 : &lm_session_key,
266 : NULL);
267 0 : if (rc < 0) {
268 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
269 0 : goto disconnect;
270 : }
271 :
272 0 : rc = gnutls_cipher_encrypt(cipher_hnd,
273 : lm_pass.data,
274 : 516);
275 0 : gnutls_cipher_deinit(cipher_hnd);
276 0 : if (rc < 0) {
277 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
278 0 : goto disconnect;
279 : }
280 :
281 0 : rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
282 0 : if (rc != 0) {
283 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
284 0 : goto disconnect;
285 : }
286 :
287 0 : oe2.in.server = &a_server;
288 0 : oe2.in.account = &a_account;
289 0 : oe2.in.password = &lm_pass;
290 0 : oe2.in.hash = &lm_verifier;
291 :
292 : /* 4. try samr_OemChangePasswordUser2 */
293 0 : status = dcerpc_samr_OemChangePasswordUser2_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &oe2);
294 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
295 0 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(oe2.out.result)) {
296 0 : status = oe2.out.result;
297 : }
298 0 : if (!NT_STATUS_IS_OK(oe2.out.result)) {
299 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
300 : "samr_OemChangePasswordUser2 for '%s\\%s' failed: %s",
301 : r->samr.in.domain_name, r->samr.in.account_name,
302 : nt_errstr(status));
303 : }
304 0 : goto disconnect;
305 : }
306 :
307 : #if 0
308 : /* prepare samr_ChangePasswordUser */
309 : E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
310 : E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
311 : E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
312 : E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
313 : E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
314 : E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
315 :
316 : /* TODO: ask for a user_handle */
317 : pw.in.handle = &user_handle;
318 : pw.in.lm_present = 1;
319 : pw.in.old_lm_crypted = &hash1;
320 : pw.in.new_lm_crypted = &hash2;
321 : pw.in.nt_present = 1;
322 : pw.in.old_nt_crypted = &hash3;
323 : pw.in.new_nt_crypted = &hash4;
324 : pw.in.cross1_present = 1;
325 : pw.in.nt_cross = &hash5;
326 : pw.in.cross2_present = 1;
327 : pw.in.lm_cross = &hash6;
328 :
329 : /* 5. try samr_ChangePasswordUser */
330 : status = dcerpc_samr_ChangePasswordUser_r(c.pdc.out.dcerpc_pipe->binding_handle, mem_ctx, &pw);
331 : if (!NT_STATUS_IS_OK(status)) {
332 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
333 : "samr_ChangePasswordUser failed: %s",
334 : nt_errstr(status));
335 : goto disconnect;
336 : }
337 :
338 : /* check result of samr_ChangePasswordUser */
339 : if (!NT_STATUS_IS_OK(pw.out.result)) {
340 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
341 : "samr_ChangePasswordUser for '%s\\%s' failed: %s",
342 : r->samr.in.domain_name, r->samr.in.account_name,
343 : nt_errstr(pw.out.result));
344 : if (NT_STATUS_EQUAL(pw.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
345 : status = pw.out.result;
346 : goto disconnect;
347 : }
348 : goto disconnect;
349 : }
350 : #endif
351 42 : disconnect:
352 : /* close connection */
353 42 : talloc_unlink(ctx, c.out.dcerpc_pipe);
354 :
355 42 : return status;
356 : }
357 :
358 42 : static NTSTATUS libnet_ChangePassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
359 : {
360 2 : NTSTATUS status;
361 2 : union libnet_ChangePassword r2;
362 :
363 42 : r2.samr.level = LIBNET_CHANGE_PASSWORD_SAMR;
364 42 : r2.samr.in.account_name = r->generic.in.account_name;
365 42 : r2.samr.in.domain_name = r->generic.in.domain_name;
366 42 : r2.samr.in.oldpassword = r->generic.in.oldpassword;
367 42 : r2.samr.in.newpassword = r->generic.in.newpassword;
368 :
369 42 : status = libnet_ChangePassword(ctx, mem_ctx, &r2);
370 :
371 42 : r->generic.out.error_string = r2.samr.out.error_string;
372 :
373 42 : return status;
374 : }
375 :
376 84 : NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
377 : {
378 84 : switch (r->generic.level) {
379 42 : case LIBNET_CHANGE_PASSWORD_GENERIC:
380 42 : return libnet_ChangePassword_generic(ctx, mem_ctx, r);
381 42 : case LIBNET_CHANGE_PASSWORD_SAMR:
382 42 : return libnet_ChangePassword_samr(ctx, mem_ctx, r);
383 0 : case LIBNET_CHANGE_PASSWORD_KRB5:
384 0 : return NT_STATUS_NOT_IMPLEMENTED;
385 0 : case LIBNET_CHANGE_PASSWORD_LDAP:
386 0 : return NT_STATUS_NOT_IMPLEMENTED;
387 0 : case LIBNET_CHANGE_PASSWORD_RAP:
388 0 : return NT_STATUS_NOT_IMPLEMENTED;
389 : }
390 :
391 0 : return NT_STATUS_INVALID_LEVEL;
392 : }
393 :
394 575 : static NTSTATUS libnet_SetPassword_samr_handle_26(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
395 : {
396 105 : NTSTATUS status;
397 105 : struct samr_SetUserInfo2 sui;
398 105 : union samr_UserInfo u_info;
399 105 : DATA_BLOB session_key;
400 :
401 575 : if (r->samr_handle.in.info21) {
402 572 : return NT_STATUS_INVALID_PARAMETER_MIX;
403 : }
404 :
405 : /* prepare samr_SetUserInfo2 level 26 */
406 3 : ZERO_STRUCT(u_info);
407 3 : u_info.info26.password_expired = 0;
408 :
409 3 : status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
410 3 : if (!NT_STATUS_IS_OK(status)) {
411 0 : r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
412 : "dcerpc_fetch_session_key failed: %s",
413 : nt_errstr(status));
414 0 : return status;
415 : }
416 :
417 3 : status = encode_rc4_passwd_buffer(r->samr_handle.in.newpassword,
418 : &session_key,
419 : &u_info.info26.password);
420 3 : if (!NT_STATUS_IS_OK(status)) {
421 0 : r->samr_handle.out.error_string =
422 0 : talloc_asprintf(mem_ctx,
423 : "encode_rc4_passwd_buffer failed: %s",
424 : nt_errstr(status));
425 0 : return status;
426 : }
427 :
428 3 : sui.in.user_handle = r->samr_handle.in.user_handle;
429 3 : sui.in.info = &u_info;
430 3 : sui.in.level = 26;
431 :
432 : /* 7. try samr_SetUserInfo2 level 26 to set the password */
433 3 : status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
434 : /* check result of samr_SetUserInfo2 level 26 */
435 3 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
436 1 : status = sui.out.result;
437 : }
438 3 : if (!NT_STATUS_IS_OK(status)) {
439 0 : r->samr_handle.out.error_string
440 1 : = talloc_asprintf(mem_ctx,
441 : "SetUserInfo2 level 26 for [%s] failed: %s",
442 : r->samr_handle.in.account_name, nt_errstr(status));
443 : }
444 :
445 3 : return status;
446 : }
447 :
448 572 : static NTSTATUS libnet_SetPassword_samr_handle_25(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
449 : {
450 105 : NTSTATUS status;
451 105 : struct samr_SetUserInfo2 sui;
452 105 : union samr_UserInfo u_info;
453 105 : DATA_BLOB session_key;
454 :
455 572 : if (!r->samr_handle.in.info21) {
456 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
457 : }
458 :
459 : /* prepare samr_SetUserInfo2 level 25 */
460 572 : ZERO_STRUCT(u_info);
461 572 : u_info.info25.info = *r->samr_handle.in.info21;
462 572 : u_info.info25.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
463 :
464 572 : status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
465 572 : if (!NT_STATUS_IS_OK(status)) {
466 0 : r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
467 : "dcerpc_fetch_session_key failed: %s",
468 : nt_errstr(status));
469 0 : return status;
470 : }
471 :
472 572 : status = encode_rc4_passwd_buffer(r->samr_handle.in.newpassword,
473 : &session_key,
474 : &u_info.info25.password);
475 572 : if (!NT_STATUS_IS_OK(status)) {
476 0 : r->samr_handle.out.error_string =
477 0 : talloc_asprintf(mem_ctx,
478 : "encode_rc4_passwd_buffer failed: %s",
479 : nt_errstr(status));
480 0 : return status;
481 : }
482 :
483 :
484 572 : sui.in.user_handle = r->samr_handle.in.user_handle;
485 572 : sui.in.info = &u_info;
486 572 : sui.in.level = 25;
487 :
488 : /* 8. try samr_SetUserInfo2 level 25 to set the password */
489 572 : status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
490 572 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
491 0 : status = sui.out.result;
492 : }
493 572 : if (!NT_STATUS_IS_OK(status)) {
494 0 : r->samr_handle.out.error_string
495 0 : = talloc_asprintf(mem_ctx,
496 : "SetUserInfo2 level 25 for [%s] failed: %s",
497 : r->samr_handle.in.account_name, nt_errstr(status));
498 : }
499 :
500 572 : return status;
501 : }
502 :
503 0 : static NTSTATUS libnet_SetPassword_samr_handle_24(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
504 : {
505 0 : NTSTATUS status;
506 0 : struct samr_SetUserInfo2 sui;
507 0 : union samr_UserInfo u_info;
508 0 : DATA_BLOB session_key;
509 0 : gnutls_cipher_hd_t cipher_hnd = NULL;
510 0 : gnutls_datum_t enc_session_key;
511 0 : int rc;
512 :
513 0 : if (r->samr_handle.in.info21) {
514 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
515 : }
516 :
517 : /* prepare samr_SetUserInfo2 level 24 */
518 0 : ZERO_STRUCT(u_info);
519 0 : encode_pw_buffer(u_info.info24.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
520 0 : u_info.info24.password_expired = 0;
521 :
522 0 : status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
523 0 : if (!NT_STATUS_IS_OK(status)) {
524 0 : r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
525 : "dcerpc_fetch_session_key failed: %s",
526 : nt_errstr(status));
527 0 : return status;
528 : }
529 :
530 0 : enc_session_key = (gnutls_datum_t) {
531 0 : .data = session_key.data,
532 0 : .size = session_key.length,
533 : };
534 :
535 0 : rc = gnutls_cipher_init(&cipher_hnd,
536 : GNUTLS_CIPHER_ARCFOUR_128,
537 : &enc_session_key,
538 : NULL);
539 0 : if (rc < 0) {
540 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
541 0 : goto out;
542 : }
543 :
544 0 : rc = gnutls_cipher_encrypt(cipher_hnd,
545 : u_info.info24.password.data,
546 : 516);
547 0 : gnutls_cipher_deinit(cipher_hnd);
548 0 : if (rc < 0) {
549 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
550 0 : goto out;
551 : }
552 :
553 0 : sui.in.user_handle = r->samr_handle.in.user_handle;
554 0 : sui.in.info = &u_info;
555 0 : sui.in.level = 24;
556 :
557 : /* 9. try samr_SetUserInfo2 level 24 to set the password */
558 0 : status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
559 0 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
560 0 : status = sui.out.result;
561 : }
562 0 : if (!NT_STATUS_IS_OK(status)) {
563 0 : r->samr_handle.out.error_string
564 0 : = talloc_asprintf(mem_ctx,
565 : "SetUserInfo2 level 24 for [%s] failed: %s",
566 : r->samr_handle.in.account_name, nt_errstr(status));
567 : }
568 :
569 0 : out:
570 0 : data_blob_clear(&session_key);
571 0 : return status;
572 : }
573 :
574 0 : static NTSTATUS libnet_SetPassword_samr_handle_23(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
575 : {
576 0 : NTSTATUS status;
577 0 : struct samr_SetUserInfo2 sui;
578 0 : union samr_UserInfo u_info;
579 0 : DATA_BLOB session_key;
580 0 : gnutls_cipher_hd_t cipher_hnd = NULL;
581 0 : gnutls_datum_t _session_key;
582 0 : int rc;
583 :
584 0 : if (!r->samr_handle.in.info21) {
585 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
586 : }
587 :
588 : /* prepare samr_SetUserInfo2 level 23 */
589 0 : ZERO_STRUCT(u_info);
590 0 : u_info.info23.info = *r->samr_handle.in.info21;
591 0 : u_info.info23.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
592 0 : encode_pw_buffer(u_info.info23.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
593 :
594 0 : status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
595 0 : if (!NT_STATUS_IS_OK(status)) {
596 0 : r->samr_handle.out.error_string
597 0 : = talloc_asprintf(mem_ctx,
598 : "dcerpc_fetch_session_key failed: %s",
599 : nt_errstr(status));
600 0 : return status;
601 : }
602 :
603 0 : _session_key = (gnutls_datum_t) {
604 0 : .data = session_key.data,
605 0 : .size = session_key.length,
606 : };
607 :
608 0 : rc = gnutls_cipher_init(&cipher_hnd,
609 : GNUTLS_CIPHER_ARCFOUR_128,
610 : &_session_key,
611 : NULL);
612 0 : if (rc < 0) {
613 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
614 0 : goto out;
615 : }
616 :
617 0 : rc = gnutls_cipher_encrypt(cipher_hnd,
618 : u_info.info23.password.data,
619 : 516);
620 0 : data_blob_clear_free(&session_key);
621 0 : gnutls_cipher_deinit(cipher_hnd);
622 0 : if (rc < 0) {
623 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
624 0 : goto out;
625 : }
626 :
627 0 : sui.in.user_handle = r->samr_handle.in.user_handle;
628 0 : sui.in.info = &u_info;
629 0 : sui.in.level = 23;
630 :
631 : /* 10. try samr_SetUserInfo2 level 23 to set the password */
632 0 : status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
633 0 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
634 0 : status = sui.out.result;
635 : }
636 0 : if (!NT_STATUS_IS_OK(status)) {
637 0 : r->samr_handle.out.error_string
638 0 : = talloc_asprintf(mem_ctx,
639 : "SetUserInfo2 level 23 for [%s] failed: %s",
640 : r->samr_handle.in.account_name, nt_errstr(status));
641 : }
642 :
643 0 : out:
644 0 : return status;
645 : }
646 :
647 : /*
648 : * 1. try samr_SetUserInfo2 level 26 to set the password
649 : * 2. try samr_SetUserInfo2 level 25 to set the password
650 : * 3. try samr_SetUserInfo2 level 24 to set the password
651 : * 4. try samr_SetUserInfo2 level 23 to set the password
652 : */
653 575 : static NTSTATUS libnet_SetPassword_samr_handle(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
654 : {
655 :
656 105 : NTSTATUS status;
657 575 : enum libnet_SetPassword_level levels[] = {
658 : LIBNET_SET_PASSWORD_SAMR_HANDLE_26,
659 : LIBNET_SET_PASSWORD_SAMR_HANDLE_25,
660 : LIBNET_SET_PASSWORD_SAMR_HANDLE_24,
661 : LIBNET_SET_PASSWORD_SAMR_HANDLE_23,
662 : };
663 105 : unsigned int i;
664 :
665 1147 : for (i=0; i < ARRAY_SIZE(levels); i++) {
666 1147 : r->generic.level = levels[i];
667 1147 : status = libnet_SetPassword(ctx, mem_ctx, r);
668 1147 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)
669 1147 : || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER_MIX)
670 575 : || NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
671 : /* Try another password set mechanism */
672 572 : continue;
673 : }
674 : break;
675 : }
676 :
677 575 : return status;
678 : }
679 : /*
680 : * set a password with DCERPC/SAMR calls
681 : * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
682 : * is it correct to contact the the pdc of the domain of the user who's password should be set?
683 : * 2. do a samr_Connect to get a policy handle
684 : * 3. do a samr_LookupDomain to get the domain sid
685 : * 4. do a samr_OpenDomain to get a domain handle
686 : * 5. do a samr_LookupNames to get the users rid
687 : * 6. do a samr_OpenUser to get a user handle
688 : * 7 call libnet_SetPassword_samr_handle to set the password
689 : */
690 3 : static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
691 : {
692 0 : NTSTATUS status;
693 0 : struct libnet_RpcConnect c;
694 0 : struct samr_Connect sc;
695 0 : struct policy_handle p_handle;
696 0 : struct samr_LookupDomain ld;
697 3 : struct dom_sid2 *sid = NULL;
698 0 : struct lsa_String d_name;
699 0 : struct samr_OpenDomain od;
700 0 : struct policy_handle d_handle;
701 0 : struct samr_LookupNames ln;
702 0 : struct samr_Ids rids, types;
703 0 : struct samr_OpenUser ou;
704 0 : struct policy_handle u_handle;
705 0 : union libnet_SetPassword r2;
706 :
707 3 : ZERO_STRUCT(c);
708 : /* prepare connect to the SAMR pipe of users domain PDC */
709 3 : c.level = LIBNET_RPC_CONNECT_PDC;
710 3 : c.in.name = r->samr.in.domain_name;
711 3 : c.in.dcerpc_iface = &ndr_table_samr;
712 :
713 : /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
714 3 : status = libnet_RpcConnect(ctx, mem_ctx, &c);
715 3 : if (!NT_STATUS_IS_OK(status)) {
716 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
717 : "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
718 : r->samr.in.domain_name, nt_errstr(status));
719 0 : return status;
720 : }
721 :
722 : /* prepare samr_Connect */
723 3 : ZERO_STRUCT(p_handle);
724 3 : sc.in.system_name = NULL;
725 3 : sc.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
726 3 : sc.out.connect_handle = &p_handle;
727 :
728 : /* 2. do a samr_Connect to get a policy handle */
729 3 : status = dcerpc_samr_Connect_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &sc);
730 3 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sc.out.result)) {
731 0 : status = sc.out.result;
732 : }
733 3 : if (!NT_STATUS_IS_OK(status)) {
734 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
735 : "samr_Connect failed: %s",
736 : nt_errstr(status));
737 0 : goto disconnect;
738 : }
739 :
740 : /* prepare samr_LookupDomain */
741 3 : d_name.string = r->samr.in.domain_name;
742 3 : ld.in.connect_handle = &p_handle;
743 3 : ld.in.domain_name = &d_name;
744 3 : ld.out.sid = &sid;
745 :
746 : /* 3. do a samr_LookupDomain to get the domain sid */
747 3 : status = dcerpc_samr_LookupDomain_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &ld);
748 3 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ld.out.result)) {
749 0 : status = ld.out.result;
750 : }
751 3 : if (!NT_STATUS_IS_OK(status)) {
752 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
753 : "samr_LookupDomain for [%s] failed: %s",
754 : r->samr.in.domain_name, nt_errstr(status));
755 0 : goto disconnect;
756 : }
757 :
758 : /* prepare samr_OpenDomain */
759 3 : ZERO_STRUCT(d_handle);
760 3 : od.in.connect_handle = &p_handle;
761 3 : od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
762 3 : od.in.sid = *ld.out.sid;
763 3 : od.out.domain_handle = &d_handle;
764 :
765 : /* 4. do a samr_OpenDomain to get a domain handle */
766 3 : status = dcerpc_samr_OpenDomain_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &od);
767 3 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(od.out.result)) {
768 0 : status = od.out.result;
769 : }
770 3 : if (!NT_STATUS_IS_OK(status)) {
771 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
772 : "samr_OpenDomain for [%s] failed: %s",
773 : r->samr.in.domain_name, nt_errstr(status));
774 0 : goto disconnect;
775 : }
776 :
777 : /* prepare samr_LookupNames */
778 3 : ln.in.domain_handle = &d_handle;
779 3 : ln.in.num_names = 1;
780 3 : ln.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
781 3 : ln.out.rids = &rids;
782 3 : ln.out.types = &types;
783 3 : if (!ln.in.names) {
784 0 : r->samr.out.error_string = "Out of Memory";
785 0 : return NT_STATUS_NO_MEMORY;
786 : }
787 3 : ln.in.names[0].string = r->samr.in.account_name;
788 :
789 : /* 5. do a samr_LookupNames to get the users rid */
790 3 : status = dcerpc_samr_LookupNames_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &ln);
791 3 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ln.out.result)) {
792 0 : status = ln.out.result;
793 : }
794 3 : if (!NT_STATUS_IS_OK(status)) {
795 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
796 : "samr_LookupNames for [%s] failed: %s",
797 : r->samr.in.account_name, nt_errstr(status));
798 0 : goto disconnect;
799 : }
800 :
801 : /* check if we got one RID for the user */
802 3 : if (ln.out.rids->count != 1) {
803 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
804 : "samr_LookupNames for [%s] returns %d RIDs",
805 : r->samr.in.account_name, ln.out.rids->count);
806 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
807 0 : goto disconnect;
808 : }
809 :
810 3 : if (ln.out.types->count != 1) {
811 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
812 : "samr_LookupNames for [%s] returns %d RID TYPEs",
813 : r->samr.in.account_name, ln.out.types->count);
814 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
815 0 : goto disconnect;
816 : }
817 :
818 : /* prepare samr_OpenUser */
819 3 : ZERO_STRUCT(u_handle);
820 3 : ou.in.domain_handle = &d_handle;
821 3 : ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
822 3 : ou.in.rid = ln.out.rids->ids[0];
823 3 : ou.out.user_handle = &u_handle;
824 :
825 : /* 6. do a samr_OpenUser to get a user handle */
826 3 : status = dcerpc_samr_OpenUser_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &ou);
827 3 : if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ou.out.result)) {
828 0 : status = ou.out.result;
829 : }
830 3 : if (!NT_STATUS_IS_OK(status)) {
831 0 : r->samr.out.error_string = talloc_asprintf(mem_ctx,
832 : "samr_OpenUser for [%s] failed: %s",
833 : r->samr.in.account_name, nt_errstr(status));
834 0 : goto disconnect;
835 : }
836 :
837 3 : r2.samr_handle.level = LIBNET_SET_PASSWORD_SAMR_HANDLE;
838 3 : r2.samr_handle.in.account_name = r->samr.in.account_name;
839 3 : r2.samr_handle.in.newpassword = r->samr.in.newpassword;
840 3 : r2.samr_handle.in.user_handle = &u_handle;
841 3 : r2.samr_handle.in.dcerpc_pipe = c.out.dcerpc_pipe;
842 3 : r2.samr_handle.in.info21 = NULL;
843 :
844 3 : status = libnet_SetPassword(ctx, mem_ctx, &r2);
845 :
846 3 : r->generic.out.error_string = r2.samr_handle.out.error_string;
847 :
848 3 : disconnect:
849 : /* close connection */
850 3 : talloc_unlink(ctx, c.out.dcerpc_pipe);
851 :
852 3 : return status;
853 : }
854 :
855 3 : static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
856 : {
857 0 : NTSTATUS status;
858 0 : union libnet_SetPassword r2;
859 :
860 3 : r2.samr.level = LIBNET_SET_PASSWORD_SAMR;
861 3 : r2.samr.in.account_name = r->generic.in.account_name;
862 3 : r2.samr.in.domain_name = r->generic.in.domain_name;
863 3 : r2.samr.in.newpassword = r->generic.in.newpassword;
864 :
865 3 : r->generic.out.error_string = "Unknown Error";
866 3 : status = libnet_SetPassword(ctx, mem_ctx, &r2);
867 :
868 3 : r->generic.out.error_string = r2.samr.out.error_string;
869 :
870 3 : return status;
871 : }
872 :
873 1728 : NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
874 : {
875 1728 : enum smb_encryption_setting encryption_state =
876 1728 : cli_credentials_get_smb_encryption(ctx->cred);
877 1728 : NTSTATUS status = NT_STATUS_INVALID_LEVEL;
878 :
879 1728 : switch (r->generic.level) {
880 3 : case LIBNET_SET_PASSWORD_GENERIC:
881 3 : status = libnet_SetPassword_generic(ctx, mem_ctx, r);
882 3 : break;
883 3 : case LIBNET_SET_PASSWORD_SAMR:
884 3 : status = libnet_SetPassword_samr(ctx, mem_ctx, r);
885 3 : break;
886 575 : case LIBNET_SET_PASSWORD_SAMR_HANDLE:
887 575 : status = libnet_SetPassword_samr_handle(ctx, mem_ctx, r);
888 470 : break;
889 105 : case LIBNET_SET_PASSWORD_SAMR_HANDLE_26:
890 105 : if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
891 0 : GNUTLS_FIPS140_SET_LAX_MODE();
892 : }
893 575 : status = libnet_SetPassword_samr_handle_26(ctx, mem_ctx, r);
894 470 : break;
895 105 : case LIBNET_SET_PASSWORD_SAMR_HANDLE_25:
896 105 : if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
897 0 : GNUTLS_FIPS140_SET_LAX_MODE();
898 : }
899 572 : status = libnet_SetPassword_samr_handle_25(ctx, mem_ctx, r);
900 467 : break;
901 0 : case LIBNET_SET_PASSWORD_SAMR_HANDLE_24:
902 0 : if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
903 0 : GNUTLS_FIPS140_SET_LAX_MODE();
904 : }
905 0 : status = libnet_SetPassword_samr_handle_24(ctx, mem_ctx, r);
906 0 : break;
907 0 : case LIBNET_SET_PASSWORD_SAMR_HANDLE_23:
908 0 : if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
909 0 : GNUTLS_FIPS140_SET_LAX_MODE();
910 : }
911 0 : status = libnet_SetPassword_samr_handle_23(ctx, mem_ctx, r);
912 0 : break;
913 0 : case LIBNET_SET_PASSWORD_KRB5:
914 0 : status = NT_STATUS_NOT_IMPLEMENTED;
915 0 : break;
916 0 : case LIBNET_SET_PASSWORD_LDAP:
917 0 : status = NT_STATUS_NOT_IMPLEMENTED;
918 0 : break;
919 0 : case LIBNET_SET_PASSWORD_RAP:
920 0 : status = NT_STATUS_NOT_IMPLEMENTED;
921 0 : break;
922 : }
923 :
924 315 : GNUTLS_FIPS140_SET_STRICT_MODE();
925 1728 : return status;
926 : }
|