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