19dd25578ba81e717b673e60ee27c2b0f8927c96
[samba.git] / source3 / rpc_client / cli_samr.c
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.
9    
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.
14    
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.
19    
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/>.
22 */
23
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"
30
31 /* User change password */
32
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)
39 {
40         NTSTATUS status;
41         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
42
43         uchar old_nt_hash[16];
44         uchar old_lm_hash[16];
45         uchar new_nt_hash[16];
46         uchar new_lm_hash[16];
47
48         ZERO_STRUCT(old_nt_hash);
49         ZERO_STRUCT(old_lm_hash);
50         ZERO_STRUCT(new_nt_hash);
51         ZERO_STRUCT(new_lm_hash);
52
53         DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
54
55         E_md4hash(oldpassword, old_nt_hash);
56         E_md4hash(newpassword, new_nt_hash);
57
58         E_deshash(oldpassword, old_lm_hash);
59         E_deshash(newpassword, new_lm_hash);
60
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);
67
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);
82
83         return status;
84 }
85
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)
91 {
92         NTSTATUS status;
93         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
94
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;
103         }
104
105         return result;
106 }
107
108 /* User change password */
109
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)
117 {
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;
123
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;
129
130         DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
131
132         init_lsa_String(&server, srv_name_slash);
133         init_lsa_String(&account, username);
134
135         /* Calculate the MD4 hash (NT compatible) of the password */
136         E_md4hash(oldpassword, old_nt_hash);
137         E_md4hash(newpassword, new_nt_hash);
138
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) */
146
147                 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
148
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);
154         }
155
156         encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
157
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);
160
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);
171
172         return status;
173 }
174
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)
180 {
181         NTSTATUS status;
182         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
183
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;
193         }
194
195         return result;
196 }
197
198 /* User change password given blobs */
199
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)
209 {
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;
216
217         DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
218
219         init_lsa_String(&server, srv_name_slash);
220         init_lsa_String(&account, username);
221
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);
226         }
227
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);
232         }
233
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);
238         }
239
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);
244         }
245
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);
256
257         return status;
258 }
259
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)
267 {
268         NTSTATUS status;
269         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
270
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;
282         }
283
284         return result;
285 }
286
287 /* change password 3 */
288
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)
298 {
299         NTSTATUS status;
300
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;
305
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];
310
311         struct lsa_String server, account;
312
313         DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
314
315         init_lsa_String(&server, srv_name_slash);
316         init_lsa_String(&account, username);
317
318         /* Calculate the MD4 hash (NT compatible) of the password */
319         E_md4hash(oldpassword, old_nt_hash);
320         E_md4hash(newpassword, new_nt_hash);
321
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) */
329
330                 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
331
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);
337         }
338
339         encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
340
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);
343
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);
357
358         return status;
359 }
360
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)
368 {
369         NTSTATUS status;
370         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
371
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;
383         }
384
385         return result;
386 }
387
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. */
392
393 void dcerpc_get_query_dispinfo_params(int loop_count,
394                                       uint32_t *max_entries,
395                                       uint32_t *max_size)
396 {
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;
418         }
419 }
420
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)
427 {
428         NTSTATUS status;
429         union samr_ConnectInfo info_in, info_out;
430         struct samr_ConnectInfo1 info1;
431         uint32_t lvl_out = 0;
432
433         ZERO_STRUCT(info1);
434
435         info1.client_version = SAMR_CONNECT_W2K;
436         info_in.info1 = info1;
437
438         status = dcerpc_samr_Connect5(h,
439                                       mem_ctx,
440                                       srv_name_slash,
441                                       access_mask,
442                                       1,
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;
450         }
451
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;
461         }
462
463         status = dcerpc_samr_Connect2(h,
464                                       mem_ctx,
465                                       srv_name_slash,
466                                       access_mask,
467                                       connect_pol,
468                                       presult);
469
470         return status;
471 }
472
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)
477 {
478         NTSTATUS status;
479         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
480
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;
489         }
490
491         return result;
492 }
493
494 /* vim: set ts=8 sw=8 noet cindent: */