s3-librpc: Rename spnego_ntlmssp_init_client and make generic
[ira/wip.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 "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"
31
32 /* User change password */
33
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)
40 {
41         NTSTATUS status;
42         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
43
44         uchar old_nt_hash[16];
45         uchar old_lm_hash[16];
46         uchar new_nt_hash[16];
47         uchar new_lm_hash[16];
48
49         ZERO_STRUCT(old_nt_hash);
50         ZERO_STRUCT(old_lm_hash);
51         ZERO_STRUCT(new_nt_hash);
52         ZERO_STRUCT(new_lm_hash);
53
54         DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
55
56         E_md4hash(oldpassword, old_nt_hash);
57         E_md4hash(newpassword, new_nt_hash);
58
59         E_deshash(oldpassword, old_lm_hash);
60         E_deshash(newpassword, new_lm_hash);
61
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);
68
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);
83
84         return status;
85 }
86
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)
92 {
93         NTSTATUS status;
94         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
95
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;
104         }
105
106         return result;
107 }
108
109 /* User change password */
110
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)
118 {
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;
124
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;
130
131         DEBUG(10,("rpccli_samr_chgpasswd_user2\n"));
132
133         init_lsa_String(&server, srv_name_slash);
134         init_lsa_String(&account, username);
135
136         /* Calculate the MD4 hash (NT compatible) of the password */
137         E_md4hash(oldpassword, old_nt_hash);
138         E_md4hash(newpassword, new_nt_hash);
139
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) */
147
148                 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
149
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);
155         }
156
157         encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
158
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);
161
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);
172
173         return status;
174 }
175
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)
181 {
182         NTSTATUS status;
183         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
184
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;
194         }
195
196         return result;
197 }
198
199 /* User change password given blobs */
200
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)
210 {
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;
217
218         DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
219
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);
224
225         init_lsa_String(&server, srv_name_slash);
226         init_lsa_String(&account, username);
227
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);
230         }
231
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);
234         }
235
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);
238         }
239
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);
242         }
243
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);
254
255         return status;
256 }
257
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)
265 {
266         NTSTATUS status;
267         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
268
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;
280         }
281
282         return result;
283 }
284
285 /* change password 3 */
286
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)
296 {
297         NTSTATUS status;
298
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;
303
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];
308
309         struct lsa_String server, account;
310
311         DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
312
313         init_lsa_String(&server, srv_name_slash);
314         init_lsa_String(&account, username);
315
316         /* Calculate the MD4 hash (NT compatible) of the password */
317         E_md4hash(oldpassword, old_nt_hash);
318         E_md4hash(newpassword, new_nt_hash);
319
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) */
327
328                 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
329
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);
335         }
336
337         encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
338
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);
341
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);
355
356         return status;
357 }
358
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)
366 {
367         NTSTATUS status;
368         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
369
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;
381         }
382
383         return result;
384 }
385
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. */
390
391 void dcerpc_get_query_dispinfo_params(int loop_count,
392                                       uint32_t *max_entries,
393                                       uint32_t *max_size)
394 {
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;
416         }
417 }
418
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)
425 {
426         NTSTATUS status;
427         union samr_ConnectInfo info_in, info_out;
428         struct samr_ConnectInfo1 info1;
429         uint32_t lvl_out = 0;
430
431         ZERO_STRUCT(info1);
432
433         info1.client_version = SAMR_CONNECT_W2K;
434         info_in.info1 = info1;
435
436         status = dcerpc_samr_Connect5(h,
437                                       mem_ctx,
438                                       srv_name_slash,
439                                       access_mask,
440                                       1,
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;
448         }
449
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;
459         }
460
461         status = dcerpc_samr_Connect2(h,
462                                       mem_ctx,
463                                       srv_name_slash,
464                                       access_mask,
465                                       connect_pol,
466                                       presult);
467
468         return status;
469 }
470
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)
475 {
476         NTSTATUS status;
477         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
478
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;
487         }
488
489         return result;
490 }
491
492 /* vim: set ts=8 sw=8 noet cindent: */