s3: Fix Coverity ID 2289: Uninitialized read
[Samba.git] / source3 / rpc_client / cli_samr.c
blob19dd25578ba81e717b673e60ee27c2b0f8927c96
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 "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/ndr_samr_c.h"
27 #include "rpc_client/cli_samr.h"
28 #include "../lib/crypto/arcfour.h"
29 #include "rpc_client/init_lsa.h"
31 /* User change password */
33 NTSTATUS dcerpc_samr_chgpasswd_user(struct dcerpc_binding_handle *h,
34 TALLOC_CTX *mem_ctx,
35 struct policy_handle *user_handle,
36 const char *newpassword,
37 const char *oldpassword,
38 NTSTATUS *presult)
40 NTSTATUS status;
41 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
43 uchar old_nt_hash[16];
44 uchar old_lm_hash[16];
45 uchar new_nt_hash[16];
46 uchar new_lm_hash[16];
48 ZERO_STRUCT(old_nt_hash);
49 ZERO_STRUCT(old_lm_hash);
50 ZERO_STRUCT(new_nt_hash);
51 ZERO_STRUCT(new_lm_hash);
53 DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
55 E_md4hash(oldpassword, old_nt_hash);
56 E_md4hash(newpassword, new_nt_hash);
58 E_deshash(oldpassword, old_lm_hash);
59 E_deshash(newpassword, new_lm_hash);
61 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
62 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
63 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
64 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
65 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
66 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
68 status = dcerpc_samr_ChangePasswordUser(h,
69 mem_ctx,
70 user_handle,
71 true,
72 &hash1,
73 &hash2,
74 true,
75 &hash3,
76 &hash4,
77 true,
78 &hash5,
79 true,
80 &hash6,
81 presult);
83 return status;
86 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
87 TALLOC_CTX *mem_ctx,
88 struct policy_handle *user_handle,
89 const char *newpassword,
90 const char *oldpassword)
92 NTSTATUS status;
93 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
95 status = dcerpc_samr_chgpasswd_user(cli->binding_handle,
96 mem_ctx,
97 user_handle,
98 newpassword,
99 oldpassword,
100 &result);
101 if (!NT_STATUS_IS_OK(status)) {
102 return status;
105 return result;
108 /* User change password */
110 NTSTATUS dcerpc_samr_chgpasswd_user2(struct dcerpc_binding_handle *h,
111 TALLOC_CTX *mem_ctx,
112 const char *srv_name_slash,
113 const char *username,
114 const char *newpassword,
115 const char *oldpassword,
116 NTSTATUS *presult)
118 NTSTATUS status;
119 struct samr_CryptPassword new_nt_password;
120 struct samr_CryptPassword new_lm_password;
121 struct samr_Password old_nt_hash_enc;
122 struct samr_Password old_lanman_hash_enc;
124 uint8_t old_nt_hash[16];
125 uint8_t old_lanman_hash[16];
126 uint8_t new_nt_hash[16];
127 uint8_t new_lanman_hash[16];
128 struct lsa_String server, account;
130 DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
132 init_lsa_String(&server, srv_name_slash);
133 init_lsa_String(&account, username);
135 /* Calculate the MD4 hash (NT compatible) of the password */
136 E_md4hash(oldpassword, old_nt_hash);
137 E_md4hash(newpassword, new_nt_hash);
139 if (lp_client_lanman_auth() &&
140 E_deshash(newpassword, new_lanman_hash) &&
141 E_deshash(oldpassword, old_lanman_hash)) {
142 /* E_deshash returns false for 'long' passwords (> 14
143 DOS chars). This allows us to match Win2k, which
144 does not store a LM hash for these passwords (which
145 would reduce the effective password length to 14) */
147 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
149 arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
150 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
151 } else {
152 ZERO_STRUCT(new_lm_password);
153 ZERO_STRUCT(old_lanman_hash_enc);
156 encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
158 arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
159 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
161 status = dcerpc_samr_ChangePasswordUser2(h,
162 mem_ctx,
163 &server,
164 &account,
165 &new_nt_password,
166 &old_nt_hash_enc,
167 true,
168 &new_lm_password,
169 &old_lanman_hash_enc,
170 presult);
172 return status;
175 NTSTATUS rpccli_samr_chgpasswd_user2(struct rpc_pipe_client *cli,
176 TALLOC_CTX *mem_ctx,
177 const char *username,
178 const char *newpassword,
179 const char *oldpassword)
181 NTSTATUS status;
182 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
184 status = dcerpc_samr_chgpasswd_user2(cli->binding_handle,
185 mem_ctx,
186 cli->srv_name_slash,
187 username,
188 newpassword,
189 oldpassword,
190 &result);
191 if (!NT_STATUS_IS_OK(status)) {
192 return status;
195 return result;
198 /* User change password given blobs */
200 NTSTATUS dcerpc_samr_chng_pswd_auth_crap(struct dcerpc_binding_handle *h,
201 TALLOC_CTX *mem_ctx,
202 const char *srv_name_slash,
203 const char *username,
204 DATA_BLOB new_nt_password_blob,
205 DATA_BLOB old_nt_hash_enc_blob,
206 DATA_BLOB new_lm_password_blob,
207 DATA_BLOB old_lm_hash_enc_blob,
208 NTSTATUS *presult)
210 NTSTATUS status;
211 struct samr_CryptPassword new_nt_password;
212 struct samr_CryptPassword new_lm_password;
213 struct samr_Password old_nt_hash_enc;
214 struct samr_Password old_lm_hash_enc;
215 struct lsa_String server, account;
217 DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
219 init_lsa_String(&server, srv_name_slash);
220 init_lsa_String(&account, username);
222 if (new_nt_password_blob.length > 0) {
223 memcpy(&new_nt_password.data, new_nt_password_blob.data, 516);
224 } else {
225 ZERO_STRUCT(new_nt_password_blob);
228 if (new_lm_password_blob.length > 0) {
229 memcpy(&new_lm_password.data, new_lm_password_blob.data, 516);
230 } else {
231 ZERO_STRUCT(new_lm_password);
234 if (old_nt_hash_enc_blob.length > 0) {
235 memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16);
236 } else {
237 ZERO_STRUCT(old_nt_hash_enc);
240 if (old_lm_hash_enc_blob.length > 0) {
241 memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16);
242 } else {
243 ZERO_STRUCT(old_lm_hash_enc);
246 status = dcerpc_samr_ChangePasswordUser2(h,
247 mem_ctx,
248 &server,
249 &account,
250 &new_nt_password,
251 &old_nt_hash_enc,
252 true,
253 &new_lm_password,
254 &old_lm_hash_enc,
255 presult);
257 return status;
260 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
261 TALLOC_CTX *mem_ctx,
262 const char *username,
263 DATA_BLOB new_nt_password_blob,
264 DATA_BLOB old_nt_hash_enc_blob,
265 DATA_BLOB new_lm_password_blob,
266 DATA_BLOB old_lm_hash_enc_blob)
268 NTSTATUS status;
269 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
271 status = dcerpc_samr_chng_pswd_auth_crap(cli->binding_handle,
272 mem_ctx,
273 cli->srv_name_slash,
274 username,
275 new_nt_password_blob,
276 old_nt_hash_enc_blob,
277 new_lm_password_blob,
278 old_lm_hash_enc_blob,
279 &result);
280 if (!NT_STATUS_IS_OK(status)) {
281 return status;
284 return result;
287 /* change password 3 */
289 NTSTATUS dcerpc_samr_chgpasswd_user3(struct dcerpc_binding_handle *h,
290 TALLOC_CTX *mem_ctx,
291 const char *srv_name_slash,
292 const char *username,
293 const char *newpassword,
294 const char *oldpassword,
295 struct samr_DomInfo1 **dominfo1,
296 struct userPwdChangeFailureInformation **reject,
297 NTSTATUS *presult)
299 NTSTATUS status;
301 struct samr_CryptPassword new_nt_password;
302 struct samr_CryptPassword new_lm_password;
303 struct samr_Password old_nt_hash_enc;
304 struct samr_Password old_lanman_hash_enc;
306 uint8_t old_nt_hash[16];
307 uint8_t old_lanman_hash[16];
308 uint8_t new_nt_hash[16];
309 uint8_t new_lanman_hash[16];
311 struct lsa_String server, account;
313 DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
315 init_lsa_String(&server, srv_name_slash);
316 init_lsa_String(&account, username);
318 /* Calculate the MD4 hash (NT compatible) of the password */
319 E_md4hash(oldpassword, old_nt_hash);
320 E_md4hash(newpassword, new_nt_hash);
322 if (lp_client_lanman_auth() &&
323 E_deshash(newpassword, new_lanman_hash) &&
324 E_deshash(oldpassword, old_lanman_hash)) {
325 /* E_deshash returns false for 'long' passwords (> 14
326 DOS chars). This allows us to match Win2k, which
327 does not store a LM hash for these passwords (which
328 would reduce the effective password length to 14) */
330 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
332 arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
333 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
334 } else {
335 ZERO_STRUCT(new_lm_password);
336 ZERO_STRUCT(old_lanman_hash_enc);
339 encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
341 arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
342 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
344 status = dcerpc_samr_ChangePasswordUser3(h,
345 mem_ctx,
346 &server,
347 &account,
348 &new_nt_password,
349 &old_nt_hash_enc,
350 true,
351 &new_lm_password,
352 &old_lanman_hash_enc,
353 NULL,
354 dominfo1,
355 reject,
356 presult);
358 return status;
361 NTSTATUS rpccli_samr_chgpasswd_user3(struct rpc_pipe_client *cli,
362 TALLOC_CTX *mem_ctx,
363 const char *username,
364 const char *newpassword,
365 const char *oldpassword,
366 struct samr_DomInfo1 **dominfo1,
367 struct userPwdChangeFailureInformation **reject)
369 NTSTATUS status;
370 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
372 status = dcerpc_samr_chgpasswd_user3(cli->binding_handle,
373 mem_ctx,
374 cli->srv_name_slash,
375 username,
376 newpassword,
377 oldpassword,
378 dominfo1,
379 reject,
380 &result);
381 if (!NT_STATUS_IS_OK(status)) {
382 return status;
385 return result;
388 /* This function returns the bizzare set of (max_entries, max_size) required
389 for the QueryDisplayInfo RPC to actually work against a domain controller
390 with large (10k and higher) numbers of users. These values were
391 obtained by inspection using ethereal and NT4 running User Manager. */
393 void dcerpc_get_query_dispinfo_params(int loop_count,
394 uint32_t *max_entries,
395 uint32_t *max_size)
397 switch(loop_count) {
398 case 0:
399 *max_entries = 512;
400 *max_size = 16383;
401 break;
402 case 1:
403 *max_entries = 1024;
404 *max_size = 32766;
405 break;
406 case 2:
407 *max_entries = 2048;
408 *max_size = 65532;
409 break;
410 case 3:
411 *max_entries = 4096;
412 *max_size = 131064;
413 break;
414 default: /* loop_count >= 4 */
415 *max_entries = 4096;
416 *max_size = 131071;
417 break;
421 NTSTATUS dcerpc_try_samr_connects(struct dcerpc_binding_handle *h,
422 TALLOC_CTX *mem_ctx,
423 const char *srv_name_slash,
424 uint32_t access_mask,
425 struct policy_handle *connect_pol,
426 NTSTATUS *presult)
428 NTSTATUS status;
429 union samr_ConnectInfo info_in, info_out;
430 struct samr_ConnectInfo1 info1;
431 uint32_t lvl_out = 0;
433 ZERO_STRUCT(info1);
435 info1.client_version = SAMR_CONNECT_W2K;
436 info_in.info1 = info1;
438 status = dcerpc_samr_Connect5(h,
439 mem_ctx,
440 srv_name_slash,
441 access_mask,
443 &info_in,
444 &lvl_out,
445 &info_out,
446 connect_pol,
447 presult);
448 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
449 return status;
452 status = dcerpc_samr_Connect4(h,
453 mem_ctx,
454 srv_name_slash,
455 SAMR_CONNECT_W2K,
456 access_mask,
457 connect_pol,
458 presult);
459 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(*presult)) {
460 return status;
463 status = dcerpc_samr_Connect2(h,
464 mem_ctx,
465 srv_name_slash,
466 access_mask,
467 connect_pol,
468 presult);
470 return status;
473 NTSTATUS rpccli_try_samr_connects(struct rpc_pipe_client *cli,
474 TALLOC_CTX *mem_ctx,
475 uint32_t access_mask,
476 struct policy_handle *connect_pol)
478 NTSTATUS status;
479 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
481 status = dcerpc_try_samr_connects(cli->binding_handle,
482 mem_ctx,
483 cli->srv_name_slash,
484 access_mask,
485 connect_pol,
486 &result);
487 if (!NT_STATUS_IS_OK(status)) {
488 return status;
491 return result;
494 /* vim: set ts=8 sw=8 noet cindent: */