r7757: Add NTLMv2 support to the NT1 Session setup (ie, not SPNEGO/NTLMSSP)
[ira/wip.git] / source4 / torture / rpc / samlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon SamLogon operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "auth/auth.h"
28 #include "lib/crypto/crypto.h"
29 #include "lib/cmdline/popt_common.h"
30
31 #define TEST_MACHINE_NAME "samlogontest"
32 #define TEST_USER_NAME "samlogontestuser"
33
34 enum ntlm_break {
35         BREAK_BOTH,
36         BREAK_NONE,
37         BREAK_LM,
38         BREAK_NT,
39         NO_LM,
40         NO_NT
41 };
42
43 struct samlogon_state {
44         TALLOC_CTX *mem_ctx;
45         const char *account_name;
46         const char *account_domain;
47         const char *password;
48         struct dcerpc_pipe *p;
49         int function_level;
50         struct netr_LogonSamLogon r;
51         struct netr_LogonSamLogonEx r_ex;
52         struct netr_LogonSamLogonWithFlags r_flags;
53         struct netr_Authenticator auth, auth2;
54         struct creds_CredentialState *creds;
55
56         DATA_BLOB chall;
57 };
58
59 /* 
60    Authenticate a user with a challenge/response, checking session key
61    and valid authentication types
62 */
63 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, 
64                                enum ntlm_break break_which,
65                                DATA_BLOB *chall, 
66                                DATA_BLOB *lm_response, 
67                                DATA_BLOB *nt_response, 
68                                uint8_t lm_key[8], 
69                                uint8_t user_session_key[16], 
70                                char **error_string)
71 {
72         NTSTATUS status;
73         struct netr_LogonSamLogon *r = &samlogon_state->r;
74         struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
75         struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
76         struct netr_NetworkInfo ninfo;
77         struct netr_SamBaseInfo *base = NULL;
78         uint16_t validation_level = 0;
79         
80         samlogon_state->r.in.logon.network = &ninfo;
81         samlogon_state->r_ex.in.logon.network = &ninfo;
82         samlogon_state->r_flags.in.logon.network = &ninfo;
83         
84         ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
85         ninfo.identity_info.parameter_control = 0;
86         ninfo.identity_info.logon_id_low = 0;
87         ninfo.identity_info.logon_id_high = 0;
88         ninfo.identity_info.account_name.string = samlogon_state->account_name;
89         ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
90                 
91         memcpy(ninfo.challenge, chall->data, 8);
92                 
93         switch (break_which) {
94         case BREAK_NONE:
95                 break;
96         case BREAK_LM:
97                 if (lm_response && lm_response->data) {
98                         lm_response->data[0]++;
99                 }
100                 break;
101         case BREAK_NT:
102                 if (nt_response && nt_response->data) {
103                         nt_response->data[0]++;
104                 }
105                 break;
106         case BREAK_BOTH:
107                 if (lm_response && lm_response->data) {
108                         lm_response->data[0]++;
109                 }
110                 if (nt_response && nt_response->data) {
111                         nt_response->data[0]++;
112                 }
113                 break;
114         case NO_LM:
115                 data_blob_free(lm_response);
116                 break;
117         case NO_NT:
118                 data_blob_free(nt_response);
119                 break;
120         }
121                 
122         if (nt_response) {
123                 ninfo.nt.data = nt_response->data;
124                 ninfo.nt.length = nt_response->length;
125         } else {
126                 ninfo.nt.data = NULL;
127                 ninfo.nt.length = 0;
128         }
129                 
130         if (lm_response) {
131                 ninfo.lm.data = lm_response->data;
132                 ninfo.lm.length = lm_response->length;
133         } else {
134                 ninfo.lm.data = NULL;
135                 ninfo.lm.length = 0;
136         }
137         
138         switch (samlogon_state->function_level) {
139         case DCERPC_NETR_LOGONSAMLOGON: 
140                 ZERO_STRUCT(samlogon_state->auth2);
141                 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
142
143                 r->out.return_authenticator = NULL;
144                 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
145                 if (!r->out.return_authenticator || 
146                     !creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
147                         printf("Credential chaining failed\n");
148                 }
149                 if (!NT_STATUS_IS_OK(status)) {
150                         if (error_string) {
151                                 *error_string = strdup(nt_errstr(status));
152                         }
153                 }
154
155                 validation_level = r->in.validation_level;
156                 switch (validation_level) {
157                 case 2:
158                         base = &r->out.validation.sam2->base;
159                         break;
160                 case 3:
161                         base = &r->out.validation.sam3->base;
162                         break;
163                 case 6:
164                         base = &r->out.validation.sam6->base;
165                         break;
166                 }
167                 break;
168         case DCERPC_NETR_LOGONSAMLOGONEX: 
169                 status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex);
170                 if (!NT_STATUS_IS_OK(status)) {
171                         if (error_string) {
172                                 *error_string = strdup(nt_errstr(status));
173                         }
174                 }
175
176                 validation_level = r_ex->in.validation_level;
177                 switch (validation_level) {
178                 case 2:
179                         base = &r_ex->out.validation.sam2->base;
180                         break;
181                 case 3:
182                         base = &r_ex->out.validation.sam3->base;
183                         break;
184                 case 6:
185                         base = &r_ex->out.validation.sam6->base;
186                         break;
187                 }
188                 break;
189         case DCERPC_NETR_LOGONSAMLOGONWITHFLAGS: 
190                 ZERO_STRUCT(samlogon_state->auth2);
191                 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
192
193                 r_flags->out.return_authenticator = NULL;
194                 status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags);
195                 if (!r_flags->out.return_authenticator || 
196                     !creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
197                         printf("Credential chaining failed\n");
198                 }
199                 if (!NT_STATUS_IS_OK(status)) {
200                         if (error_string) {
201                                 *error_string = strdup(nt_errstr(status));
202                         }
203                 }
204
205                 validation_level = r_flags->in.validation_level;
206                 switch (validation_level) {
207                 case 2:
208                         base = &r_flags->out.validation.sam2->base;
209                         break;
210                 case 3:
211                         base = &r_flags->out.validation.sam3->base;
212                         break;
213                 case 6:
214                         base = &r_flags->out.validation.sam6->base;
215                         break;
216                 }
217                 break;
218         }
219                 
220
221         if (!NT_STATUS_IS_OK(status)) {
222                 /* we cannot check the session key, if the logon failed... */
223                 return status;
224         }
225
226         if (!base) {
227                 printf("No user info returned from 'successful' SamLogon*() call!\n");
228                 return NT_STATUS_INVALID_PARAMETER;
229         }
230
231         /* find and decyrpt the session keys, return in parameters above */
232         if (validation_level == 6) {
233                 /* they aren't encrypted! */
234                 if (user_session_key) {
235                         memcpy(user_session_key, base->key.key, 16);
236                 }
237                 if (lm_key) {
238                         memcpy(lm_key, base->LMSessKey.key, 8);
239                 }
240         } else if (samlogon_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
241                 static const char zeros[16];
242                         
243                 if (memcmp(base->key.key, zeros,  
244                            sizeof(base->key.key)) != 0) {
245                         creds_arcfour_crypt(samlogon_state->creds, 
246                                             base->key.key, 
247                                             sizeof(base->key.key));
248                 }
249                         
250                 if (user_session_key) {
251                         memcpy(user_session_key, base->key.key, 16);
252                 }
253                         
254                 if (memcmp(base->LMSessKey.key, zeros,  
255                            sizeof(base->LMSessKey.key)) != 0) {
256                         creds_arcfour_crypt(samlogon_state->creds, 
257                                             base->LMSessKey.key, 
258                                             sizeof(base->LMSessKey.key));
259                 }
260                         
261                 if (lm_key) {
262                         memcpy(lm_key, base->LMSessKey.key, 8);
263                 }
264         } else {
265                 static const char zeros[16];
266                         
267                 if (user_session_key) {
268                         memcpy(user_session_key, base->key.key, 16);
269                 }
270
271                 if (memcmp(base->LMSessKey.key, zeros,  
272                            sizeof(base->LMSessKey.key)) != 0) {
273                         creds_des_decrypt_LMKey(samlogon_state->creds, 
274                                                 &base->LMSessKey);
275                 }
276                         
277                 if (lm_key) {
278                         memcpy(lm_key, base->LMSessKey.key, 8);
279                 }
280         }
281         
282         return status;
283
284
285
286 /* 
287  * Test the normal 'LM and NTLM' combination
288  */
289
290 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
291 {
292         BOOL pass = True;
293         BOOL lm_good;
294         NTSTATUS nt_status;
295         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
296         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
297         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
298
299         uint8_t lm_key[8];
300         uint8_t user_session_key[16];
301         uint8_t lm_hash[16];
302         uint8_t nt_hash[16];
303         
304         ZERO_STRUCT(lm_key);
305         ZERO_STRUCT(user_session_key);
306
307         lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
308         if (!lm_good) {
309                 ZERO_STRUCT(lm_hash);
310         } else {
311                 E_deshash(samlogon_state->password, lm_hash); 
312         }
313                 
314         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
315
316         E_md4hash(samlogon_state->password, nt_hash);
317         SMBsesskeygen_ntv1(nt_hash, session_key.data);
318
319         nt_status = check_samlogon(samlogon_state,
320                                    break_which,
321                                    &samlogon_state->chall,
322                                    &lm_response,
323                                    &nt_response,
324                                    lm_key, 
325                                    user_session_key,
326                                    error_string);
327         
328         data_blob_free(&lm_response);
329
330         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
331                 /* for 'long' passwords, the LM password is invalid */
332                 if (break_which == NO_NT && !lm_good) {
333                         return True;
334                 }
335                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
336         }
337
338         if (!NT_STATUS_IS_OK(nt_status)) {
339                 return False;
340         }
341
342         if (break_which == NO_NT && !lm_good) {
343                 printf("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
344                 return False;
345         }
346
347         if (memcmp(lm_hash, lm_key, 
348                    sizeof(lm_key)) != 0) {
349                 printf("LM Key does not match expectations!\n");
350                 printf("lm_key:\n");
351                 dump_data(1, lm_key, 8);
352                 printf("expected:\n");
353                 dump_data(1, lm_hash, 8);
354                 pass = False;
355         }
356
357         switch (break_which) {
358         case NO_NT:
359         {
360                 uint8_t lm_key_expected[16];
361                 memcpy(lm_key_expected, lm_hash, 8);
362                 memset(lm_key_expected+8, '\0', 8);
363                 if (memcmp(lm_key_expected, user_session_key, 
364                            16) != 0) {
365                         printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
366                         printf("user_session_key:\n");
367                         dump_data(1, user_session_key, sizeof(user_session_key));
368                         printf("expected:\n");
369                         dump_data(1, lm_key_expected, sizeof(lm_key_expected));
370                         pass = False;
371                 }
372                 break;
373         }
374         default:
375                 if (memcmp(session_key.data, user_session_key, 
376                            sizeof(user_session_key)) != 0) {
377                         printf("NT Session Key does not match expectations!\n");
378                         printf("user_session_key:\n");
379                         dump_data(1, user_session_key, 16);
380                         printf("expected:\n");
381                         dump_data(1, session_key.data, session_key.length);
382                         pass = False;
383                 }
384         }
385         return pass;
386 }
387
388 /* 
389  * Test LM authentication, no NT response supplied
390  */
391
392 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string) 
393 {
394
395         return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
396 }
397
398 /* 
399  * Test the NTLM response only, no LM.
400  */
401
402 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
403 {
404         return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
405 }
406
407 /* 
408  * Test the NTLM response only, but in the LM field.
409  */
410
411 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) 
412 {
413         BOOL pass = True;
414         NTSTATUS nt_status;
415         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
416
417         uint8_t lm_key[8];
418         uint8_t lm_hash[16];
419         uint8_t user_session_key[16];
420         
421         ZERO_STRUCT(user_session_key);
422
423         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
424
425         E_deshash(samlogon_state->password, lm_hash); 
426
427         nt_status = check_samlogon(samlogon_state,
428                                    BREAK_NONE,
429                                    &samlogon_state->chall,
430                                    &nt_response,
431                                    NULL,
432                                    lm_key, 
433                                    user_session_key,
434                                    error_string);
435         
436         if (!NT_STATUS_IS_OK(nt_status)) {
437                 return False;
438         }
439
440         if (memcmp(lm_hash, lm_key, 
441                    sizeof(lm_key)) != 0) {
442                 printf("LM Key does not match expectations!\n");
443                 printf("lm_key:\n");
444                 dump_data(1, lm_key, 8);
445                 printf("expected:\n");
446                 dump_data(1, lm_hash, 8);
447                 pass = False;
448         }
449         if (memcmp(lm_hash, user_session_key, 8) != 0) {
450                 uint8_t lm_key_expected[16];
451                 memcpy(lm_key_expected, lm_hash, 8);
452                 memset(lm_key_expected+8, '\0', 8);
453                 if (memcmp(lm_key_expected, user_session_key, 
454                            16) != 0) {
455                         printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
456                         printf("user_session_key:\n");
457                         dump_data(1, user_session_key, sizeof(user_session_key));
458                         printf("expected:\n");
459                         dump_data(1, lm_key_expected, sizeof(lm_key_expected));
460                         pass = False;
461                 }
462         }
463         return pass;
464 }
465
466 /* 
467  * Test the NTLM response only, but in the both the NT and LM fields.
468  */
469
470 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) 
471 {
472         BOOL pass = True;
473         BOOL lm_good;
474         NTSTATUS nt_status;
475         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
476         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
477
478         uint8_t lm_key[8];
479         uint8_t lm_hash[16];
480         uint8_t user_session_key[16];
481         uint8_t nt_hash[16];
482         
483         ZERO_STRUCT(lm_key);
484         ZERO_STRUCT(user_session_key);
485
486         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
487                      nt_response.data);
488         E_md4hash(samlogon_state->password, nt_hash);
489         SMBsesskeygen_ntv1(nt_hash, 
490                            session_key.data);
491
492         lm_good = E_deshash(samlogon_state->password, lm_hash); 
493         if (!lm_good) {
494                 ZERO_STRUCT(lm_hash);
495         }
496
497         nt_status = check_samlogon(samlogon_state,
498                                    BREAK_NONE,
499                                    &samlogon_state->chall,
500                                    NULL, 
501                                    &nt_response,
502                                    lm_key, 
503                                    user_session_key,
504                                    error_string);
505         
506         if (!NT_STATUS_IS_OK(nt_status)) {
507                 return False;
508         }
509
510         if (memcmp(lm_hash, lm_key, 
511                    sizeof(lm_key)) != 0) {
512                 printf("LM Key does not match expectations!\n");
513                 printf("lm_key:\n");
514                 dump_data(1, lm_key, 8);
515                 printf("expected:\n");
516                 dump_data(1, lm_hash, 8);
517                 pass = False;
518         }
519         if (memcmp(session_key.data, user_session_key, 
520                    sizeof(user_session_key)) != 0) {
521                 printf("NT Session Key does not match expectations!\n");
522                 printf("user_session_key:\n");
523                 dump_data(1, user_session_key, 16);
524                 printf("expected:\n");
525                 dump_data(1, session_key.data, session_key.length);
526                 pass = False;
527         }
528
529
530         return pass;
531 }
532
533 /* 
534  * Test the NTLMv2 and LMv2 responses
535  */
536
537 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
538 {
539         BOOL pass = True;
540         NTSTATUS nt_status;
541         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
542         DATA_BLOB lmv2_response = data_blob(NULL, 0);
543         DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
544         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
545         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
546
547         uint8_t lm_session_key[8];
548         uint8_t user_session_key[16];
549
550         ZERO_STRUCT(lm_session_key);
551         ZERO_STRUCT(user_session_key);
552         
553         /* TODO - test with various domain cases, and without domain */
554         if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
555                               samlogon_state->account_name, samlogon_state->account_domain, 
556                               samlogon_state->password, &samlogon_state->chall,
557                               &names_blob,
558                               &lmv2_response, &ntlmv2_response, 
559                               &lmv2_session_key, &ntlmv2_session_key)) {
560                 data_blob_free(&names_blob);
561                 return False;
562         }
563         data_blob_free(&names_blob);
564
565         nt_status = check_samlogon(samlogon_state,
566                                    break_which,
567                                    &samlogon_state->chall,
568                                    &lmv2_response,
569                                    &ntlmv2_response,
570                                    lm_session_key, 
571                                    user_session_key,
572                                    error_string);
573         
574         data_blob_free(&lmv2_response);
575         data_blob_free(&ntlmv2_response);
576
577
578         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
579                 return break_which == BREAK_BOTH;
580         }
581
582         if (!NT_STATUS_IS_OK(nt_status)) {
583                 return False;
584         }
585
586         switch (break_which) {
587         case NO_NT:
588                 if (memcmp(lmv2_session_key.data, user_session_key,
589                            sizeof(user_session_key)) != 0) {
590                         printf("USER (LMv2) Session Key does not match expectations!\n");
591                         printf("user_session_key:\n");
592                         dump_data(1, user_session_key, 16);
593                         printf("expected:\n");
594                         dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
595                         pass = False;
596                 }
597                 if (memcmp(lmv2_session_key.data, lm_session_key, 
598                            sizeof(lm_session_key)) != 0) {
599                         printf("LM (LMv2) Session Key does not match expectations!\n");
600                         printf("lm_session_key:\n");
601                         dump_data(1, lm_session_key, 8);
602                         printf("expected:\n");
603                         dump_data(1, lmv2_session_key.data, 8);
604                         pass = False;
605                 }
606                 break;
607         default:
608                 if (memcmp(ntlmv2_session_key.data, user_session_key, 
609                            sizeof(user_session_key)) != 0) {
610                         if (memcmp(lmv2_session_key.data, user_session_key,
611                                    sizeof(user_session_key)) == 0) {
612                                 printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
613                                 printf("user_session_key:\n");
614                                 dump_data(1, user_session_key, 16);
615                                 printf("expected:\n");
616                                 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
617                                 pass = False;
618                                 
619                         } else {
620                                 printf("USER (NTLMv2) Session Key does not match expectations!\n");
621                                 printf("user_session_key:\n");
622                                 dump_data(1, user_session_key, 16);
623                                 printf("expected:\n");
624                                 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
625                                 pass = False;
626                         }
627                 }
628                 if (memcmp(ntlmv2_session_key.data, lm_session_key, 
629                            sizeof(lm_session_key)) != 0) {
630                         if (memcmp(lmv2_session_key.data, lm_session_key,
631                                    sizeof(lm_session_key)) == 0) {
632                                 printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
633                                 printf("user_session_key:\n");
634                                 dump_data(1, lm_session_key, 8);
635                                 printf("expected:\n");
636                                 dump_data(1, ntlmv2_session_key.data, 8);
637                                 pass = False;
638                         } else {
639                                 printf("LM (NTLMv2) Session Key does not match expectations!\n");
640                                 printf("lm_session_key:\n");
641                                 dump_data(1, lm_session_key, 8);
642                                 printf("expected:\n");
643                                 dump_data(1, ntlmv2_session_key.data, 8);
644                                 pass = False;
645                         }
646                 }
647         }
648
649         return pass;
650 }
651
652 /* 
653  * Test the NTLM and LMv2 responses
654  */
655
656 static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
657 {
658         BOOL pass = True;
659         NTSTATUS nt_status;
660         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
661         DATA_BLOB lmv2_response = data_blob(NULL, 0);
662         DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
663         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
664         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
665
666         DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
667         DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
668
669         uint8_t lm_hash[16];
670         uint8_t lm_session_key[8];
671         uint8_t user_session_key[16];
672         uint8_t nt_hash[16];
673
674         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
675                      ntlm_response.data);
676         E_md4hash(samlogon_state->password, nt_hash);
677         SMBsesskeygen_ntv1(nt_hash, 
678                            ntlm_session_key.data);
679         E_deshash(samlogon_state->password, lm_hash); 
680
681         ZERO_STRUCT(lm_session_key);
682         ZERO_STRUCT(user_session_key);
683         
684         /* TODO - test with various domain cases, and without domain */
685         if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
686                               samlogon_state->account_name, samlogon_state->account_domain, 
687                               samlogon_state->password, &samlogon_state->chall,
688                               &names_blob,
689                               &lmv2_response, &ntlmv2_response, 
690                               &lmv2_session_key, &ntlmv2_session_key)) {
691                 data_blob_free(&names_blob);
692                 return False;
693         }
694         data_blob_free(&names_blob);
695
696         nt_status = check_samlogon(samlogon_state,
697                                    break_which,
698                                    &samlogon_state->chall,
699                                    &lmv2_response,
700                                    &ntlm_response,
701                                    lm_session_key, 
702                                    user_session_key,
703                                    error_string);
704         
705         data_blob_free(&lmv2_response);
706         data_blob_free(&ntlmv2_response);
707
708
709         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
710                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
711         }
712
713         if (!NT_STATUS_IS_OK(nt_status)) {
714                 return False;
715         }
716
717         switch (break_which) {
718         case NO_NT:
719                 if (memcmp(lmv2_session_key.data, user_session_key, 
720                            sizeof(user_session_key)) != 0) {
721                         printf("USER (LMv2) Session Key does not match expectations!\n");
722                         printf("user_session_key:\n");
723                         dump_data(1, user_session_key, 16);
724                         printf("expected:\n");
725                         dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
726                         pass = False;
727                 }
728                 if (memcmp(lmv2_session_key.data, lm_session_key, 
729                            sizeof(lm_session_key)) != 0) {
730                         printf("LM (LMv2) Session Key does not match expectations!\n");
731                         printf("lm_session_key:\n");
732                         dump_data(1, lm_session_key, 8);
733                         printf("expected:\n");
734                         dump_data(1, lmv2_session_key.data, 8);
735                         pass = False;
736                 }
737                 break;
738         case BREAK_LM:
739                 if (memcmp(ntlm_session_key.data, user_session_key, 
740                            sizeof(user_session_key)) != 0) {
741                         printf("USER (NTLMv2) Session Key does not match expectations!\n");
742                         printf("user_session_key:\n");
743                         dump_data(1, user_session_key, 16);
744                         printf("expected:\n");
745                         dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
746                         pass = False;
747                 }
748                 if (memcmp(lm_hash, lm_session_key, 
749                            sizeof(lm_session_key)) != 0) {
750                         printf("LM Session Key does not match expectations!\n");
751                         printf("lm_session_key:\n");
752                         dump_data(1, lm_session_key, 8);
753                         printf("expected:\n");
754                         dump_data(1, lm_hash, 8);
755                         pass = False;
756                 }
757                 break;
758         default:
759                 if (memcmp(ntlm_session_key.data, user_session_key, 
760                            sizeof(user_session_key)) != 0) {
761                         printf("USER (NTLMv2) Session Key does not match expectations!\n");
762                         printf("user_session_key:\n");
763                         dump_data(1, user_session_key, 16);
764                         printf("expected:\n");
765                         dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
766                         pass = False;
767                 }
768                 if (memcmp(ntlm_session_key.data, lm_session_key, 
769                            sizeof(lm_session_key)) != 0) {
770                         printf("LM (NTLMv2) Session Key does not match expectations!\n");
771                         printf("lm_session_key:\n");
772                         dump_data(1, lm_session_key, 8);
773                         printf("expected:\n");
774                         dump_data(1, ntlm_session_key.data, 8);
775                         pass = False;
776                 }
777         }
778
779         return pass;
780 }
781
782 /* 
783  * Test the NTLMv2 and LMv2 responses
784  */
785
786 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
787 {
788         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
789 }
790
791 /* 
792  * Test the LMv2 response only
793  */
794
795 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 
796 {
797         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
798 }
799
800 /* 
801  * Test the NTLMv2 response only
802  */
803
804 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
805 {
806         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
807 }
808
809 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
810 {
811         return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
812 }
813
814 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 
815 {
816         return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
817 }
818
819 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 
820 {
821         return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
822 }
823
824 static BOOL test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
825 {
826         return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
827 }
828 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
829 {
830         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
831 }
832
833 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
834 {
835         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
836 }
837
838 static BOOL test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
839 {
840         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, error_string);
841 }
842
843 static BOOL test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
844 {
845         return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
846 }
847
848 static BOOL test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
849 {
850         return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, error_string);
851 }
852
853 static BOOL test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string) 
854 {
855         return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, error_string);
856 }
857
858 /* 
859  * Test the NTLM2 response (extra challenge in LM feild)
860  *
861  * This test is the same as the 'break LM' test, but checks that the
862  * server implements NTLM2 session security in the right place
863  * (NETLOGON is the wrong place).
864  */
865
866 static BOOL test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) 
867 {
868         BOOL pass = True;
869         NTSTATUS nt_status;
870         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
871         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
872
873         uint8_t lm_key[8];
874         uint8_t nt_hash[16];
875         uint8_t lm_hash[16];
876         uint8_t nt_key[16];
877         uint8_t user_session_key[16];
878         uint8_t expected_user_session_key[16];
879         uint8_t session_nonce_hash[16];
880         uint8_t client_chall[8];
881         
882         struct MD5Context md5_session_nonce_ctx;
883         HMACMD5Context hmac_ctx;
884                         
885         ZERO_STRUCT(user_session_key);
886         ZERO_STRUCT(lm_key);
887         generate_random_buffer(client_chall, 8);
888         
889         MD5Init(&md5_session_nonce_ctx);
890         MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8);
891         MD5Update(&md5_session_nonce_ctx, client_chall, 8);
892         MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
893         
894         E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
895         E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
896         SMBsesskeygen_ntv1((const uint8_t *)nt_hash, 
897                            nt_key);
898
899         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
900
901         memcpy(lm_response.data, session_nonce_hash, 8);
902         memset(lm_response.data + 8, 0, 16);
903
904         hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx);
905         hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx);
906         hmac_md5_update(client_chall, 8, &hmac_ctx);
907         hmac_md5_final(expected_user_session_key, &hmac_ctx);
908
909         nt_status = check_samlogon(samlogon_state,
910                                    BREAK_NONE,
911                                    &samlogon_state->chall,
912                                    &lm_response,
913                                    &nt_response,
914                                    lm_key, 
915                                    user_session_key,
916                                    error_string);
917         
918         if (!NT_STATUS_IS_OK(nt_status)) {
919                 return False;
920         }
921
922         if (memcmp(lm_hash, lm_key, 
923                    sizeof(lm_key)) != 0) {
924                 printf("LM Key does not match expectations!\n");
925                 printf("lm_key:\n");
926                 dump_data(1, lm_key, 8);
927                 printf("expected:\n");
928                 dump_data(1, lm_hash, 8);
929                 pass = False;
930         }
931         if (memcmp(nt_key, user_session_key, 16) != 0) {
932                 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
933                 printf("user_session_key:\n");
934                 dump_data(1, user_session_key, sizeof(user_session_key));
935                 printf("expected:\n");
936                 dump_data(1, nt_key, sizeof(nt_key));
937                 pass = False;
938         }
939         return pass;
940 }
941
942 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
943 {
944         NTSTATUS nt_status;
945         DATA_BLOB nt_response = data_blob(NULL, 0);
946         DATA_BLOB lm_response = data_blob(NULL, 0);
947         char *password;
948         char *dospw;
949         void *unicodepw;
950
951         uint8_t user_session_key[16];
952         uint8_t lm_key[16];
953         static const uint8_t zeros[8];
954         DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
955
956         ZERO_STRUCT(user_session_key);
957         
958         if ((push_ucs2_talloc(samlogon_state->mem_ctx, &unicodepw, 
959                               samlogon_state->password)) == -1) {
960                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
961                 exit(1);
962         }
963
964         nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
965
966         password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
967
968         if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX, 
969                                    CH_DOS, password,
970                                    strlen(password)+1, 
971                                    (void**)&dospw)) == -1) {
972                 DEBUG(0, ("convert_string_talloc failed!\n"));
973                 exit(1);
974         }
975
976         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
977
978         nt_status = check_samlogon(samlogon_state,
979                                    break_which,
980                                    &chall,
981                                    &lm_response,
982                                    &nt_response,
983                                    lm_key, 
984                                    user_session_key,
985                                    error_string);
986         
987         if (!NT_STATUS_IS_OK(nt_status)) {
988                 return break_which == BREAK_NT;
989         }
990
991         return True;
992 }
993
994 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
995                                        char **error_string) {
996         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
997 }
998
999 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
1000                                      char **error_string) {
1001         return test_plaintext(samlogon_state, BREAK_LM, error_string);
1002 }
1003
1004 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
1005                                      char **error_string) {
1006         return test_plaintext(samlogon_state, BREAK_NT, error_string);
1007 }
1008
1009 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
1010                                    char **error_string) {
1011         return test_plaintext(samlogon_state, NO_LM, error_string);
1012 }
1013
1014 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
1015                                    char **error_string) {
1016         return test_plaintext(samlogon_state, NO_NT, error_string);
1017 }
1018
1019 /* 
1020    Tests:
1021    
1022    - LM only
1023    - NT and LM             
1024    - NT
1025    - NT in LM field
1026    - NT in both fields
1027    - NTLMv2
1028    - NTLMv2 and LMv2
1029    - LMv2
1030    - plaintext tests (in challenge-response fields)
1031   
1032    check we get the correct session key in each case
1033    check what values we get for the LM session key
1034    
1035 */
1036
1037 static const struct ntlm_tests {
1038         BOOL (*fn)(struct samlogon_state *, char **);
1039         const char *name;
1040         BOOL expect_fail;
1041 } test_table[] = {
1042         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
1043         {test_lm, "LM", False},
1044         {test_lm_ntlm, "LM and NTLM", False},
1045         {test_lm_ntlm_both_broken, "LM and NTLM, both broken", False},
1046         {test_ntlm, "NTLM", False},
1047         {test_ntlm_in_lm, "NTLM in LM", False},
1048         {test_ntlm_in_both, "NTLM in both", False},
1049         {test_ntlmv2, "NTLMv2", False},
1050         {test_lmv2, "LMv2", False},
1051         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
1052         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
1053         {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", False},
1054         {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
1055         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
1056         {test_ntlm2, "NTLM2 (NTLMv2 session security)", False},
1057         {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", False},
1058         {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", False},
1059         {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", False},
1060         {test_plaintext_none_broken, "Plaintext", True},
1061         {test_plaintext_lm_broken, "Plaintext LM broken", True},
1062         {test_plaintext_nt_broken, "Plaintext NT broken", True},
1063         {test_plaintext_nt_only, "Plaintext NT only", True},
1064         {test_plaintext_lm_only, "Plaintext LM only", True},
1065         {NULL, NULL}
1066 };
1067
1068 /*
1069   try a netlogon SamLogon
1070 */
1071 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1072                           struct creds_CredentialState *creds, 
1073                           const char *account_domain, const char *account_name, 
1074                           const char *plain_pass,
1075                           int n_subtests)
1076 {
1077         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1078         int i, v, l, f;
1079         BOOL ret = True;
1080         int validation_levels[] = {2,3,6};
1081         int logon_levels[] = { 2, 6 };
1082         int function_levels[] = { 
1083                 DCERPC_NETR_LOGONSAMLOGON,
1084                 DCERPC_NETR_LOGONSAMLOGONEX,
1085                 DCERPC_NETR_LOGONSAMLOGONWITHFLAGS };
1086         struct samlogon_state samlogon_state;
1087         
1088         printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1089         
1090         samlogon_state.account_name = account_name;
1091         samlogon_state.account_domain = account_domain;
1092         samlogon_state.password = plain_pass;
1093         samlogon_state.p = p;
1094         samlogon_state.creds = creds;
1095
1096         samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1097
1098         generate_random_buffer(samlogon_state.chall.data, 8);
1099         samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1100         samlogon_state.r_flags.in.workstation = TEST_MACHINE_NAME;
1101         samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1102         samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1103         samlogon_state.r_flags.in.flags = 0;
1104
1105         samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1106         samlogon_state.r_ex.in.workstation = TEST_MACHINE_NAME;
1107         samlogon_state.r_ex.in.flags = 0;
1108
1109         samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1110         samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
1111         samlogon_state.r.in.credential = &samlogon_state.auth;
1112         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1113
1114         for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1115                 for (i=0; test_table[i].fn; i++) {
1116                         if (n_subtests && (i > n_subtests)) {
1117                                 continue;
1118                         }
1119                         for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1120                                 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1121                                         char *error_string = NULL;
1122                                         TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1123                                         samlogon_state.mem_ctx = tmp_ctx;
1124                                         samlogon_state.function_level = function_levels[f];
1125                                         samlogon_state.r.in.validation_level = validation_levels[v];
1126                                         samlogon_state.r.in.logon_level = logon_levels[l];
1127                                         samlogon_state.r_ex.in.validation_level = validation_levels[v];
1128                                         samlogon_state.r_ex.in.logon_level = logon_levels[l];
1129                                         samlogon_state.r_flags.in.validation_level = validation_levels[v];
1130                                         samlogon_state.r_flags.in.logon_level = logon_levels[l];
1131                                         if (!test_table[i].fn(&samlogon_state, &error_string)) {
1132                                                 printf("Testing [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n", 
1133                                                        samlogon_state.account_domain,
1134                                                        samlogon_state.account_name,
1135                                                        test_table[i].name, validation_levels[v], 
1136                                                        logon_levels[l], function_levels[f]);
1137                                                 
1138                                                 if (test_table[i].expect_fail) {
1139                                                         printf(" failed (expected, test incomplete): %s\n", error_string);
1140                                                 } else {
1141                                                         printf(" failed: %s\n", error_string);
1142                                                         ret = False;
1143                                                 }
1144                                                 SAFE_FREE(error_string);
1145                                         }
1146                                         talloc_free(tmp_ctx);
1147                                 }
1148                         }
1149                 }
1150         }
1151         talloc_free(fn_ctx);
1152         return ret;
1153 }
1154
1155 /*
1156   test an ADS style interactive domain logon
1157 */
1158 static BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1159                                   struct creds_CredentialState *creds, 
1160                                   const char *account_domain, const char *account_name,
1161                                   const char *plain_pass)
1162 {
1163         NTSTATUS status;
1164         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1165         struct netr_LogonSamLogonWithFlags r;
1166         struct netr_Authenticator a, ra;
1167         struct netr_PasswordInfo pinfo;
1168
1169         ZERO_STRUCT(a);
1170         ZERO_STRUCT(r);
1171         ZERO_STRUCT(ra);
1172
1173         creds_client_authenticator(creds, &a);
1174
1175         r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1176         r.in.workstation = TEST_MACHINE_NAME;
1177         r.in.credential = &a;
1178         r.in.return_authenticator = &ra;
1179         r.in.logon_level = 5;
1180         r.in.logon.password = &pinfo;
1181         r.in.validation_level = 6;
1182         r.in.flags = 0;
1183
1184         pinfo.identity_info.domain_name.string = account_domain;
1185         pinfo.identity_info.parameter_control = 0;
1186         pinfo.identity_info.logon_id_low = 0;
1187         pinfo.identity_info.logon_id_high = 0;
1188         pinfo.identity_info.account_name.string = account_name;
1189         pinfo.identity_info.workstation.string = TEST_MACHINE_NAME;
1190
1191         E_deshash(plain_pass, pinfo.lmpassword.hash);
1192         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1193
1194         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1195                 creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1196                 creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1197         } else {
1198                 creds_des_encrypt(creds, &pinfo.lmpassword);
1199                 creds_des_encrypt(creds, &pinfo.ntpassword);
1200         }
1201
1202         printf("Testing netr_LogonSamLogonWithFlags (Interactive Logon)\n");
1203
1204         status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);
1205         if (!r.out.return_authenticator || !creds_client_check(creds, &r.out.return_authenticator->cred)) {
1206                 printf("Credential chaining failed\n");
1207                 talloc_free(fn_ctx);
1208                 return False;
1209         }
1210
1211         talloc_free(fn_ctx);
1212
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - %s\n", account_name, account_domain, nt_errstr(status));
1215                 return False;
1216         }
1217
1218         return True;
1219 }
1220
1221
1222
1223 BOOL torture_rpc_samlogon(void)
1224 {
1225         NTSTATUS status;
1226         struct dcerpc_pipe *p;
1227         struct dcerpc_binding *b;
1228         struct cli_credentials *credentials;
1229         TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1230         BOOL ret = True;
1231         struct test_join *join_ctx;
1232 #if 0
1233         struct test_join *user_ctx;
1234         const char *user_password;
1235 #endif
1236         char *test_machine_account;
1237         const char *machine_password;
1238         const char *binding = lp_parm_string(-1, "torture", "binding");
1239         int i;
1240         int ci;
1241
1242         unsigned int credential_flags[] = {
1243                 NETLOGON_NEG_AUTH2_FLAGS,
1244                 NETLOGON_NEG_ARCFOUR,
1245                 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1246                 NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1247                 0 /* yes, this is a valid flag, causes the use of DES */ 
1248         };
1249
1250         struct creds_CredentialState *creds;
1251
1252         struct {
1253                 const char *domain;
1254                 const char *username;
1255                 const char *password;
1256                 BOOL network_login;
1257         } usercreds[] = {
1258                 {
1259                         cli_credentials_get_domain(cmdline_credentials),
1260                         cli_credentials_get_username(cmdline_credentials),
1261                         cli_credentials_get_password(cmdline_credentials),
1262                         True
1263                 },
1264                 {
1265                         cli_credentials_get_realm(cmdline_credentials),
1266                         cli_credentials_get_username(cmdline_credentials),
1267                         cli_credentials_get_password(cmdline_credentials),
1268                         True
1269                 },
1270                 {
1271                         NULL,
1272                         talloc_asprintf(mem_ctx, 
1273                                         "%s@%s", 
1274                                         cli_credentials_get_username(cmdline_credentials),
1275                                         cli_credentials_get_domain(cmdline_credentials)
1276                                 ),
1277                         cli_credentials_get_password(cmdline_credentials),
1278                         False
1279                 },
1280                 {
1281                         NULL,
1282                         talloc_asprintf(mem_ctx, 
1283                                         "%s@%s", 
1284                                         cli_credentials_get_username(cmdline_credentials),
1285                                         cli_credentials_get_realm(cmdline_credentials)
1286                                 ),
1287                         cli_credentials_get_password(cmdline_credentials),
1288                         True
1289                 },
1290 #if 0
1291                 {       
1292                         lp_parm_string(-1, "torture", "userdomain"),
1293                         TEST_USER_NAME,
1294                         NULL,
1295                         True
1296                 },
1297                 {
1298                         NULL,
1299                         talloc_asprintf(mem_ctx, 
1300                                         "%s@%s", 
1301                                         TEST_USER_NAME,
1302                                         lp_realm()),
1303                         NULL,
1304                         True
1305                 },
1306                 {
1307                         NULL,
1308                         talloc_asprintf(mem_ctx, 
1309                                         "%s@%s", 
1310                                         TEST_USER_NAME,
1311                                         lp_parm_string(-1, "torture", "userdomain")),
1312                         NULL,
1313                         False
1314                 }
1315 #endif
1316         };
1317                 
1318         credentials = cli_credentials_init(mem_ctx);
1319
1320         test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1321         /* We only need to join as a workstation here, and in future,
1322          * if we wish to test against trusted domains, we must be a
1323          * workstation here */
1324         join_ctx = torture_create_testuser(test_machine_account, lp_workgroup(), ACB_WSTRUST, 
1325                                            &machine_password);
1326         if (!join_ctx) {
1327                 printf("Failed to join as Workstation\n");
1328                 return False;
1329         }
1330 #if 0
1331         user_ctx = torture_create_testuser(TEST_USER_NAME,
1332                                            lp_parm_string(-1, "torture", "userdomain"),
1333                                            ACB_NORMAL, 
1334                                            &user_password);
1335         if (!user_ctx) {
1336                 printf("Failed to join as Workstation\n");
1337                 return False;
1338         }
1339
1340         usercreds[3].password = user_password;
1341         usercreds[4].password = user_password;
1342         usercreds[5].password = user_password;
1343 #endif
1344
1345         status = dcerpc_parse_binding(mem_ctx, binding, &b);
1346         if (!NT_STATUS_IS_OK(status)) {
1347                 printf("Bad binding string %s\n", binding);
1348                 ret = False;
1349                 goto failed;
1350         }
1351
1352         /* We have to use schannel, otherwise the SamLogonEx fails
1353          * with INTERNAL_ERROR */
1354
1355         b->flags &= ~DCERPC_AUTH_OPTIONS;
1356         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
1357
1358         cli_credentials_set_workstation(credentials, TEST_MACHINE_NAME, CRED_SPECIFIED);
1359         cli_credentials_set_domain(credentials, lp_workgroup(), CRED_SPECIFIED);
1360         cli_credentials_set_username(credentials, test_machine_account, CRED_SPECIFIED);
1361         cli_credentials_set_password(credentials, machine_password, CRED_SPECIFIED);
1362         cli_credentials_set_secure_channel_type(credentials,
1363                                                 SEC_CHAN_WKSTA);
1364
1365         status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 
1366                                        DCERPC_NETLOGON_UUID,
1367                                        DCERPC_NETLOGON_VERSION,
1368                                        credentials, NULL);
1369
1370         if (!NT_STATUS_IS_OK(status)) {
1371                 printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
1372                 ret = False;
1373                 goto failed;
1374         }
1375
1376         status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
1377         if (!NT_STATUS_IS_OK(status)) {
1378                 ret = False;
1379                 goto failed;
1380         }
1381
1382         /* Try all the tests for different username forms */
1383         for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1384                 
1385                 if (!test_InteractiveLogon(p, mem_ctx, creds,
1386                                            usercreds[ci].domain,
1387                                            usercreds[ci].username,
1388                                            usercreds[ci].password)) {
1389                         ret = False;
1390                 }
1391                 
1392                 if (usercreds[ci].network_login) {
1393                         if (!test_SamLogon(p, mem_ctx, creds, 
1394                                            usercreds[ci].domain,
1395                                            usercreds[ci].username,
1396                                            usercreds[ci].password,
1397                                            0)) {
1398                                 ret = False;
1399                         }
1400                 }
1401         }
1402
1403         /* Using the first username form, try the different
1404          * credentials flag setups, on only one of the tests (checks
1405          * session key encryption) */
1406
1407         for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1408                 if (!test_InteractiveLogon(p, mem_ctx, creds,
1409                                            usercreds[0].domain,
1410                                            usercreds[0].username,
1411                                            usercreds[0].password)) {
1412                         ret = False;
1413                 }
1414                 
1415                 if (usercreds[ci].network_login) {
1416                         if (!test_SamLogon(p, mem_ctx, creds, 
1417                                            usercreds[0].domain,
1418                                            usercreds[0].username,
1419                                            usercreds[0].password,
1420                                            1)) {
1421                                 ret = False;
1422                         }
1423                 }
1424         }
1425
1426 failed:
1427         talloc_free(mem_ctx);
1428
1429         torture_leave_domain(join_ctx);
1430 #if 0
1431         torture_leave_domain(user_ctx);
1432 #endif
1433         return ret;
1434 }