~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/lib/krb5/keytab/t_keytab.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lib/krb5/keytab/t_keytab.c
 
3
 *
 
4
 * Copyright (C) 2007 by the Massachusetts Institute of Technology.
 
5
 * All rights reserved.
 
6
 *
 
7
 * Export of this software from the United States of America may
 
8
 *   require a specific license from the United States Government.
 
9
 *   It is the responsibility of any person or organization contemplating
 
10
 *   export to obtain such a license before exporting.
 
11
 * 
 
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 
13
 * distribute this software and its documentation for any purpose and
 
14
 * without fee is hereby granted, provided that the above copyright
 
15
 * notice appear in all copies and that both that copyright notice and
 
16
 * this permission notice appear in supporting documentation, and that
 
17
 * the name of M.I.T. not be used in advertising or publicity pertaining
 
18
 * to distribution of the software without specific, written prior
 
19
 * permission.  Furthermore if you modify this software you must label
 
20
 * your software as modified software and not distribute it in such a
 
21
 * fashion that it might be confused with the original M.I.T. software.
 
22
 * M.I.T. makes no representations about the suitability of
 
23
 * this software for any purpose.  It is provided "as is" without express
 
24
 * or implied warranty.
 
25
 * 
 
26
 * 
 
27
 *
 
28
 * A set of tests for the keytab interface
 
29
 */
 
30
 
 
31
 
 
32
#include "k5-int.h"
 
33
#include "autoconf.h"
 
34
#include <stdio.h>
 
35
#include <errno.h>
 
36
#if HAVE_UNISTD_H
 
37
#include <unistd.h>
 
38
#endif
 
39
#include <string.h>
 
40
 
 
41
 
 
42
int debug=0;
 
43
 
 
44
extern const krb5_kt_ops krb5_ktf_writable_ops;
 
45
 
 
46
#define KRB5_OK 0
 
47
 
 
48
#define CHECK(kret,msg) \
 
49
     if (kret != KRB5_OK) {\
 
50
          com_err(msg, kret, ""); \
 
51
          fflush(stderr);\
 
52
          exit(1);\
 
53
     } else if(debug) printf("%s went ok\n", msg);
 
54
 
 
55
 
 
56
#define CHECK_STR(str,msg) \
 
57
     if (str == 0) {\
 
58
          com_err(msg, kret, "");\
 
59
          exit(1);\
 
60
     } else if(debug) printf("%s went ok\n", msg);
 
61
 
 
62
static void test_misc(krb5_context context)
 
63
{
 
64
  /* Tests for certain error returns */
 
65
  krb5_error_code       kret;
 
66
  krb5_keytab ktid;
 
67
  char defname[BUFSIZ];
 
68
  char *name;
 
69
 
 
70
  fprintf(stderr, "Testing miscellaneous error conditions\n");
 
71
 
 
72
  kret = krb5_kt_resolve(context, "unknown_method_ep:/tmp/name", &ktid);
 
73
  if (kret != KRB5_KT_UNKNOWN_TYPE) {
 
74
    CHECK(kret, "resolve unknown type");
 
75
  }
 
76
 
 
77
  /* Test length limits on krb5_kt_default_name */
 
78
  kret = krb5_kt_default_name(context, defname, sizeof(defname));
 
79
  CHECK(kret, "krb5_kt_default_name error");
 
80
 
 
81
  /* Now allocate space - without the null... */
 
82
  name = malloc(strlen(defname));
 
83
  if(!name) {
 
84
          fprintf(stderr, "Out of memory in testing\n");
 
85
          exit(1);
 
86
  }
 
87
  kret = krb5_kt_default_name(context, name, strlen(defname));
 
88
  free(name);
 
89
  if (kret != KRB5_CONFIG_NOTENUFSPACE) {
 
90
          CHECK(kret, "krb5_kt_default_name limited");
 
91
  }
 
92
}
 
93
 
 
94
static void kt_test(krb5_context context, const char *name)
 
95
{
 
96
     krb5_error_code kret;
 
97
     krb5_keytab kt;
 
98
     const char *type;
 
99
     char buf[BUFSIZ];
 
100
     char *p;
 
101
     krb5_keytab_entry kent, kent2;
 
102
     krb5_principal princ;
 
103
     krb5_kt_cursor cursor, cursor2;
 
104
     int cnt;
 
105
 
 
106
     kret = krb5_kt_resolve(context, name, &kt);
 
107
     CHECK(kret, "resolve");
 
108
 
 
109
     type = krb5_kt_get_type(context, kt);
 
110
     CHECK_STR(type, "getting kt type");
 
111
     printf("  Type is: %s\n", type);
 
112
 
 
113
     kret = krb5_kt_get_name(context, kt, buf, sizeof(buf));
 
114
     CHECK(kret, "get_name");
 
115
     printf("  Name is: %s\n", buf);
 
116
 
 
117
     /* Check that length checks fail */
 
118
     /* The buffer is allocated too small - to allow for valgrind test of
 
119
        overflows
 
120
     */
 
121
     p = malloc(strlen(buf));
 
122
     kret = krb5_kt_get_name(context, kt, p, 1);
 
123
     if(kret != KRB5_KT_NAME_TOOLONG) {
 
124
             CHECK(kret, "get_name - size 1");
 
125
     }
 
126
 
 
127
 
 
128
     kret = krb5_kt_get_name(context, kt, p, strlen(buf));
 
129
     if(kret != KRB5_KT_NAME_TOOLONG) {
 
130
             CHECK(kret, "get_name");
 
131
     }
 
132
     free(p);
 
133
 
 
134
     /* Try to lookup unknown principal - when keytab does not exist*/
 
135
     kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ);
 
136
     CHECK(kret, "parsing principal");
 
137
 
 
138
     
 
139
     kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent);
 
140
     if((kret != KRB5_KT_NOTFOUND) && (kret != ENOENT)) {
 
141
             CHECK(kret, "Getting non-existant entry");
 
142
     }
 
143
 
 
144
 
 
145
     /* ===================   Add entries to keytab ================= */
 
146
     /*
 
147
      * Add the following for this principal
 
148
      * enctype 1, kvno 1, key = "1"
 
149
      * enctype 2, kvno 1, key = "1"
 
150
      * enctype 1, kvno 2, key = "2"
 
151
      */
 
152
     memset(&kent, 0, sizeof(kent));
 
153
     kent.magic = KV5M_KEYTAB_ENTRY;
 
154
     kent.principal = princ;
 
155
     kent.timestamp = 327689;
 
156
     kent.vno = 1;
 
157
     kent.key.magic = KV5M_KEYBLOCK;
 
158
     kent.key.enctype = 1;
 
159
     kent.key.length = 1;
 
160
     kent.key.contents = (krb5_octet *) "1";
 
161
 
 
162
 
 
163
     kret = krb5_kt_add_entry(context, kt, &kent);
 
164
     CHECK(kret, "Adding initial entry");
 
165
 
 
166
     kent.key.enctype = 2;
 
167
     kret = krb5_kt_add_entry(context, kt, &kent);
 
168
     CHECK(kret, "Adding second entry");
 
169
 
 
170
     kent.key.enctype = 1;
 
171
     kent.vno = 2;
 
172
     kent.key.contents = (krb5_octet *) "2";
 
173
     kret = krb5_kt_add_entry(context, kt, &kent);
 
174
     CHECK(kret, "Adding third entry");
 
175
     
 
176
     /* Free memory */
 
177
     krb5_free_principal(context, princ);
 
178
 
 
179
     /* ==============   Test iterating over contents of keytab ========= */
 
180
 
 
181
     kret = krb5_kt_start_seq_get(context, kt, &cursor);
 
182
     CHECK(kret, "Start sequence get");
 
183
 
 
184
 
 
185
     memset(&kent, 0, sizeof(kent));
 
186
     cnt = 0;
 
187
     while((kret = krb5_kt_next_entry(context, kt, &kent, &cursor)) == 0) {
 
188
             if(((kent.vno != 1) && (kent.vno != 2)) || 
 
189
                ((kent.key.enctype != 1) && (kent.key.enctype != 2)) || 
 
190
                (kent.key.length != 1) ||
 
191
                (kent.key.contents[0] != kent.vno +'0')) {
 
192
                     fprintf(stderr, "Error in read contents\n");
 
193
                     exit(1);
 
194
             }
 
195
 
 
196
             if((kent.magic != KV5M_KEYTAB_ENTRY) || 
 
197
                (kent.key.magic != KV5M_KEYBLOCK)) {
 
198
                     fprintf(stderr, "Magic number in sequence not proper\n");
 
199
                     exit(1);
 
200
             }
 
201
 
 
202
             cnt++;
 
203
             krb5_free_keytab_entry_contents(context, &kent);
 
204
     }
 
205
     if (kret != KRB5_KT_END) {
 
206
             CHECK(kret, "getting next entry");
 
207
     }
 
208
 
 
209
     if(cnt != 3) {
 
210
             fprintf(stderr, "Mismatch in number of entries in keytab");
 
211
     }
 
212
 
 
213
     kret = krb5_kt_end_seq_get(context, kt, &cursor);
 
214
     CHECK(kret, "End sequence get");
 
215
 
 
216
 
 
217
     /* ==========================   get_entry tests ============== */
 
218
 
 
219
     /* Try to lookup unknown principal  - now that keytab exists*/
 
220
     kret = krb5_parse_name(context, "test3/test2@TEST.MIT.EDU", &princ);
 
221
     CHECK(kret, "parsing principal");
 
222
 
 
223
     
 
224
     kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent);
 
225
     if((kret != KRB5_KT_NOTFOUND)) {
 
226
             CHECK(kret, "Getting non-existant entry");
 
227
     }
 
228
 
 
229
     krb5_free_principal(context, princ);
 
230
 
 
231
     /* Try to lookup known principal */
 
232
     kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ);
 
233
     CHECK(kret, "parsing principal");
 
234
 
 
235
     kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent);
 
236
     CHECK(kret, "looking up principal");
 
237
 
 
238
     /* Ensure a valid answer  - we did not specify an enctype or kvno */
 
239
     if (!krb5_principal_compare(context, princ, kent.principal) ||
 
240
         ((kent.vno != 1) && (kent.vno != 2)) ||
 
241
         ((kent.key.enctype != 1) && (kent.key.enctype != 2)) || 
 
242
         (kent.key.length != 1) ||
 
243
         (kent.key.contents[0] != kent.vno +'0')) {
 
244
             fprintf(stderr, "Retrieved principal does not check\n");
 
245
             exit(1);
 
246
     }
 
247
 
 
248
     krb5_free_keytab_entry_contents(context, &kent);
 
249
 
 
250
     /* Try to lookup a specific enctype - but unspecified kvno - should give
 
251
      * max kvno 
 
252
      */
 
253
     kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent);
 
254
     CHECK(kret, "looking up principal");
 
255
 
 
256
     /* Ensure a valid answer  - we did specified an enctype */
 
257
     if (!krb5_principal_compare(context, princ, kent.principal) ||
 
258
         (kent.vno != 2) || (kent.key.enctype != 1) ||
 
259
         (kent.key.length != 1) ||
 
260
         (kent.key.contents[0] != kent.vno +'0')) {
 
261
             fprintf(stderr, "Retrieved principal does not check\n");
 
262
 
 
263
             exit(1);
 
264
 
 
265
     }
 
266
 
 
267
     krb5_free_keytab_entry_contents(context, &kent);
 
268
 
 
269
     /* Try to lookup unspecified enctype, but a specified kvno */
 
270
 
 
271
     kret = krb5_kt_get_entry(context, kt, princ, 2, 0, &kent);
 
272
     CHECK(kret, "looking up principal");
 
273
 
 
274
     /* Ensure a valid answer  - we did not specify a kvno */
 
275
     if (!krb5_principal_compare(context, princ, kent.principal) ||
 
276
         (kent.vno != 2) || (kent.key.enctype != 1) ||
 
277
         (kent.key.length != 1) ||
 
278
         (kent.key.contents[0] != kent.vno +'0')) {
 
279
             fprintf(stderr, "Retrieved principal does not check\n");
 
280
 
 
281
             exit(1);
 
282
 
 
283
     }
 
284
 
 
285
     krb5_free_keytab_entry_contents(context, &kent);
 
286
 
 
287
 
 
288
 
 
289
     /* Try to lookup specified enctype and kvno */
 
290
 
 
291
     kret = krb5_kt_get_entry(context, kt, princ, 1, 1, &kent);
 
292
     CHECK(kret, "looking up principal");
 
293
 
 
294
     if (!krb5_principal_compare(context, princ, kent.principal) ||
 
295
         (kent.vno != 1) || (kent.key.enctype != 1) ||
 
296
         (kent.key.length != 1) ||
 
297
         (kent.key.contents[0] != kent.vno +'0')) {
 
298
             fprintf(stderr, "Retrieved principal does not check\n");
 
299
 
 
300
             exit(1);
 
301
 
 
302
     }
 
303
 
 
304
     krb5_free_keytab_entry_contents(context, &kent);
 
305
 
 
306
 
 
307
     /* Try lookup with active iterators.  */
 
308
     kret = krb5_kt_start_seq_get(context, kt, &cursor);
 
309
     CHECK(kret, "Start sequence get(2)");
 
310
     kret = krb5_kt_start_seq_get(context, kt, &cursor2);
 
311
     CHECK(kret, "Start sequence get(3)");
 
312
     kret = krb5_kt_next_entry(context, kt, &kent, &cursor);
 
313
     CHECK(kret, "getting next entry(2)");
 
314
     krb5_free_keytab_entry_contents(context, &kent);
 
315
     kret = krb5_kt_next_entry(context, kt, &kent, &cursor);
 
316
     CHECK(kret, "getting next entry(3)");
 
317
     kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2);
 
318
     CHECK(kret, "getting next entry(4)");
 
319
     krb5_free_keytab_entry_contents(context, &kent2);
 
320
     kret = krb5_kt_get_entry(context, kt, kent.principal, 0, 0, &kent2);
 
321
     CHECK(kret, "looking up principal(2)");
 
322
     krb5_free_keytab_entry_contents(context, &kent2);
 
323
     kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2);
 
324
     CHECK(kret, "getting next entry(5)");
 
325
     if (!krb5_principal_compare(context, kent.principal, kent2.principal)) {
 
326
         fprintf(stderr, "iterators not in sync\n");
 
327
         exit(1);
 
328
     }
 
329
     krb5_free_keytab_entry_contents(context, &kent);
 
330
     krb5_free_keytab_entry_contents(context, &kent2);
 
331
     kret = krb5_kt_next_entry(context, kt, &kent, &cursor);
 
332
     CHECK(kret, "getting next entry(6)");
 
333
     kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2);
 
334
     CHECK(kret, "getting next entry(7)");
 
335
     krb5_free_keytab_entry_contents(context, &kent);
 
336
     krb5_free_keytab_entry_contents(context, &kent2);
 
337
     kret = krb5_kt_end_seq_get(context, kt, &cursor);
 
338
     CHECK(kret, "ending sequence get(1)");
 
339
     kret = krb5_kt_end_seq_get(context, kt, &cursor2);
 
340
     CHECK(kret, "ending sequence get(2)");
 
341
 
 
342
     /* Try to lookup specified enctype and kvno  - that does not exist*/
 
343
 
 
344
     kret = krb5_kt_get_entry(context, kt, princ, 3, 1, &kent);
 
345
     if(kret != KRB5_KT_KVNONOTFOUND) {
 
346
             CHECK(kret, "looking up specific principal, kvno, enctype");
 
347
     }
 
348
 
 
349
     krb5_free_principal(context, princ);
 
350
 
 
351
 
 
352
     /* =========================   krb5_kt_remove_entry =========== */
 
353
     /* Lookup the keytab entry w/ 2 kvno - and delete version 2 - 
 
354
        ensure gone */
 
355
     kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ);
 
356
     CHECK(kret, "parsing principal");
 
357
 
 
358
     kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent);
 
359
     CHECK(kret, "looking up principal");
 
360
 
 
361
     /* Ensure a valid answer  - we are looking for max(kvno) and enc=1 */
 
362
     if (!krb5_principal_compare(context, princ, kent.principal) ||
 
363
         (kent.vno != 2) || (kent.key.enctype != 1) ||
 
364
         (kent.key.length != 1) ||
 
365
         (kent.key.contents[0] != kent.vno +'0')) {
 
366
             fprintf(stderr, "Retrieved principal does not check\n");
 
367
 
 
368
             exit(1);
 
369
 
 
370
     }
 
371
 
 
372
     /* Delete it */
 
373
     kret = krb5_kt_remove_entry(context, kt, &kent);
 
374
     CHECK(kret, "Removing entry");
 
375
 
 
376
     krb5_free_keytab_entry_contents(context, &kent);
 
377
     /* And ensure gone */
 
378
 
 
379
     kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent);
 
380
     CHECK(kret, "looking up principal");
 
381
 
 
382
     /* Ensure a valid answer - kvno should now be 1 - we deleted 2 */
 
383
     if (!krb5_principal_compare(context, princ, kent.principal) ||
 
384
         (kent.vno != 1) || (kent.key.enctype != 1) ||
 
385
         (kent.key.length != 1) ||
 
386
         (kent.key.contents[0] != kent.vno +'0')) {
 
387
             fprintf(stderr, "Delete principal check failed\n");
 
388
 
 
389
             exit(1);
 
390
 
 
391
     }
 
392
     krb5_free_keytab_entry_contents(context, &kent);
 
393
 
 
394
     krb5_free_principal(context, princ);
 
395
     
 
396
     /* =======================  Finally close =======================  */
 
397
 
 
398
     kret = krb5_kt_close(context, kt);
 
399
     CHECK(kret, "close");
 
400
 
 
401
}
 
402
 
 
403
static void do_test(krb5_context context, const char *prefix, 
 
404
                    krb5_boolean delete)
 
405
{
 
406
  char *name, *filename;
 
407
 
 
408
  if (asprintf(&filename, "/tmp/kttest.%ld", (long) getpid()) < 0) {
 
409
      perror("asprintf");
 
410
      exit(1);
 
411
  }
 
412
  if (asprintf(&name, "%s%s", prefix, filename) < 0) {
 
413
      perror("asprintf");
 
414
      exit(1);
 
415
  }
 
416
  printf("Starting test on %s\n", name);
 
417
  kt_test(context, name);
 
418
  printf("Test on %s passed\n", name);
 
419
  if(delete)
 
420
          unlink(filename);
 
421
  free(filename);
 
422
  free(name);
 
423
 
 
424
}
 
425
 
 
426
int 
 
427
main (void)
 
428
{
 
429
        krb5_context context;
 
430
        krb5_error_code kret;
 
431
 
 
432
 
 
433
        if ((kret = krb5_init_context(&context))) {
 
434
                printf("Couldn't initialize krb5 library: %s\n",
 
435
                       error_message(kret));
 
436
                exit(1);
 
437
        }
 
438
 
 
439
        /* All keytab types are registered by default -- test for 
 
440
           redundant error */
 
441
        kret = krb5_kt_register(context, &krb5_ktf_writable_ops);
 
442
        if(kret && kret != KRB5_KT_TYPE_EXISTS) {
 
443
                CHECK(kret, "register ktf_writable");
 
444
        }
 
445
 
 
446
        test_misc(context);
 
447
        do_test(context, "WRFILE:", FALSE);
 
448
        do_test(context, "MEMORY:", TRUE);
 
449
 
 
450
        krb5_free_context(context);
 
451
        return 0;
 
452
 
 
453
}
 
454
 
 
455
 
 
456
#if 0
 
457
/* remove and add are functions, so that they can return NOWRITE
 
458
   if not a writable keytab */
 
459
krb5_error_code KRB5_CALLCONV krb5_kt_remove_entry
 
460
        (krb5_context,
 
461
                krb5_keytab,
 
462
                krb5_keytab_entry * );
 
463
 
 
464
 
 
465
 
 
466
#endif