2 Unix SMB/CIFS implementation.
4 Copyright (C) Tim Potter 2000-2001,
5 Copyright (C) Andrew Tridgell 1992-1997,2000,
6 Copyright (C) Rafal Szczesniak 2002.
7 Copyright (C) Jeremy Allison 2005.
8 Copyright (C) Guenther Deschner 2008.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_client/rpc_client.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/cli_samr.h"
29 #include "rpc_client/init_lsa.h"
30 #include "rpc_client/init_samr.h"
31 #include "librpc/rpc/dcerpc_samr.h"
32 #include "lib/crypto/gnutls_helpers.h"
33 #include <gnutls/gnutls.h>
34 #include <gnutls/crypto.h>
36 /* User change password */
38 NTSTATUS dcerpc_samr_chgpasswd_user(struct dcerpc_binding_handle *h,
40 struct policy_handle *user_handle,
41 const char *newpassword,
42 const char *oldpassword,
47 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
49 uint8_t old_nt_hash[16] = {0};
50 uint8_t old_lm_hash[16] = {0};
51 uint8_t new_nt_hash[16] = {0};
52 uint8_t new_lm_hash[16] = {0};
54 DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
56 E_md4hash(oldpassword, old_nt_hash);
57 E_md4hash(newpassword, new_nt_hash);
59 E_deshash(oldpassword, old_lm_hash);
60 E_deshash(newpassword, new_lm_hash);
62 rc = E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
64 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
67 rc = E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
69 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
72 rc = E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
74 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
77 rc = E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
79 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
82 rc = E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
84 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
87 rc = E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
89 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
93 status = dcerpc_samr_ChangePasswordUser(h,
109 ZERO_ARRAY(old_nt_hash);
110 ZERO_ARRAY(old_lm_hash);
111 ZERO_ARRAY(new_nt_hash);
112 ZERO_ARRAY(new_lm_hash);
117 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
119 struct policy_handle *user_handle,
120 const char *newpassword,
121 const char *oldpassword)
124 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
126 status = dcerpc_samr_chgpasswd_user(cli->binding_handle,
132 if (!NT_STATUS_IS_OK(status)) {
139 /* User change password */
141 NTSTATUS dcerpc_samr_chgpasswd_user2(struct dcerpc_binding_handle *h,
143 const char *srv_name_slash,
144 const char *username,
145 const char *newpassword,
146 const char *oldpassword,
151 struct samr_CryptPassword new_nt_password;
152 struct samr_CryptPassword new_lm_password;
153 struct samr_Password old_nt_hash_enc;
154 struct samr_Password old_lanman_hash_enc;
156 uint8_t old_nt_hash[16] = { 0 };
157 uint8_t old_lanman_hash[16];
158 uint8_t new_nt_hash[16];
159 uint8_t new_lanman_hash[16];
160 struct lsa_String server, account;
162 DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
164 DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
166 init_lsa_String(&server, srv_name_slash);
167 init_lsa_String(&account, username);
169 /* Calculate the MD4 hash (NT compatible) of the password */
170 E_md4hash(oldpassword, old_nt_hash);
171 E_md4hash(newpassword, new_nt_hash);
173 if (lp_client_lanman_auth() &&
174 E_deshash(newpassword, new_lanman_hash) &&
175 E_deshash(oldpassword, old_lanman_hash)) {
176 /* E_deshash returns false for 'long' passwords (> 14
177 DOS chars). This allows us to match Win2k, which
178 does not store a LM hash for these passwords (which
179 would reduce the effective password length to 14) */
180 status = init_samr_CryptPassword(newpassword,
183 if (!NT_STATUS_IS_OK(status)) {
187 rc = E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
189 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
193 ZERO_STRUCT(new_lm_password);
194 ZERO_STRUCT(old_lanman_hash_enc);
197 status = init_samr_CryptPassword(newpassword,
200 if (!NT_STATUS_IS_OK(status)) {
203 rc = E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
205 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
209 status = dcerpc_samr_ChangePasswordUser2(h,
217 &old_lanman_hash_enc,
221 ZERO_STRUCT(new_nt_password);
222 ZERO_STRUCT(new_lm_password);
223 ZERO_STRUCT(old_nt_hash_enc);
224 ZERO_STRUCT(old_lanman_hash_enc);
225 ZERO_ARRAY(new_nt_hash);
226 ZERO_ARRAY(new_lanman_hash);
227 ZERO_ARRAY(old_nt_hash);
228 ZERO_ARRAY(old_lanman_hash);
233 NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli,
235 const char *username,
236 const char *newpassword,
237 const char *oldpassword)
240 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
242 status = dcerpc_samr_chgpasswd_user2(cli->binding_handle,
249 if (!NT_STATUS_IS_OK(status)) {
256 /* User change password given blobs */
258 NTSTATUS dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle *h,
260 const char *srv_name_slash,
261 const char *username,
262 DATA_BLOB new_nt_password_blob,
263 DATA_BLOB old_nt_hash_enc_blob,
264 DATA_BLOB new_lm_password_blob,
265 DATA_BLOB old_lm_hash_enc_blob,
269 struct samr_CryptPassword new_nt_password;
270 struct samr_CryptPassword new_lm_password;
271 struct samr_Password old_nt_hash_enc;
272 struct samr_Password old_lm_hash_enc;
273 struct lsa_String server, account;
275 DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
277 ZERO_STRUCT(new_nt_password);
278 ZERO_STRUCT(new_lm_password);
279 ZERO_STRUCT(old_nt_hash_enc);
280 ZERO_STRUCT(old_lm_hash_enc);
282 init_lsa_String(&server, srv_name_slash);
283 init_lsa_String(&account, username);
285 if (new_nt_password_blob.data && new_nt_password_blob.length >= 516) {
286 memcpy(&new_nt_password.data, new_nt_password_blob.data, 516);
289 if (new_lm_password_blob.data && new_lm_password_blob.length >= 516) {
290 memcpy(&new_lm_password.data, new_lm_password_blob.data, 516);
293 if (old_nt_hash_enc_blob.data && old_nt_hash_enc_blob.length >= 16) {
294 memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16);
297 if (old_lm_hash_enc_blob.data && old_lm_hash_enc_blob.length >= 16) {
298 memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16);
301 status = dcerpc_samr_ChangePasswordUser2(h,
315 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
317 const char *username,
318 DATA_BLOB new_nt_password_blob,
319 DATA_BLOB old_nt_hash_enc_blob,
320 DATA_BLOB new_lm_password_blob,
321 DATA_BLOB old_lm_hash_enc_blob)
324 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
326 status = dcerpc_samr_chng_pswd_auth_crap(cli->binding_handle,
330 new_nt_password_blob,
331 old_nt_hash_enc_blob,
332 new_lm_password_blob,
333 old_lm_hash_enc_blob,
335 if (!NT_STATUS_IS_OK(status)) {
342 /* change password 3 */
344 NTSTATUS dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle *h,
346 const char *srv_name_slash,
347 const char *username,
348 const char *newpassword,
349 const char *oldpassword,
350 struct samr_DomInfo1 **dominfo1,
351 struct userPwdChangeFailureInformation **reject,
357 struct samr_CryptPassword new_nt_password;
358 struct samr_CryptPassword new_lm_password;
359 struct samr_Password old_nt_hash_enc;
360 struct samr_Password old_lanman_hash_enc;
362 uint8_t old_nt_hash[16] = { 0 };
363 uint8_t old_lanman_hash[16];
364 uint8_t new_nt_hash[16];
365 uint8_t new_lanman_hash[16];
367 struct lsa_String server, account;
369 DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
371 DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
373 init_lsa_String(&server, srv_name_slash);
374 init_lsa_String(&account, username);
376 /* Calculate the MD4 hash (NT compatible) of the password */
377 E_md4hash(oldpassword, old_nt_hash);
378 E_md4hash(newpassword, new_nt_hash);
380 if (lp_client_lanman_auth() &&
381 E_deshash(newpassword, new_lanman_hash) &&
382 E_deshash(oldpassword, old_lanman_hash)) {
383 /* E_deshash returns false for 'long' passwords (> 14
384 DOS chars). This allows us to match Win2k, which
385 does not store a LM hash for these passwords (which
386 would reduce the effective password length to 14) */
387 status = init_samr_CryptPassword(newpassword,
390 if (!NT_STATUS_IS_OK(status)) {
394 rc = E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
396 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
400 ZERO_STRUCT(new_lm_password);
401 ZERO_STRUCT(old_lanman_hash_enc);
404 status = init_samr_CryptPassword(newpassword,
407 if (!NT_STATUS_IS_OK(status)) {
411 rc = E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
413 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
417 status = dcerpc_samr_ChangePasswordUser3(h,
425 &old_lanman_hash_enc,
432 ZERO_STRUCT(new_nt_password);
433 ZERO_STRUCT(new_lm_password);
434 ZERO_STRUCT(old_nt_hash_enc);
435 ZERO_STRUCT(old_lanman_hash_enc);
436 ZERO_ARRAY(new_nt_hash);
437 ZERO_ARRAY(new_lanman_hash);
438 ZERO_ARRAY(old_nt_hash);
439 ZERO_ARRAY(old_lanman_hash);
444 NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli,
446 const char *username,
447 const char *newpassword,
448 const char *oldpassword,
449 struct samr_DomInfo1 **dominfo1,
450 struct userPwdChangeFailureInformation **reject)
453 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
455 status = dcerpc_samr_chgpasswd_user3(cli->binding_handle,
464 if (!NT_STATUS_IS_OK(status)) {
471 NTSTATUS dcerpc_samr_chgpasswd_user4(struct dcerpc_binding_handle *h,
473 const char *srv_name_slash,
474 const char *username,
475 const char *oldpassword,
476 const char *newpassword,
479 struct lsa_String server, user_account;
480 uint8_t old_nt_key_data[16] = {0};
481 gnutls_datum_t old_nt_key = {
482 .data = old_nt_key_data,
483 .size = sizeof(old_nt_key),
485 struct samr_EncryptedPasswordAES pwd_buf = {
489 .data = pwd_buf.salt,
490 .length = sizeof(pwd_buf.salt),
492 gnutls_datum_t iv_datum = {
496 uint8_t cek_data[16] = {0};
499 .length = sizeof(cek_data),
501 uint64_t pbkdf2_iterations = 0;
502 uint8_t pw_data[514] = {0};
503 DATA_BLOB plaintext = {
505 .length = sizeof(pw_data),
507 DATA_BLOB ciphertext = data_blob_null;
512 generate_nonce_buffer(iv.data, iv.length);
514 /* Calculate the MD4 hash (NT compatible) of the password */
515 E_md4hash(oldpassword, old_nt_key_data);
517 init_lsa_String(&server, srv_name_slash);
518 init_lsa_String(&user_account, username);
520 pbkdf2_iterations = generate_random_u64_range(5000, 1000000);
522 rc = gnutls_pbkdf2(GNUTLS_MAC_SHA512,
528 BURN_DATA(old_nt_key_data);
530 status = gnutls_error_to_ntstatus(rc, NT_STATUS_WRONG_PASSWORD);
534 ok = encode_pwd_buffer514_from_str(pw_data, newpassword, STR_UNICODE);
536 return NT_STATUS_INTERNAL_ERROR;
539 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(
543 &samr_aes256_enc_key_salt,
544 &samr_aes256_mac_key_salt,
550 if (!NT_STATUS_IS_OK(status)) {
554 pwd_buf.cipher_len = ciphertext.length;
555 pwd_buf.cipher = ciphertext.data;
556 pwd_buf.PBKDF2Iterations = pbkdf2_iterations;
558 status = dcerpc_samr_ChangePasswordUser4(h,
564 data_blob_free(&ciphertext);
569 /* This function returns the bizarre set of (max_entries, max_size) required
570 for the QueryDisplayInfo RPC to actually work against a domain controller
571 with large (10k and higher) numbers of users. These values were
572 obtained by inspection using ethereal and NT4 running User Manager. */
574 void dcerpc_get_query_dispinfo_params(int loop_count,
575 uint32_t *max_entries,
595 default: /* loop_count >= 4 */
602 NTSTATUS dcerpc_try_samr_connects(struct dcerpc_binding_handle *h,
604 const char *srv_name_slash,
605 uint32_t access_mask,
606 struct policy_handle *connect_pol,
610 union samr_ConnectInfo info_in, info_out;
611 struct samr_ConnectInfo1 info1;
612 uint32_t lvl_out = 0;
616 info1.client_version = SAMR_CONNECT_W2K;
617 info_in.info1 = info1;
619 status = dcerpc_samr_Connect5(h,
629 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
633 status = dcerpc_samr_Connect4(h,
640 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
644 status = dcerpc_samr_Connect2(h,
654 /* vim: set ts=8 sw=8 noet cindent: */