BUG 9474: Downgrade v4 printer driver requests to v3.
[Samba.git] / source3 / rpc_client / cli_samr.c
blobe2bf08de4a02c4752519e559b549d8af7b30da21
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 "../lib/crypto/arcfour.h"
30 #include "rpc_client/init_lsa.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 uchar old_nt_hash[16];
45 uchar old_lm_hash[16];
46 uchar new_nt_hash[16];
47 uchar new_lm_hash[16];
49 ZERO_STRUCT(old_nt_hash);
50 ZERO_STRUCT(old_lm_hash);
51 ZERO_STRUCT(new_nt_hash);
52 ZERO_STRUCT(new_lm_hash);
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 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
63 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
64 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
65 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
66 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
67 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
69 status = dcerpc_samr_ChangePasswordUser(h,
70 mem_ctx,
71 user_handle,
72 true,
73 &hash1,
74 &hash2,
75 true,
76 &hash3,
77 &hash4,
78 true,
79 &hash5,
80 true,
81 &hash6,
82 presult);
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 DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
133 init_lsa_String(&server, srv_name_slash);
134 init_lsa_String(&account, username);
136 /* Calculate the MD4 hash (NT compatible) of the password */
137 E_md4hash(oldpassword, old_nt_hash);
138 E_md4hash(newpassword, new_nt_hash);
140 if (lp_client_lanman_auth() &&
141 E_deshash(newpassword, new_lanman_hash) &&
142 E_deshash(oldpassword, old_lanman_hash)) {
143 /* E_deshash returns false for 'long' passwords (> 14
144 DOS chars). This allows us to match Win2k, which
145 does not store a LM hash for these passwords (which
146 would reduce the effective password length to 14) */
148 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
150 arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
151 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
152 } else {
153 ZERO_STRUCT(new_lm_password);
154 ZERO_STRUCT(old_lanman_hash_enc);
157 encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
159 arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
160 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
162 status = dcerpc_samr_ChangePasswordUser2(h,
163 mem_ctx,
164 &server,
165 &account,
166 &new_nt_password,
167 &old_nt_hash_enc,
168 true,
169 &new_lm_password,
170 &old_lanman_hash_enc,
171 presult);
173 return status;
176 NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli,
177 TALLOC_CTX *mem_ctx,
178 const char *username,
179 const char *newpassword,
180 const char *oldpassword)
182 NTSTATUS status;
183 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
185 status = dcerpc_samr_chgpasswd_user2(cli->binding_handle,
186 mem_ctx,
187 cli->srv_name_slash,
188 username,
189 newpassword,
190 oldpassword,
191 &result);
192 if (!NT_STATUS_IS_OK(status)) {
193 return status;
196 return result;
199 /* User change password given blobs */
201 NTSTATUS dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle *h,
202 TALLOC_CTX *mem_ctx,
203 const char *srv_name_slash,
204 const char *username,
205 DATA_BLOB new_nt_password_blob,
206 DATA_BLOB old_nt_hash_enc_blob,
207 DATA_BLOB new_lm_password_blob,
208 DATA_BLOB old_lm_hash_enc_blob,
209 NTSTATUS *presult)
211 NTSTATUS status;
212 struct samr_CryptPassword new_nt_password;
213 struct samr_CryptPassword new_lm_password;
214 struct samr_Password old_nt_hash_enc;
215 struct samr_Password old_lm_hash_enc;
216 struct lsa_String server, account;
218 DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
220 ZERO_STRUCT(new_nt_password);
221 ZERO_STRUCT(new_lm_password);
222 ZERO_STRUCT(old_nt_hash_enc);
223 ZERO_STRUCT(old_lm_hash_enc);
225 init_lsa_String(&server, srv_name_slash);
226 init_lsa_String(&account, username);
228 if (new_nt_password_blob.data && new_nt_password_blob.length >= 516) {
229 memcpy(&new_nt_password.data, new_nt_password_blob.data, 516);
232 if (new_lm_password_blob.data && new_lm_password_blob.length >= 516) {
233 memcpy(&new_lm_password.data, new_lm_password_blob.data, 516);
236 if (old_nt_hash_enc_blob.data && old_nt_hash_enc_blob.length >= 16) {
237 memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16);
240 if (old_lm_hash_enc_blob.data && old_lm_hash_enc_blob.length >= 16) {
241 memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16);
244 status = dcerpc_samr_ChangePasswordUser2(h,
245 mem_ctx,
246 &server,
247 &account,
248 &new_nt_password,
249 &old_nt_hash_enc,
250 true,
251 &new_lm_password,
252 &old_lm_hash_enc,
253 presult);
255 return status;
258 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
259 TALLOC_CTX *mem_ctx,
260 const char *username,
261 DATA_BLOB new_nt_password_blob,
262 DATA_BLOB old_nt_hash_enc_blob,
263 DATA_BLOB new_lm_password_blob,
264 DATA_BLOB old_lm_hash_enc_blob)
266 NTSTATUS status;
267 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
269 status = dcerpc_samr_chng_pswd_auth_crap(cli->binding_handle,
270 mem_ctx,
271 cli->srv_name_slash,
272 username,
273 new_nt_password_blob,
274 old_nt_hash_enc_blob,
275 new_lm_password_blob,
276 old_lm_hash_enc_blob,
277 &result);
278 if (!NT_STATUS_IS_OK(status)) {
279 return status;
282 return result;
285 /* change password 3 */
287 NTSTATUS dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle *h,
288 TALLOC_CTX *mem_ctx,
289 const char *srv_name_slash,
290 const char *username,
291 const char *newpassword,
292 const char *oldpassword,
293 struct samr_DomInfo1 **dominfo1,
294 struct userPwdChangeFailureInformation **reject,
295 NTSTATUS *presult)
297 NTSTATUS status;
299 struct samr_CryptPassword new_nt_password;
300 struct samr_CryptPassword new_lm_password;
301 struct samr_Password old_nt_hash_enc;
302 struct samr_Password old_lanman_hash_enc;
304 uint8_t old_nt_hash[16];
305 uint8_t old_lanman_hash[16];
306 uint8_t new_nt_hash[16];
307 uint8_t new_lanman_hash[16];
309 struct lsa_String server, account;
311 DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
313 init_lsa_String(&server, srv_name_slash);
314 init_lsa_String(&account, username);
316 /* Calculate the MD4 hash (NT compatible) of the password */
317 E_md4hash(oldpassword, old_nt_hash);
318 E_md4hash(newpassword, new_nt_hash);
320 if (lp_client_lanman_auth() &&
321 E_deshash(newpassword, new_lanman_hash) &&
322 E_deshash(oldpassword, old_lanman_hash)) {
323 /* E_deshash returns false for 'long' passwords (> 14
324 DOS chars). This allows us to match Win2k, which
325 does not store a LM hash for these passwords (which
326 would reduce the effective password length to 14) */
328 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
330 arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
331 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
332 } else {
333 ZERO_STRUCT(new_lm_password);
334 ZERO_STRUCT(old_lanman_hash_enc);
337 encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
339 arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
340 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
342 status = dcerpc_samr_ChangePasswordUser3(h,
343 mem_ctx,
344 &server,
345 &account,
346 &new_nt_password,
347 &old_nt_hash_enc,
348 true,
349 &new_lm_password,
350 &old_lanman_hash_enc,
351 NULL,
352 dominfo1,
353 reject,
354 presult);
356 return status;
359 NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli,
360 TALLOC_CTX *mem_ctx,
361 const char *username,
362 const char *newpassword,
363 const char *oldpassword,
364 struct samr_DomInfo1 **dominfo1,
365 struct userPwdChangeFailureInformation **reject)
367 NTSTATUS status;
368 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
370 status = dcerpc_samr_chgpasswd_user3(cli->binding_handle,
371 mem_ctx,
372 cli->srv_name_slash,
373 username,
374 newpassword,
375 oldpassword,
376 dominfo1,
377 reject,
378 &result);
379 if (!NT_STATUS_IS_OK(status)) {
380 return status;
383 return result;
386 /* This function returns the bizzare set of (max_entries, max_size) required
387 for the QueryDisplayInfo RPC to actually work against a domain controller
388 with large (10k and higher) numbers of users. These values were
389 obtained by inspection using ethereal and NT4 running User Manager. */
391 void dcerpc_get_query_dispinfo_params(int loop_count,
392 uint32_t *max_entries,
393 uint32_t *max_size)
395 switch(loop_count) {
396 case 0:
397 *max_entries = 512;
398 *max_size = 16383;
399 break;
400 case 1:
401 *max_entries = 1024;
402 *max_size = 32766;
403 break;
404 case 2:
405 *max_entries = 2048;
406 *max_size = 65532;
407 break;
408 case 3:
409 *max_entries = 4096;
410 *max_size = 131064;
411 break;
412 default: /* loop_count >= 4 */
413 *max_entries = 4096;
414 *max_size = 131071;
415 break;
419 NTSTATUS dcerpc_try_samr_connects(struct dcerpc_binding_handle *h,
420 TALLOC_CTX *mem_ctx,
421 const char *srv_name_slash,
422 uint32_t access_mask,
423 struct policy_handle *connect_pol,
424 NTSTATUS *presult)
426 NTSTATUS status;
427 union samr_ConnectInfo info_in, info_out;
428 struct samr_ConnectInfo1 info1;
429 uint32_t lvl_out = 0;
431 ZERO_STRUCT(info1);
433 info1.client_version = SAMR_CONNECT_W2K;
434 info_in.info1 = info1;
436 status = dcerpc_samr_Connect5(h,
437 mem_ctx,
438 srv_name_slash,
439 access_mask,
441 &info_in,
442 &lvl_out,
443 &info_out,
444 connect_pol,
445 presult);
446 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
447 return status;
450 status = dcerpc_samr_Connect4(h,
451 mem_ctx,
452 srv_name_slash,
453 SAMR_CONNECT_W2K,
454 access_mask,
455 connect_pol,
456 presult);
457 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
458 return status;
461 status = dcerpc_samr_Connect2(h,
462 mem_ctx,
463 srv_name_slash,
464 access_mask,
465 connect_pol,
466 presult);
468 return status;
471 NTSTATUS rpccli_try_samr_connects(struct rpc_pipe_client *cli,
472 TALLOC_CTX *mem_ctx,
473 uint32_t access_mask,
474 struct policy_handle *connect_pol)
476 NTSTATUS status;
477 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
479 status = dcerpc_try_samr_connects(cli->binding_handle,
480 mem_ctx,
481 cli->srv_name_slash,
482 access_mask,
483 connect_pol,
484 &result);
485 if (!NT_STATUS_IS_OK(status)) {
486 return status;
489 return result;
492 /* vim: set ts=8 sw=8 noet cindent: */