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"
32 /* User change password */
34 NTSTATUS
dcerpc_samr_chgpasswd_user(struct dcerpc_binding_handle
*h
,
36 struct policy_handle
*user_handle
,
37 const char *newpassword
,
38 const char *oldpassword
,
42 struct samr_Password hash1
, hash2
, hash3
, hash4
, hash5
, hash6
;
44 uint8_t old_nt_hash
[16] = {0};
45 uint8_t old_lm_hash
[16] = {0};
46 uint8_t new_nt_hash
[16] = {0};
47 uint8_t new_lm_hash
[16] = {0};
49 DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
51 E_md4hash(oldpassword
, old_nt_hash
);
52 E_md4hash(newpassword
, new_nt_hash
);
54 E_deshash(oldpassword
, old_lm_hash
);
55 E_deshash(newpassword
, new_lm_hash
);
57 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
58 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
59 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
60 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
61 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
62 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
64 status
= dcerpc_samr_ChangePasswordUser(h
,
79 ZERO_ARRAY(old_nt_hash
);
80 ZERO_ARRAY(old_lm_hash
);
81 ZERO_ARRAY(new_nt_hash
);
82 ZERO_ARRAY(new_lm_hash
);
87 NTSTATUS
rpccli_samr_chgpasswd_user(struct rpc_pipe_client
*cli
,
89 struct policy_handle
*user_handle
,
90 const char *newpassword
,
91 const char *oldpassword
)
94 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
96 status
= dcerpc_samr_chgpasswd_user(cli
->binding_handle
,
102 if (!NT_STATUS_IS_OK(status
)) {
109 /* User change password */
111 NTSTATUS
dcerpc_samr_chgpasswd_user2(struct dcerpc_binding_handle
*h
,
113 const char *srv_name_slash
,
114 const char *username
,
115 const char *newpassword
,
116 const char *oldpassword
,
120 struct samr_CryptPassword new_nt_password
;
121 struct samr_CryptPassword new_lm_password
;
122 struct samr_Password old_nt_hash_enc
;
123 struct samr_Password old_lanman_hash_enc
;
125 uint8_t old_nt_hash
[16];
126 uint8_t old_lanman_hash
[16];
127 uint8_t new_nt_hash
[16];
128 uint8_t new_lanman_hash
[16];
129 struct lsa_String server
, account
;
131 DATA_BLOB session_key
= data_blob_const(old_nt_hash
, 16);
133 DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
135 init_lsa_String(&server
, srv_name_slash
);
136 init_lsa_String(&account
, username
);
138 /* Calculate the MD4 hash (NT compatible) of the password */
139 E_md4hash(oldpassword
, old_nt_hash
);
140 E_md4hash(newpassword
, new_nt_hash
);
142 if (lp_client_lanman_auth() &&
143 E_deshash(newpassword
, new_lanman_hash
) &&
144 E_deshash(oldpassword
, old_lanman_hash
)) {
145 /* E_deshash returns false for 'long' passwords (> 14
146 DOS chars). This allows us to match Win2k, which
147 does not store a LM hash for these passwords (which
148 would reduce the effective password length to 14) */
149 status
= init_samr_CryptPassword(newpassword
,
152 if (!NT_STATUS_IS_OK(status
)) {
156 E_old_pw_hash(new_nt_hash
, old_lanman_hash
, old_lanman_hash_enc
.hash
);
158 ZERO_STRUCT(new_lm_password
);
159 ZERO_STRUCT(old_lanman_hash_enc
);
162 status
= init_samr_CryptPassword(newpassword
,
165 if (!NT_STATUS_IS_OK(status
)) {
168 E_old_pw_hash(new_nt_hash
, old_nt_hash
, old_nt_hash_enc
.hash
);
170 status
= dcerpc_samr_ChangePasswordUser2(h
,
178 &old_lanman_hash_enc
,
181 ZERO_STRUCT(new_nt_password
);
182 ZERO_STRUCT(new_lm_password
);
183 ZERO_STRUCT(old_nt_hash_enc
);
184 ZERO_STRUCT(old_lanman_hash_enc
);
185 ZERO_ARRAY(new_nt_hash
);
186 ZERO_ARRAY(new_lanman_hash
);
187 ZERO_ARRAY(old_nt_hash
);
188 ZERO_ARRAY(old_lanman_hash
);
193 NTSTATUS
rpccli_samr_chgpasswd_user2(struct rpc_pipe_client
*cli
,
195 const char *username
,
196 const char *newpassword
,
197 const char *oldpassword
)
200 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
202 status
= dcerpc_samr_chgpasswd_user2(cli
->binding_handle
,
209 if (!NT_STATUS_IS_OK(status
)) {
216 /* User change password given blobs */
218 NTSTATUS
dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle
*h
,
220 const char *srv_name_slash
,
221 const char *username
,
222 DATA_BLOB new_nt_password_blob
,
223 DATA_BLOB old_nt_hash_enc_blob
,
224 DATA_BLOB new_lm_password_blob
,
225 DATA_BLOB old_lm_hash_enc_blob
,
229 struct samr_CryptPassword new_nt_password
;
230 struct samr_CryptPassword new_lm_password
;
231 struct samr_Password old_nt_hash_enc
;
232 struct samr_Password old_lm_hash_enc
;
233 struct lsa_String server
, account
;
235 DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
237 ZERO_STRUCT(new_nt_password
);
238 ZERO_STRUCT(new_lm_password
);
239 ZERO_STRUCT(old_nt_hash_enc
);
240 ZERO_STRUCT(old_lm_hash_enc
);
242 init_lsa_String(&server
, srv_name_slash
);
243 init_lsa_String(&account
, username
);
245 if (new_nt_password_blob
.data
&& new_nt_password_blob
.length
>= 516) {
246 memcpy(&new_nt_password
.data
, new_nt_password_blob
.data
, 516);
249 if (new_lm_password_blob
.data
&& new_lm_password_blob
.length
>= 516) {
250 memcpy(&new_lm_password
.data
, new_lm_password_blob
.data
, 516);
253 if (old_nt_hash_enc_blob
.data
&& old_nt_hash_enc_blob
.length
>= 16) {
254 memcpy(&old_nt_hash_enc
.hash
, old_nt_hash_enc_blob
.data
, 16);
257 if (old_lm_hash_enc_blob
.data
&& old_lm_hash_enc_blob
.length
>= 16) {
258 memcpy(&old_lm_hash_enc
.hash
, old_lm_hash_enc_blob
.data
, 16);
261 status
= dcerpc_samr_ChangePasswordUser2(h
,
275 NTSTATUS
rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client
*cli
,
277 const char *username
,
278 DATA_BLOB new_nt_password_blob
,
279 DATA_BLOB old_nt_hash_enc_blob
,
280 DATA_BLOB new_lm_password_blob
,
281 DATA_BLOB old_lm_hash_enc_blob
)
284 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
286 status
= dcerpc_samr_chng_pswd_auth_crap(cli
->binding_handle
,
290 new_nt_password_blob
,
291 old_nt_hash_enc_blob
,
292 new_lm_password_blob
,
293 old_lm_hash_enc_blob
,
295 if (!NT_STATUS_IS_OK(status
)) {
302 /* change password 3 */
304 NTSTATUS
dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle
*h
,
306 const char *srv_name_slash
,
307 const char *username
,
308 const char *newpassword
,
309 const char *oldpassword
,
310 struct samr_DomInfo1
**dominfo1
,
311 struct userPwdChangeFailureInformation
**reject
,
316 struct samr_CryptPassword new_nt_password
;
317 struct samr_CryptPassword new_lm_password
;
318 struct samr_Password old_nt_hash_enc
;
319 struct samr_Password old_lanman_hash_enc
;
321 uint8_t old_nt_hash
[16];
322 uint8_t old_lanman_hash
[16];
323 uint8_t new_nt_hash
[16];
324 uint8_t new_lanman_hash
[16];
326 struct lsa_String server
, account
;
328 DATA_BLOB session_key
= data_blob_const(old_nt_hash
, 16);
330 DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
332 init_lsa_String(&server
, srv_name_slash
);
333 init_lsa_String(&account
, username
);
335 /* Calculate the MD4 hash (NT compatible) of the password */
336 E_md4hash(oldpassword
, old_nt_hash
);
337 E_md4hash(newpassword
, new_nt_hash
);
339 if (lp_client_lanman_auth() &&
340 E_deshash(newpassword
, new_lanman_hash
) &&
341 E_deshash(oldpassword
, old_lanman_hash
)) {
342 /* E_deshash returns false for 'long' passwords (> 14
343 DOS chars). This allows us to match Win2k, which
344 does not store a LM hash for these passwords (which
345 would reduce the effective password length to 14) */
346 status
= init_samr_CryptPassword(newpassword
,
349 if (!NT_STATUS_IS_OK(status
)) {
353 E_old_pw_hash(new_nt_hash
, old_lanman_hash
, old_lanman_hash_enc
.hash
);
355 ZERO_STRUCT(new_lm_password
);
356 ZERO_STRUCT(old_lanman_hash_enc
);
359 status
= init_samr_CryptPassword(newpassword
,
362 if (!NT_STATUS_IS_OK(status
)) {
366 E_old_pw_hash(new_nt_hash
, old_nt_hash
, old_nt_hash_enc
.hash
);
368 status
= dcerpc_samr_ChangePasswordUser3(h
,
376 &old_lanman_hash_enc
,
382 ZERO_STRUCT(new_nt_password
);
383 ZERO_STRUCT(new_lm_password
);
384 ZERO_STRUCT(old_nt_hash_enc
);
385 ZERO_STRUCT(old_lanman_hash_enc
);
386 ZERO_ARRAY(new_nt_hash
);
387 ZERO_ARRAY(new_lanman_hash
);
388 ZERO_ARRAY(old_nt_hash
);
389 ZERO_ARRAY(old_lanman_hash
);
394 NTSTATUS
rpccli_samr_chgpasswd_user3(struct rpc_pipe_client
*cli
,
396 const char *username
,
397 const char *newpassword
,
398 const char *oldpassword
,
399 struct samr_DomInfo1
**dominfo1
,
400 struct userPwdChangeFailureInformation
**reject
)
403 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
405 status
= dcerpc_samr_chgpasswd_user3(cli
->binding_handle
,
414 if (!NT_STATUS_IS_OK(status
)) {
421 /* This function returns the bizzare set of (max_entries, max_size) required
422 for the QueryDisplayInfo RPC to actually work against a domain controller
423 with large (10k and higher) numbers of users. These values were
424 obtained by inspection using ethereal and NT4 running User Manager. */
426 void dcerpc_get_query_dispinfo_params(int loop_count
,
427 uint32_t *max_entries
,
447 default: /* loop_count >= 4 */
454 NTSTATUS
dcerpc_try_samr_connects(struct dcerpc_binding_handle
*h
,
456 const char *srv_name_slash
,
457 uint32_t access_mask
,
458 struct policy_handle
*connect_pol
,
462 union samr_ConnectInfo info_in
, info_out
;
463 struct samr_ConnectInfo1 info1
;
464 uint32_t lvl_out
= 0;
468 info1
.client_version
= SAMR_CONNECT_W2K
;
469 info_in
.info1
= info1
;
471 status
= dcerpc_samr_Connect5(h
,
481 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(*presult
)) {
485 status
= dcerpc_samr_Connect4(h
,
492 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(*presult
)) {
496 status
= dcerpc_samr_Connect2(h
,
506 /* vim: set ts=8 sw=8 noet cindent: */