rpcclient: Move rpccli_try_samr_connects() to cmd_samr.c
[Samba.git] / source3 / rpc_client / cli_samr.c
bloba3b24e7b1646b47e3ea31e2ed6582172bb9f099b
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 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,
65 mem_ctx,
66 user_handle,
67 true,
68 &hash1,
69 &hash2,
70 true,
71 &hash3,
72 &hash4,
73 true,
74 &hash5,
75 true,
76 &hash6,
77 presult);
79 ZERO_ARRAY(old_nt_hash);
80 ZERO_ARRAY(old_lm_hash);
81 ZERO_ARRAY(new_nt_hash);
82 ZERO_ARRAY(new_lm_hash);
84 return status;
87 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
88 TALLOC_CTX *mem_ctx,
89 struct policy_handle *user_handle,
90 const char *newpassword,
91 const char *oldpassword)
93 NTSTATUS status;
94 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
96 status = dcerpc_samr_chgpasswd_user(cli->binding_handle,
97 mem_ctx,
98 user_handle,
99 newpassword,
100 oldpassword,
101 &result);
102 if (!NT_STATUS_IS_OK(status)) {
103 return status;
106 return result;
109 /* User change password */
111 NTSTATUS dcerpc_samr_chgpasswd_user2(struct dcerpc_binding_handle *h,
112 TALLOC_CTX *mem_ctx,
113 const char *srv_name_slash,
114 const char *username,
115 const char *newpassword,
116 const char *oldpassword,
117 NTSTATUS *presult)
119 NTSTATUS status;
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,
150 &session_key,
151 &new_lm_password);
152 if (!NT_STATUS_IS_OK(status)) {
153 return status;
156 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
157 } else {
158 ZERO_STRUCT(new_lm_password);
159 ZERO_STRUCT(old_lanman_hash_enc);
162 status = init_samr_CryptPassword(newpassword,
163 &session_key,
164 &new_nt_password);
165 if (!NT_STATUS_IS_OK(status)) {
166 return status;
168 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
170 status = dcerpc_samr_ChangePasswordUser2(h,
171 mem_ctx,
172 &server,
173 &account,
174 &new_nt_password,
175 &old_nt_hash_enc,
176 true,
177 &new_lm_password,
178 &old_lanman_hash_enc,
179 presult);
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);
190 return status;
193 NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli,
194 TALLOC_CTX *mem_ctx,
195 const char *username,
196 const char *newpassword,
197 const char *oldpassword)
199 NTSTATUS status;
200 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
202 status = dcerpc_samr_chgpasswd_user2(cli->binding_handle,
203 mem_ctx,
204 cli->srv_name_slash,
205 username,
206 newpassword,
207 oldpassword,
208 &result);
209 if (!NT_STATUS_IS_OK(status)) {
210 return status;
213 return result;
216 /* User change password given blobs */
218 NTSTATUS dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle *h,
219 TALLOC_CTX *mem_ctx,
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,
226 NTSTATUS *presult)
228 NTSTATUS status;
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,
262 mem_ctx,
263 &server,
264 &account,
265 &new_nt_password,
266 &old_nt_hash_enc,
267 true,
268 &new_lm_password,
269 &old_lm_hash_enc,
270 presult);
272 return status;
275 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
276 TALLOC_CTX *mem_ctx,
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)
283 NTSTATUS status;
284 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
286 status = dcerpc_samr_chng_pswd_auth_crap(cli->binding_handle,
287 mem_ctx,
288 cli->srv_name_slash,
289 username,
290 new_nt_password_blob,
291 old_nt_hash_enc_blob,
292 new_lm_password_blob,
293 old_lm_hash_enc_blob,
294 &result);
295 if (!NT_STATUS_IS_OK(status)) {
296 return status;
299 return result;
302 /* change password 3 */
304 NTSTATUS dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle *h,
305 TALLOC_CTX *mem_ctx,
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,
312 NTSTATUS *presult)
314 NTSTATUS status;
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,
347 &session_key,
348 &new_lm_password);
349 if (!NT_STATUS_IS_OK(status)) {
350 return status;
353 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
354 } else {
355 ZERO_STRUCT(new_lm_password);
356 ZERO_STRUCT(old_lanman_hash_enc);
359 status = init_samr_CryptPassword(newpassword,
360 &session_key,
361 &new_nt_password);
362 if (!NT_STATUS_IS_OK(status)) {
363 return status;
366 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
368 status = dcerpc_samr_ChangePasswordUser3(h,
369 mem_ctx,
370 &server,
371 &account,
372 &new_nt_password,
373 &old_nt_hash_enc,
374 true,
375 &new_lm_password,
376 &old_lanman_hash_enc,
377 NULL,
378 dominfo1,
379 reject,
380 presult);
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);
391 return status;
394 NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli,
395 TALLOC_CTX *mem_ctx,
396 const char *username,
397 const char *newpassword,
398 const char *oldpassword,
399 struct samr_DomInfo1 **dominfo1,
400 struct userPwdChangeFailureInformation **reject)
402 NTSTATUS status;
403 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
405 status = dcerpc_samr_chgpasswd_user3(cli->binding_handle,
406 mem_ctx,
407 cli->srv_name_slash,
408 username,
409 newpassword,
410 oldpassword,
411 dominfo1,
412 reject,
413 &result);
414 if (!NT_STATUS_IS_OK(status)) {
415 return status;
418 return result;
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,
428 uint32_t *max_size)
430 switch(loop_count) {
431 case 0:
432 *max_entries = 512;
433 *max_size = 16383;
434 break;
435 case 1:
436 *max_entries = 1024;
437 *max_size = 32766;
438 break;
439 case 2:
440 *max_entries = 2048;
441 *max_size = 65532;
442 break;
443 case 3:
444 *max_entries = 4096;
445 *max_size = 131064;
446 break;
447 default: /* loop_count >= 4 */
448 *max_entries = 4096;
449 *max_size = 131071;
450 break;
454 NTSTATUS dcerpc_try_samr_connects(struct dcerpc_binding_handle *h,
455 TALLOC_CTX *mem_ctx,
456 const char *srv_name_slash,
457 uint32_t access_mask,
458 struct policy_handle *connect_pol,
459 NTSTATUS *presult)
461 NTSTATUS status;
462 union samr_ConnectInfo info_in, info_out;
463 struct samr_ConnectInfo1 info1;
464 uint32_t lvl_out = 0;
466 ZERO_STRUCT(info1);
468 info1.client_version = SAMR_CONNECT_W2K;
469 info_in.info1 = info1;
471 status = dcerpc_samr_Connect5(h,
472 mem_ctx,
473 srv_name_slash,
474 access_mask,
476 &info_in,
477 &lvl_out,
478 &info_out,
479 connect_pol,
480 presult);
481 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
482 return status;
485 status = dcerpc_samr_Connect4(h,
486 mem_ctx,
487 srv_name_slash,
488 SAMR_CONNECT_W2K,
489 access_mask,
490 connect_pol,
491 presult);
492 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
493 return status;
496 status = dcerpc_samr_Connect2(h,
497 mem_ctx,
498 srv_name_slash,
499 access_mask,
500 connect_pol,
501 presult);
503 return status;
506 /* vim: set ts=8 sw=8 noet cindent: */