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