tests/krb5: Fix sha1 checksum type
[Samba.git] / source3 / rpc_client / cli_samr.c
blobacd96480a20d64d4ebeffe78bd58c29cec7b4978
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
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/>.
24 #include "includes.h"
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,
35 TALLOC_CTX *mem_ctx,
36 struct policy_handle *user_handle,
37 const char *newpassword,
38 const char *oldpassword,
39 NTSTATUS *presult)
41 NTSTATUS status;
42 int rc;
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);
59 if (rc != 0) {
60 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
61 goto done;
63 rc = E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
64 if (rc != 0) {
65 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
66 goto done;
68 rc = E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
69 if (rc != 0) {
70 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
71 goto done;
73 rc = E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
74 if (rc != 0) {
75 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
76 goto done;
78 rc = E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
79 if (rc != 0) {
80 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
81 goto done;
83 rc = E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
84 if (rc != 0) {
85 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
86 goto done;
89 status = dcerpc_samr_ChangePasswordUser(h,
90 mem_ctx,
91 user_handle,
92 true,
93 &hash1,
94 &hash2,
95 true,
96 &hash3,
97 &hash4,
98 true,
99 &hash5,
100 true,
101 &hash6,
102 presult);
104 done:
105 ZERO_ARRAY(old_nt_hash);
106 ZERO_ARRAY(old_lm_hash);
107 ZERO_ARRAY(new_nt_hash);
108 ZERO_ARRAY(new_lm_hash);
110 return status;
113 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
114 TALLOC_CTX *mem_ctx,
115 struct policy_handle *user_handle,
116 const char *newpassword,
117 const char *oldpassword)
119 NTSTATUS status;
120 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
122 status = dcerpc_samr_chgpasswd_user(cli->binding_handle,
123 mem_ctx,
124 user_handle,
125 newpassword,
126 oldpassword,
127 &result);
128 if (!NT_STATUS_IS_OK(status)) {
129 return status;
132 return result;
135 /* User change password */
137 NTSTATUS dcerpc_samr_chgpasswd_user2(struct dcerpc_binding_handle *h,
138 TALLOC_CTX *mem_ctx,
139 const char *srv_name_slash,
140 const char *username,
141 const char *newpassword,
142 const char *oldpassword,
143 NTSTATUS *presult)
145 NTSTATUS status;
146 int rc;
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,
177 &session_key,
178 &new_lm_password);
179 if (!NT_STATUS_IS_OK(status)) {
180 return status;
183 rc = E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
184 if (rc != 0) {
185 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
186 goto done;
188 } else {
189 ZERO_STRUCT(new_lm_password);
190 ZERO_STRUCT(old_lanman_hash_enc);
193 status = init_samr_CryptPassword(newpassword,
194 &session_key,
195 &new_nt_password);
196 if (!NT_STATUS_IS_OK(status)) {
197 return status;
199 rc = E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
200 if (rc != 0) {
201 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
202 goto done;
205 status = dcerpc_samr_ChangePasswordUser2(h,
206 mem_ctx,
207 &server,
208 &account,
209 &new_nt_password,
210 &old_nt_hash_enc,
211 true,
212 &new_lm_password,
213 &old_lanman_hash_enc,
214 presult);
216 done:
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);
226 return status;
229 NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli,
230 TALLOC_CTX *mem_ctx,
231 const char *username,
232 const char *newpassword,
233 const char *oldpassword)
235 NTSTATUS status;
236 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
238 status = dcerpc_samr_chgpasswd_user2(cli->binding_handle,
239 mem_ctx,
240 cli->srv_name_slash,
241 username,
242 newpassword,
243 oldpassword,
244 &result);
245 if (!NT_STATUS_IS_OK(status)) {
246 return status;
249 return result;
252 /* User change password given blobs */
254 NTSTATUS dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle *h,
255 TALLOC_CTX *mem_ctx,
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,
262 NTSTATUS *presult)
264 NTSTATUS status;
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,
298 mem_ctx,
299 &server,
300 &account,
301 &new_nt_password,
302 &old_nt_hash_enc,
303 true,
304 &new_lm_password,
305 &old_lm_hash_enc,
306 presult);
308 return status;
311 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
312 TALLOC_CTX *mem_ctx,
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)
319 NTSTATUS status;
320 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
322 status = dcerpc_samr_chng_pswd_auth_crap(cli->binding_handle,
323 mem_ctx,
324 cli->srv_name_slash,
325 username,
326 new_nt_password_blob,
327 old_nt_hash_enc_blob,
328 new_lm_password_blob,
329 old_lm_hash_enc_blob,
330 &result);
331 if (!NT_STATUS_IS_OK(status)) {
332 return status;
335 return result;
338 /* change password 3 */
340 NTSTATUS dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle *h,
341 TALLOC_CTX *mem_ctx,
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,
348 NTSTATUS *presult)
350 NTSTATUS status;
351 int rc;
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,
384 &session_key,
385 &new_lm_password);
386 if (!NT_STATUS_IS_OK(status)) {
387 return status;
390 rc = E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
391 if (rc != 0) {
392 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
393 goto done;
395 } else {
396 ZERO_STRUCT(new_lm_password);
397 ZERO_STRUCT(old_lanman_hash_enc);
400 status = init_samr_CryptPassword(newpassword,
401 &session_key,
402 &new_nt_password);
403 if (!NT_STATUS_IS_OK(status)) {
404 return status;
407 rc = E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
408 if (rc != 0) {
409 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
410 goto done;
413 status = dcerpc_samr_ChangePasswordUser3(h,
414 mem_ctx,
415 &server,
416 &account,
417 &new_nt_password,
418 &old_nt_hash_enc,
419 true,
420 &new_lm_password,
421 &old_lanman_hash_enc,
422 NULL,
423 dominfo1,
424 reject,
425 presult);
427 done:
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);
437 return status;
440 NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli,
441 TALLOC_CTX *mem_ctx,
442 const char *username,
443 const char *newpassword,
444 const char *oldpassword,
445 struct samr_DomInfo1 **dominfo1,
446 struct userPwdChangeFailureInformation **reject)
448 NTSTATUS status;
449 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
451 status = dcerpc_samr_chgpasswd_user3(cli->binding_handle,
452 mem_ctx,
453 cli->srv_name_slash,
454 username,
455 newpassword,
456 oldpassword,
457 dominfo1,
458 reject,
459 &result);
460 if (!NT_STATUS_IS_OK(status)) {
461 return status;
464 return result;
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,
474 uint32_t *max_size)
476 switch(loop_count) {
477 case 0:
478 *max_entries = 512;
479 *max_size = 16383;
480 break;
481 case 1:
482 *max_entries = 1024;
483 *max_size = 32766;
484 break;
485 case 2:
486 *max_entries = 2048;
487 *max_size = 65532;
488 break;
489 case 3:
490 *max_entries = 4096;
491 *max_size = 131064;
492 break;
493 default: /* loop_count >= 4 */
494 *max_entries = 4096;
495 *max_size = 131071;
496 break;
500 NTSTATUS dcerpc_try_samr_connects(struct dcerpc_binding_handle *h,
501 TALLOC_CTX *mem_ctx,
502 const char *srv_name_slash,
503 uint32_t access_mask,
504 struct policy_handle *connect_pol,
505 NTSTATUS *presult)
507 NTSTATUS status;
508 union samr_ConnectInfo info_in, info_out;
509 struct samr_ConnectInfo1 info1;
510 uint32_t lvl_out = 0;
512 ZERO_STRUCT(info1);
514 info1.client_version = SAMR_CONNECT_W2K;
515 info_in.info1 = info1;
517 status = dcerpc_samr_Connect5(h,
518 mem_ctx,
519 srv_name_slash,
520 access_mask,
522 &info_in,
523 &lvl_out,
524 &info_out,
525 connect_pol,
526 presult);
527 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
528 return status;
531 status = dcerpc_samr_Connect4(h,
532 mem_ctx,
533 srv_name_slash,
534 SAMR_CONNECT_W2K,
535 access_mask,
536 connect_pol,
537 presult);
538 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
539 return status;
542 status = dcerpc_samr_Connect2(h,
543 mem_ctx,
544 srv_name_slash,
545 access_mask,
546 connect_pol,
547 presult);
549 return status;
552 /* vim: set ts=8 sw=8 noet cindent: */