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
,
43 struct samr_Password hash1
, hash2
, hash3
, hash4
, hash5
, hash6
;
45 uint8_t old_nt_hash
[16] = {0};
46 uint8_t old_lm_hash
[16] = {0};
47 uint8_t new_nt_hash
[16] = {0};
48 uint8_t new_lm_hash
[16] = {0};
50 DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
52 E_md4hash(oldpassword
, old_nt_hash
);
53 E_md4hash(newpassword
, new_nt_hash
);
55 E_deshash(oldpassword
, old_lm_hash
);
56 E_deshash(newpassword
, new_lm_hash
);
58 rc
= E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
60 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
63 rc
= E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
65 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
68 rc
= E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
70 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
73 rc
= E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
75 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
78 rc
= E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
80 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
83 rc
= E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
85 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
89 status
= dcerpc_samr_ChangePasswordUser(h
,
105 ZERO_ARRAY(old_nt_hash
);
106 ZERO_ARRAY(old_lm_hash
);
107 ZERO_ARRAY(new_nt_hash
);
108 ZERO_ARRAY(new_lm_hash
);
113 NTSTATUS
rpccli_samr_chgpasswd_user(struct rpc_pipe_client
*cli
,
115 struct policy_handle
*user_handle
,
116 const char *newpassword
,
117 const char *oldpassword
)
120 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
122 status
= dcerpc_samr_chgpasswd_user(cli
->binding_handle
,
128 if (!NT_STATUS_IS_OK(status
)) {
135 /* User change password */
137 NTSTATUS
dcerpc_samr_chgpasswd_user2(struct dcerpc_binding_handle
*h
,
139 const char *srv_name_slash
,
140 const char *username
,
141 const char *newpassword
,
142 const char *oldpassword
,
147 struct samr_CryptPassword new_nt_password
;
148 struct samr_CryptPassword new_lm_password
;
149 struct samr_Password old_nt_hash_enc
;
150 struct samr_Password old_lanman_hash_enc
;
152 uint8_t old_nt_hash
[16];
153 uint8_t old_lanman_hash
[16];
154 uint8_t new_nt_hash
[16];
155 uint8_t new_lanman_hash
[16];
156 struct lsa_String server
, account
;
158 DATA_BLOB session_key
= data_blob_const(old_nt_hash
, 16);
160 DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
162 init_lsa_String(&server
, srv_name_slash
);
163 init_lsa_String(&account
, username
);
165 /* Calculate the MD4 hash (NT compatible) of the password */
166 E_md4hash(oldpassword
, old_nt_hash
);
167 E_md4hash(newpassword
, new_nt_hash
);
169 if (lp_client_lanman_auth() &&
170 E_deshash(newpassword
, new_lanman_hash
) &&
171 E_deshash(oldpassword
, old_lanman_hash
)) {
172 /* E_deshash returns false for 'long' passwords (> 14
173 DOS chars). This allows us to match Win2k, which
174 does not store a LM hash for these passwords (which
175 would reduce the effective password length to 14) */
176 status
= init_samr_CryptPassword(newpassword
,
179 if (!NT_STATUS_IS_OK(status
)) {
183 rc
= E_old_pw_hash(new_nt_hash
, old_lanman_hash
, old_lanman_hash_enc
.hash
);
185 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
189 ZERO_STRUCT(new_lm_password
);
190 ZERO_STRUCT(old_lanman_hash_enc
);
193 status
= init_samr_CryptPassword(newpassword
,
196 if (!NT_STATUS_IS_OK(status
)) {
199 rc
= E_old_pw_hash(new_nt_hash
, old_nt_hash
, old_nt_hash_enc
.hash
);
201 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
205 status
= dcerpc_samr_ChangePasswordUser2(h
,
213 &old_lanman_hash_enc
,
217 ZERO_STRUCT(new_nt_password
);
218 ZERO_STRUCT(new_lm_password
);
219 ZERO_STRUCT(old_nt_hash_enc
);
220 ZERO_STRUCT(old_lanman_hash_enc
);
221 ZERO_ARRAY(new_nt_hash
);
222 ZERO_ARRAY(new_lanman_hash
);
223 ZERO_ARRAY(old_nt_hash
);
224 ZERO_ARRAY(old_lanman_hash
);
229 NTSTATUS
rpccli_samr_chgpasswd_user2(struct rpc_pipe_client
*cli
,
231 const char *username
,
232 const char *newpassword
,
233 const char *oldpassword
)
236 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
238 status
= dcerpc_samr_chgpasswd_user2(cli
->binding_handle
,
245 if (!NT_STATUS_IS_OK(status
)) {
252 /* User change password given blobs */
254 NTSTATUS
dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle
*h
,
256 const char *srv_name_slash
,
257 const char *username
,
258 DATA_BLOB new_nt_password_blob
,
259 DATA_BLOB old_nt_hash_enc_blob
,
260 DATA_BLOB new_lm_password_blob
,
261 DATA_BLOB old_lm_hash_enc_blob
,
265 struct samr_CryptPassword new_nt_password
;
266 struct samr_CryptPassword new_lm_password
;
267 struct samr_Password old_nt_hash_enc
;
268 struct samr_Password old_lm_hash_enc
;
269 struct lsa_String server
, account
;
271 DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
273 ZERO_STRUCT(new_nt_password
);
274 ZERO_STRUCT(new_lm_password
);
275 ZERO_STRUCT(old_nt_hash_enc
);
276 ZERO_STRUCT(old_lm_hash_enc
);
278 init_lsa_String(&server
, srv_name_slash
);
279 init_lsa_String(&account
, username
);
281 if (new_nt_password_blob
.data
&& new_nt_password_blob
.length
>= 516) {
282 memcpy(&new_nt_password
.data
, new_nt_password_blob
.data
, 516);
285 if (new_lm_password_blob
.data
&& new_lm_password_blob
.length
>= 516) {
286 memcpy(&new_lm_password
.data
, new_lm_password_blob
.data
, 516);
289 if (old_nt_hash_enc_blob
.data
&& old_nt_hash_enc_blob
.length
>= 16) {
290 memcpy(&old_nt_hash_enc
.hash
, old_nt_hash_enc_blob
.data
, 16);
293 if (old_lm_hash_enc_blob
.data
&& old_lm_hash_enc_blob
.length
>= 16) {
294 memcpy(&old_lm_hash_enc
.hash
, old_lm_hash_enc_blob
.data
, 16);
297 status
= dcerpc_samr_ChangePasswordUser2(h
,
311 NTSTATUS
rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client
*cli
,
313 const char *username
,
314 DATA_BLOB new_nt_password_blob
,
315 DATA_BLOB old_nt_hash_enc_blob
,
316 DATA_BLOB new_lm_password_blob
,
317 DATA_BLOB old_lm_hash_enc_blob
)
320 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
322 status
= dcerpc_samr_chng_pswd_auth_crap(cli
->binding_handle
,
326 new_nt_password_blob
,
327 old_nt_hash_enc_blob
,
328 new_lm_password_blob
,
329 old_lm_hash_enc_blob
,
331 if (!NT_STATUS_IS_OK(status
)) {
338 /* change password 3 */
340 NTSTATUS
dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle
*h
,
342 const char *srv_name_slash
,
343 const char *username
,
344 const char *newpassword
,
345 const char *oldpassword
,
346 struct samr_DomInfo1
**dominfo1
,
347 struct userPwdChangeFailureInformation
**reject
,
353 struct samr_CryptPassword new_nt_password
;
354 struct samr_CryptPassword new_lm_password
;
355 struct samr_Password old_nt_hash_enc
;
356 struct samr_Password old_lanman_hash_enc
;
358 uint8_t old_nt_hash
[16];
359 uint8_t old_lanman_hash
[16];
360 uint8_t new_nt_hash
[16];
361 uint8_t new_lanman_hash
[16];
363 struct lsa_String server
, account
;
365 DATA_BLOB session_key
= data_blob_const(old_nt_hash
, 16);
367 DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
369 init_lsa_String(&server
, srv_name_slash
);
370 init_lsa_String(&account
, username
);
372 /* Calculate the MD4 hash (NT compatible) of the password */
373 E_md4hash(oldpassword
, old_nt_hash
);
374 E_md4hash(newpassword
, new_nt_hash
);
376 if (lp_client_lanman_auth() &&
377 E_deshash(newpassword
, new_lanman_hash
) &&
378 E_deshash(oldpassword
, old_lanman_hash
)) {
379 /* E_deshash returns false for 'long' passwords (> 14
380 DOS chars). This allows us to match Win2k, which
381 does not store a LM hash for these passwords (which
382 would reduce the effective password length to 14) */
383 status
= init_samr_CryptPassword(newpassword
,
386 if (!NT_STATUS_IS_OK(status
)) {
390 rc
= E_old_pw_hash(new_nt_hash
, old_lanman_hash
, old_lanman_hash_enc
.hash
);
392 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
396 ZERO_STRUCT(new_lm_password
);
397 ZERO_STRUCT(old_lanman_hash_enc
);
400 status
= init_samr_CryptPassword(newpassword
,
403 if (!NT_STATUS_IS_OK(status
)) {
407 rc
= E_old_pw_hash(new_nt_hash
, old_nt_hash
, old_nt_hash_enc
.hash
);
409 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
);
413 status
= dcerpc_samr_ChangePasswordUser3(h
,
421 &old_lanman_hash_enc
,
428 ZERO_STRUCT(new_nt_password
);
429 ZERO_STRUCT(new_lm_password
);
430 ZERO_STRUCT(old_nt_hash_enc
);
431 ZERO_STRUCT(old_lanman_hash_enc
);
432 ZERO_ARRAY(new_nt_hash
);
433 ZERO_ARRAY(new_lanman_hash
);
434 ZERO_ARRAY(old_nt_hash
);
435 ZERO_ARRAY(old_lanman_hash
);
440 NTSTATUS
rpccli_samr_chgpasswd_user3(struct rpc_pipe_client
*cli
,
442 const char *username
,
443 const char *newpassword
,
444 const char *oldpassword
,
445 struct samr_DomInfo1
**dominfo1
,
446 struct userPwdChangeFailureInformation
**reject
)
449 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
451 status
= dcerpc_samr_chgpasswd_user3(cli
->binding_handle
,
460 if (!NT_STATUS_IS_OK(status
)) {
467 /* This function returns the bizzare set of (max_entries, max_size) required
468 for the QueryDisplayInfo RPC to actually work against a domain controller
469 with large (10k and higher) numbers of users. These values were
470 obtained by inspection using ethereal and NT4 running User Manager. */
472 void dcerpc_get_query_dispinfo_params(int loop_count
,
473 uint32_t *max_entries
,
493 default: /* loop_count >= 4 */
500 NTSTATUS
dcerpc_try_samr_connects(struct dcerpc_binding_handle
*h
,
502 const char *srv_name_slash
,
503 uint32_t access_mask
,
504 struct policy_handle
*connect_pol
,
508 union samr_ConnectInfo info_in
, info_out
;
509 struct samr_ConnectInfo1 info1
;
510 uint32_t lvl_out
= 0;
514 info1
.client_version
= SAMR_CONNECT_W2K
;
515 info_in
.info1
= info1
;
517 status
= dcerpc_samr_Connect5(h
,
527 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(*presult
)) {
531 status
= dcerpc_samr_Connect4(h
,
538 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(*presult
)) {
542 status
= dcerpc_samr_Connect2(h
,
552 /* vim: set ts=8 sw=8 noet cindent: */