~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/utils/ntlm_auth_diagnostics.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Unix SMB/CIFS implementation.
3
 
 
4
 
   Winbind status program.
5
 
 
6
 
   Copyright (C) Tim Potter      2000-2003
7
 
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8
 
   Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000 
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 "utils/ntlm_auth.h"
27
 
 
28
 
#undef DBGC_CLASS
29
 
#define DBGC_CLASS DBGC_WINBIND
30
 
 
31
 
enum ntlm_break {
32
 
        BREAK_NONE,
33
 
        BREAK_LM,
34
 
        BREAK_NT,
35
 
        NO_LM,
36
 
        NO_NT
37
 
};
38
 
 
39
 
/* 
40
 
   Authenticate a user with a challenge/response, checking session key
41
 
   and valid authentication types
42
 
*/
43
 
 
44
 
/* 
45
 
 * Test the normal 'LM and NTLM' combination
46
 
 */
47
 
 
48
 
static BOOL test_lm_ntlm_broken(enum ntlm_break break_which) 
49
 
{
50
 
        BOOL pass = True;
51
 
        NTSTATUS nt_status;
52
 
        uint32 flags = 0;
53
 
        DATA_BLOB lm_response = data_blob(NULL, 24);
54
 
        DATA_BLOB nt_response = data_blob(NULL, 24);
55
 
        DATA_BLOB session_key = data_blob(NULL, 16);
56
 
 
57
 
        uchar lm_key[8];
58
 
        uchar user_session_key[16];
59
 
        uchar lm_hash[16];
60
 
        uchar nt_hash[16];
61
 
        DATA_BLOB chall = get_challenge();
62
 
        char *error_string;
63
 
        
64
 
        ZERO_STRUCT(lm_key);
65
 
        ZERO_STRUCT(user_session_key);
66
 
 
67
 
        flags |= WBFLAG_PAM_LMKEY;
68
 
        flags |= WBFLAG_PAM_USER_SESSION_KEY;
69
 
 
70
 
        SMBencrypt(opt_password,chall.data,lm_response.data);
71
 
        E_deshash(opt_password, lm_hash); 
72
 
 
73
 
        SMBNTencrypt(opt_password,chall.data,nt_response.data);
74
 
 
75
 
        E_md4hash(opt_password, nt_hash);
76
 
        SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
77
 
 
78
 
        switch (break_which) {
79
 
        case BREAK_NONE:
80
 
                break;
81
 
        case BREAK_LM:
82
 
                lm_response.data[0]++;
83
 
                break;
84
 
        case BREAK_NT:
85
 
                nt_response.data[0]++;
86
 
                break;
87
 
        case NO_LM:
88
 
                data_blob_free(&lm_response);
89
 
                break;
90
 
        case NO_NT:
91
 
                data_blob_free(&nt_response);
92
 
                break;
93
 
        }
94
 
 
95
 
        nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
96
 
                                              opt_workstation,
97
 
                                              &chall,
98
 
                                              &lm_response,
99
 
                                              &nt_response,
100
 
                                              flags,
101
 
                                              lm_key, 
102
 
                                              user_session_key,
103
 
                                              &error_string, NULL);
104
 
        
105
 
        data_blob_free(&lm_response);
106
 
 
107
 
        if (!NT_STATUS_IS_OK(nt_status)) {
108
 
                d_printf("%s (0x%x)\n", 
109
 
                         error_string,
110
 
                         NT_STATUS_V(nt_status));
111
 
                SAFE_FREE(error_string);
112
 
                return break_which == BREAK_NT;
113
 
        }
114
 
 
115
 
        if (memcmp(lm_hash, lm_key, 
116
 
                   sizeof(lm_key)) != 0) {
117
 
                DEBUG(1, ("LM Key does not match expectations!\n"));
118
 
                DEBUG(1, ("lm_key:\n"));
119
 
                dump_data(1, (const char *)lm_key, 8);
120
 
                DEBUG(1, ("expected:\n"));
121
 
                dump_data(1, (const char *)lm_hash, 8);
122
 
                pass = False;
123
 
        }
124
 
 
125
 
        if (break_which == NO_NT) {
126
 
                if (memcmp(lm_hash, user_session_key, 
127
 
                           8) != 0) {
128
 
                        DEBUG(1, ("NT Session Key does not match expectations (should be LM hash)!\n"));
129
 
                        DEBUG(1, ("user_session_key:\n"));
130
 
                        dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
131
 
                        DEBUG(1, ("expected:\n"));
132
 
                        dump_data(1, (const char *)lm_hash, sizeof(lm_hash));
133
 
                        pass = False;
134
 
                }
135
 
        } else {                
136
 
                if (memcmp(session_key.data, user_session_key, 
137
 
                           sizeof(user_session_key)) != 0) {
138
 
                        DEBUG(1, ("NT Session Key does not match expectations!\n"));
139
 
                        DEBUG(1, ("user_session_key:\n"));
140
 
                        dump_data(1, (const char *)user_session_key, 16);
141
 
                        DEBUG(1, ("expected:\n"));
142
 
                        dump_data(1, (const char *)session_key.data, session_key.length);
143
 
                        pass = False;
144
 
                }
145
 
        }
146
 
        return pass;
147
 
}
148
 
 
149
 
/* 
150
 
 * Test LM authentication, no NT response supplied
151
 
 */
152
 
 
153
 
static BOOL test_lm(void) 
154
 
{
155
 
 
156
 
        return test_lm_ntlm_broken(NO_NT);
157
 
}
158
 
 
159
 
/* 
160
 
 * Test the NTLM response only, no LM.
161
 
 */
162
 
 
163
 
static BOOL test_ntlm(void) 
164
 
{
165
 
        return test_lm_ntlm_broken(NO_LM);
166
 
}
167
 
 
168
 
/* 
169
 
 * Test the NTLM response only, but in the LM field.
170
 
 */
171
 
 
172
 
static BOOL test_ntlm_in_lm(void) 
173
 
{
174
 
        BOOL pass = True;
175
 
        NTSTATUS nt_status;
176
 
        uint32 flags = 0;
177
 
        DATA_BLOB nt_response = data_blob(NULL, 24);
178
 
 
179
 
        uchar lm_key[8];
180
 
        uchar lm_hash[16];
181
 
        uchar user_session_key[16];
182
 
        DATA_BLOB chall = get_challenge();
183
 
        char *error_string;
184
 
        
185
 
        ZERO_STRUCT(user_session_key);
186
 
 
187
 
        flags |= WBFLAG_PAM_LMKEY;
188
 
        flags |= WBFLAG_PAM_USER_SESSION_KEY;
189
 
 
190
 
        SMBNTencrypt(opt_password,chall.data,nt_response.data);
191
 
 
192
 
        E_deshash(opt_password, lm_hash); 
193
 
 
194
 
        nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
195
 
                                              opt_workstation,
196
 
                                              &chall,
197
 
                                              &nt_response,
198
 
                                              NULL,
199
 
                                              flags,
200
 
                                              lm_key,
201
 
                                              user_session_key,
202
 
                                              &error_string, NULL);
203
 
        
204
 
        data_blob_free(&nt_response);
205
 
 
206
 
        if (!NT_STATUS_IS_OK(nt_status)) {
207
 
                d_printf("%s (0x%x)\n", 
208
 
                         error_string,
209
 
                         NT_STATUS_V(nt_status));
210
 
                SAFE_FREE(error_string);
211
 
                return False;
212
 
        }
213
 
 
214
 
        if (memcmp(lm_hash, lm_key, 
215
 
                   sizeof(lm_key)) != 0) {
216
 
                DEBUG(1, ("LM Key does not match expectations!\n"));
217
 
                DEBUG(1, ("lm_key:\n"));
218
 
                dump_data(1, (const char *)lm_key, 8);
219
 
                DEBUG(1, ("expected:\n"));
220
 
                dump_data(1, (const char *)lm_hash, 8);
221
 
                pass = False;
222
 
        }
223
 
        if (memcmp(lm_hash, user_session_key, 8) != 0) {
224
 
                DEBUG(1, ("Session Key (first 8 lm hash) does not match expectations!\n"));
225
 
                DEBUG(1, ("user_session_key:\n"));
226
 
                dump_data(1, (const char *)user_session_key, 16);
227
 
                DEBUG(1, ("expected:\n"));
228
 
                dump_data(1, (const char *)lm_hash, 8);
229
 
                pass = False;
230
 
        }
231
 
        return pass;
232
 
}
233
 
 
234
 
/* 
235
 
 * Test the NTLM response only, but in the both the NT and LM fields.
236
 
 */
237
 
 
238
 
static BOOL test_ntlm_in_both(void) 
239
 
{
240
 
        BOOL pass = True;
241
 
        NTSTATUS nt_status;
242
 
        uint32 flags = 0;
243
 
        DATA_BLOB nt_response = data_blob(NULL, 24);
244
 
        DATA_BLOB session_key = data_blob(NULL, 16);
245
 
 
246
 
        char lm_key[8];
247
 
        char lm_hash[16];
248
 
        char user_session_key[16];
249
 
        char nt_hash[16];
250
 
        DATA_BLOB chall = get_challenge();
251
 
        char *error_string;
252
 
        
253
 
        ZERO_STRUCT(lm_key);
254
 
        ZERO_STRUCT(user_session_key);
255
 
 
256
 
        flags |= WBFLAG_PAM_LMKEY;
257
 
        flags |= WBFLAG_PAM_USER_SESSION_KEY;
258
 
 
259
 
        SMBNTencrypt(opt_password,chall.data,nt_response.data);
260
 
        E_md4hash(opt_password, (unsigned char *)nt_hash);
261
 
        SMBsesskeygen_ntv1((const unsigned char *)nt_hash, NULL, session_key.data);
262
 
 
263
 
        E_deshash(opt_password, (unsigned char *)lm_hash); 
264
 
 
265
 
        nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
266
 
                                              opt_workstation,
267
 
                                              &chall,
268
 
                                              &nt_response,
269
 
                                              &nt_response,
270
 
                                              flags,
271
 
                                              (unsigned char *)lm_key,
272
 
                                              (unsigned char *)user_session_key,
273
 
                                              &error_string, NULL);
274
 
        
275
 
        data_blob_free(&nt_response);
276
 
 
277
 
        if (!NT_STATUS_IS_OK(nt_status)) {
278
 
                d_printf("%s (0x%x)\n", 
279
 
                         error_string,
280
 
                         NT_STATUS_V(nt_status));
281
 
                SAFE_FREE(error_string);
282
 
                return False;
283
 
        }
284
 
 
285
 
        if (memcmp(lm_hash, lm_key, 
286
 
                   sizeof(lm_key)) != 0) {
287
 
                DEBUG(1, ("LM Key does not match expectations!\n"));
288
 
                DEBUG(1, ("lm_key:\n"));
289
 
                dump_data(1, lm_key, 8);
290
 
                DEBUG(1, ("expected:\n"));
291
 
                dump_data(1, lm_hash, 8);
292
 
                pass = False;
293
 
        }
294
 
        if (memcmp(session_key.data, user_session_key, 
295
 
                   sizeof(user_session_key)) != 0) {
296
 
                DEBUG(1, ("NT Session Key does not match expectations!\n"));
297
 
                DEBUG(1, ("user_session_key:\n"));
298
 
                dump_data(1, user_session_key, 16);
299
 
                DEBUG(1, ("expected:\n"));
300
 
                dump_data(1, (const char *)session_key.data, session_key.length);
301
 
                pass = False;
302
 
        }
303
 
 
304
 
 
305
 
        return pass;
306
 
}
307
 
 
308
 
/* 
309
 
 * Test the NTLMv2 and LMv2 responses
310
 
 */
311
 
 
312
 
static BOOL test_lmv2_ntlmv2_broken(enum ntlm_break break_which) 
313
 
{
314
 
        BOOL pass = True;
315
 
        NTSTATUS nt_status;
316
 
        uint32 flags = 0;
317
 
        DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
318
 
        DATA_BLOB lmv2_response = data_blob(NULL, 0);
319
 
        DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
320
 
        DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain());
321
 
 
322
 
        uchar user_session_key[16];
323
 
        DATA_BLOB chall = get_challenge();
324
 
        char *error_string;
325
 
 
326
 
        ZERO_STRUCT(user_session_key);
327
 
        
328
 
        flags |= WBFLAG_PAM_USER_SESSION_KEY;
329
 
 
330
 
        if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall,
331
 
                              &names_blob,
332
 
                              &lmv2_response, &ntlmv2_response, 
333
 
                              &ntlmv2_session_key)) {
334
 
                data_blob_free(&names_blob);
335
 
                return False;
336
 
        }
337
 
        data_blob_free(&names_blob);
338
 
 
339
 
        switch (break_which) {
340
 
        case BREAK_NONE:
341
 
                break;
342
 
        case BREAK_LM:
343
 
                lmv2_response.data[0]++;
344
 
                break;
345
 
        case BREAK_NT:
346
 
                ntlmv2_response.data[0]++;
347
 
                break;
348
 
        case NO_LM:
349
 
                data_blob_free(&lmv2_response);
350
 
                break;
351
 
        case NO_NT:
352
 
                data_blob_free(&ntlmv2_response);
353
 
                break;
354
 
        }
355
 
 
356
 
        nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
357
 
                                              opt_workstation,
358
 
                                              &chall,
359
 
                                              &lmv2_response,
360
 
                                              &ntlmv2_response,
361
 
                                              flags,
362
 
                                              NULL, 
363
 
                                              user_session_key,
364
 
                                              &error_string, NULL);
365
 
        
366
 
        data_blob_free(&lmv2_response);
367
 
        data_blob_free(&ntlmv2_response);
368
 
 
369
 
        if (!NT_STATUS_IS_OK(nt_status)) {
370
 
                d_printf("%s (0x%x)\n", 
371
 
                         error_string,
372
 
                         NT_STATUS_V(nt_status));
373
 
                SAFE_FREE(error_string);
374
 
                return break_which == BREAK_NT;
375
 
        }
376
 
 
377
 
        if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, 
378
 
                   sizeof(user_session_key)) != 0) {
379
 
                DEBUG(1, ("USER (NTLMv2) Session Key does not match expectations!\n"));
380
 
                DEBUG(1, ("user_session_key:\n"));
381
 
                dump_data(1, (const char *)user_session_key, 16);
382
 
                DEBUG(1, ("expected:\n"));
383
 
                dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
384
 
                pass = False;
385
 
        }
386
 
        return pass;
387
 
}
388
 
 
389
 
/* 
390
 
 * Test the NTLMv2 and LMv2 responses
391
 
 */
392
 
 
393
 
static BOOL test_lmv2_ntlmv2(void) 
394
 
{
395
 
        return test_lmv2_ntlmv2_broken(BREAK_NONE);
396
 
}
397
 
 
398
 
/* 
399
 
 * Test the LMv2 response only
400
 
 */
401
 
 
402
 
static BOOL test_lmv2(void) 
403
 
{
404
 
        return test_lmv2_ntlmv2_broken(NO_NT);
405
 
}
406
 
 
407
 
/* 
408
 
 * Test the NTLMv2 response only
409
 
 */
410
 
 
411
 
static BOOL test_ntlmv2(void) 
412
 
{
413
 
        return test_lmv2_ntlmv2_broken(NO_LM);
414
 
}
415
 
 
416
 
static BOOL test_lm_ntlm(void) 
417
 
{
418
 
        return test_lm_ntlm_broken(BREAK_NONE);
419
 
}
420
 
 
421
 
static BOOL test_ntlm_lm_broken(void) 
422
 
{
423
 
        return test_lm_ntlm_broken(BREAK_LM);
424
 
}
425
 
 
426
 
static BOOL test_ntlm_ntlm_broken(void) 
427
 
{
428
 
        return test_lm_ntlm_broken(BREAK_NT);
429
 
}
430
 
 
431
 
static BOOL test_ntlmv2_lmv2_broken(void) 
432
 
{
433
 
        return test_lmv2_ntlmv2_broken(BREAK_LM);
434
 
}
435
 
 
436
 
static BOOL test_ntlmv2_ntlmv2_broken(void) 
437
 
{
438
 
        return test_lmv2_ntlmv2_broken(BREAK_NT);
439
 
}
440
 
 
441
 
static BOOL test_plaintext(enum ntlm_break break_which)
442
 
{
443
 
        NTSTATUS nt_status;
444
 
        uint32 flags = 0;
445
 
        DATA_BLOB nt_response = data_blob(NULL, 0);
446
 
        DATA_BLOB lm_response = data_blob(NULL, 0);
447
 
        char *password;
448
 
        smb_ucs2_t *nt_response_ucs2;
449
 
 
450
 
        uchar user_session_key[16];
451
 
        uchar lm_key[16];
452
 
        static const uchar zeros[8];
453
 
        DATA_BLOB chall = data_blob(zeros, sizeof(zeros));
454
 
        char *error_string;
455
 
 
456
 
        ZERO_STRUCT(user_session_key);
457
 
        
458
 
        flags |= WBFLAG_PAM_LMKEY;
459
 
        flags |= WBFLAG_PAM_USER_SESSION_KEY;
460
 
 
461
 
        if ((push_ucs2_allocate(&nt_response_ucs2, opt_password)) == -1) {
462
 
                DEBUG(0, ("push_ucs2_allocate failed!\n"));
463
 
                exit(1);
464
 
        }
465
 
 
466
 
        nt_response.data = (unsigned char *)nt_response_ucs2;
467
 
        nt_response.length = strlen_w(nt_response_ucs2)*sizeof(smb_ucs2_t);
468
 
 
469
 
        if ((password = strdup_upper(opt_password)) == NULL) {
470
 
                DEBUG(0, ("strdup_upper failed!\n"));
471
 
                exit(1);
472
 
        }
473
 
 
474
 
        if ((convert_string_allocate(NULL, CH_UNIX, 
475
 
                                     CH_DOS, password,
476
 
                                     strlen(password)+1, 
477
 
                                     &lm_response.data,True)) == -1) {
478
 
                DEBUG(0, ("convert_string_allocate failed!\n"));
479
 
                exit(1);
480
 
        }
481
 
 
482
 
        SAFE_FREE(password);
483
 
 
484
 
        lm_response.length = strlen((const char *)lm_response.data);
485
 
 
486
 
        switch (break_which) {
487
 
        case BREAK_NONE:
488
 
                break;
489
 
        case BREAK_LM:
490
 
                lm_response.data[0]++;
491
 
                break;
492
 
        case BREAK_NT:
493
 
                nt_response.data[0]++;
494
 
                break;
495
 
        case NO_LM:
496
 
                SAFE_FREE(lm_response.data);
497
 
                lm_response.length = 0;
498
 
                break;
499
 
        case NO_NT:
500
 
                SAFE_FREE(nt_response.data);
501
 
                nt_response.length = 0;
502
 
                break;
503
 
        }
504
 
 
505
 
        nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
506
 
                                              opt_workstation,
507
 
                                              &chall,
508
 
                                              &lm_response,
509
 
                                              &nt_response,
510
 
                                              flags,
511
 
                                              lm_key,
512
 
                                              user_session_key,
513
 
                                              &error_string, NULL);
514
 
        
515
 
        SAFE_FREE(nt_response.data);
516
 
        SAFE_FREE(lm_response.data);
517
 
        data_blob_free(&chall);
518
 
 
519
 
        if (!NT_STATUS_IS_OK(nt_status)) {
520
 
                d_printf("%s (0x%x)\n", 
521
 
                         error_string,
522
 
                         NT_STATUS_V(nt_status));
523
 
                SAFE_FREE(error_string);
524
 
                return break_which == BREAK_NT;
525
 
        }
526
 
 
527
 
        return break_which != BREAK_NT;
528
 
}
529
 
 
530
 
static BOOL test_plaintext_none_broken(void) {
531
 
        return test_plaintext(BREAK_NONE);
532
 
}
533
 
 
534
 
static BOOL test_plaintext_lm_broken(void) {
535
 
        return test_plaintext(BREAK_LM);
536
 
}
537
 
 
538
 
static BOOL test_plaintext_nt_broken(void) {
539
 
        return test_plaintext(BREAK_NT);
540
 
}
541
 
 
542
 
static BOOL test_plaintext_nt_only(void) {
543
 
        return test_plaintext(NO_LM);
544
 
}
545
 
 
546
 
static BOOL test_plaintext_lm_only(void) {
547
 
        return test_plaintext(NO_NT);
548
 
}
549
 
 
550
 
/* 
551
 
   Tests:
552
 
   
553
 
   - LM only
554
 
   - NT and LM             
555
 
   - NT
556
 
   - NT in LM field
557
 
   - NT in both fields
558
 
   - NTLMv2
559
 
   - NTLMv2 and LMv2
560
 
   - LMv2
561
 
   - plaintext tests (in challenge-response feilds)
562
 
  
563
 
   check we get the correct session key in each case
564
 
   check what values we get for the LM session key
565
 
   
566
 
*/
567
 
 
568
 
static const struct ntlm_tests {
569
 
        BOOL (*fn)(void);
570
 
        const char *name;
571
 
} test_table[] = {
572
 
        {test_lm, "LM"},
573
 
        {test_lm_ntlm, "LM and NTLM"},
574
 
        {test_ntlm, "NTLM"},
575
 
        {test_ntlm_in_lm, "NTLM in LM"},
576
 
        {test_ntlm_in_both, "NTLM in both"},
577
 
        {test_ntlmv2, "NTLMv2"},
578
 
        {test_lmv2_ntlmv2, "NTLMv2 and LMv2"},
579
 
        {test_lmv2, "LMv2"},
580
 
        {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken"},
581
 
        {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken"},
582
 
        {test_ntlm_lm_broken, "NTLM and LM, LM broken"},
583
 
        {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken"},
584
 
        {test_plaintext_none_broken, "Plaintext"},
585
 
        {test_plaintext_lm_broken, "Plaintext LM broken"},
586
 
        {test_plaintext_nt_broken, "Plaintext NT broken"},
587
 
        {test_plaintext_nt_only, "Plaintext NT only"},
588
 
        {test_plaintext_lm_only, "Plaintext LM only"},
589
 
        {NULL, NULL}
590
 
};
591
 
 
592
 
BOOL diagnose_ntlm_auth(void)
593
 
{
594
 
        unsigned int i;
595
 
        BOOL pass = True;
596
 
 
597
 
        for (i=0; test_table[i].fn; i++) {
598
 
                if (!test_table[i].fn()) {
599
 
                        DEBUG(1, ("Test %s failed!\n", test_table[i].name));
600
 
                        pass = False;
601
 
                }
602
 
        }
603
 
 
604
 
        return pass;
605
 
}
606