2
* lib/krb5/keytab/t_keytab.c
4
* Copyright (C) 2007 by the Massachusetts Institute of Technology.
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.
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.
28
* A set of tests for the keytab interface
44
extern const krb5_kt_ops krb5_ktf_writable_ops;
48
#define CHECK(kret,msg) \
49
if (kret != KRB5_OK) {\
50
com_err(msg, kret, ""); \
53
} else if(debug) printf("%s went ok\n", msg);
56
#define CHECK_STR(str,msg) \
58
com_err(msg, kret, "");\
60
} else if(debug) printf("%s went ok\n", msg);
62
static void test_misc(krb5_context context)
64
/* Tests for certain error returns */
70
fprintf(stderr, "Testing miscellaneous error conditions\n");
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");
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");
81
/* Now allocate space - without the null... */
82
name = malloc(strlen(defname));
84
fprintf(stderr, "Out of memory in testing\n");
87
kret = krb5_kt_default_name(context, name, strlen(defname));
89
if (kret != KRB5_CONFIG_NOTENUFSPACE) {
90
CHECK(kret, "krb5_kt_default_name limited");
94
static void kt_test(krb5_context context, const char *name)
101
krb5_keytab_entry kent, kent2;
102
krb5_principal princ;
103
krb5_kt_cursor cursor, cursor2;
106
kret = krb5_kt_resolve(context, name, &kt);
107
CHECK(kret, "resolve");
109
type = krb5_kt_get_type(context, kt);
110
CHECK_STR(type, "getting kt type");
111
printf(" Type is: %s\n", type);
113
kret = krb5_kt_get_name(context, kt, buf, sizeof(buf));
114
CHECK(kret, "get_name");
115
printf(" Name is: %s\n", buf);
117
/* Check that length checks fail */
118
/* The buffer is allocated too small - to allow for valgrind test of
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");
128
kret = krb5_kt_get_name(context, kt, p, strlen(buf));
129
if(kret != KRB5_KT_NAME_TOOLONG) {
130
CHECK(kret, "get_name");
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");
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");
145
/* =================== Add entries to keytab ================= */
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"
152
memset(&kent, 0, sizeof(kent));
153
kent.magic = KV5M_KEYTAB_ENTRY;
154
kent.principal = princ;
155
kent.timestamp = 327689;
157
kent.key.magic = KV5M_KEYBLOCK;
158
kent.key.enctype = 1;
160
kent.key.contents = (krb5_octet *) "1";
163
kret = krb5_kt_add_entry(context, kt, &kent);
164
CHECK(kret, "Adding initial entry");
166
kent.key.enctype = 2;
167
kret = krb5_kt_add_entry(context, kt, &kent);
168
CHECK(kret, "Adding second entry");
170
kent.key.enctype = 1;
172
kent.key.contents = (krb5_octet *) "2";
173
kret = krb5_kt_add_entry(context, kt, &kent);
174
CHECK(kret, "Adding third entry");
177
krb5_free_principal(context, princ);
179
/* ============== Test iterating over contents of keytab ========= */
181
kret = krb5_kt_start_seq_get(context, kt, &cursor);
182
CHECK(kret, "Start sequence get");
185
memset(&kent, 0, sizeof(kent));
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");
196
if((kent.magic != KV5M_KEYTAB_ENTRY) ||
197
(kent.key.magic != KV5M_KEYBLOCK)) {
198
fprintf(stderr, "Magic number in sequence not proper\n");
203
krb5_free_keytab_entry_contents(context, &kent);
205
if (kret != KRB5_KT_END) {
206
CHECK(kret, "getting next entry");
210
fprintf(stderr, "Mismatch in number of entries in keytab");
213
kret = krb5_kt_end_seq_get(context, kt, &cursor);
214
CHECK(kret, "End sequence get");
217
/* ========================== get_entry tests ============== */
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");
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");
229
krb5_free_principal(context, princ);
231
/* Try to lookup known principal */
232
kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ);
233
CHECK(kret, "parsing principal");
235
kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent);
236
CHECK(kret, "looking up principal");
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");
248
krb5_free_keytab_entry_contents(context, &kent);
250
/* Try to lookup a specific enctype - but unspecified kvno - should give
253
kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent);
254
CHECK(kret, "looking up principal");
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");
267
krb5_free_keytab_entry_contents(context, &kent);
269
/* Try to lookup unspecified enctype, but a specified kvno */
271
kret = krb5_kt_get_entry(context, kt, princ, 2, 0, &kent);
272
CHECK(kret, "looking up principal");
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");
285
krb5_free_keytab_entry_contents(context, &kent);
289
/* Try to lookup specified enctype and kvno */
291
kret = krb5_kt_get_entry(context, kt, princ, 1, 1, &kent);
292
CHECK(kret, "looking up principal");
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");
304
krb5_free_keytab_entry_contents(context, &kent);
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");
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)");
342
/* Try to lookup specified enctype and kvno - that does not exist*/
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");
349
krb5_free_principal(context, princ);
352
/* ========================= krb5_kt_remove_entry =========== */
353
/* Lookup the keytab entry w/ 2 kvno - and delete version 2 -
355
kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ);
356
CHECK(kret, "parsing principal");
358
kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent);
359
CHECK(kret, "looking up principal");
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");
373
kret = krb5_kt_remove_entry(context, kt, &kent);
374
CHECK(kret, "Removing entry");
376
krb5_free_keytab_entry_contents(context, &kent);
377
/* And ensure gone */
379
kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent);
380
CHECK(kret, "looking up principal");
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");
392
krb5_free_keytab_entry_contents(context, &kent);
394
krb5_free_principal(context, princ);
396
/* ======================= Finally close ======================= */
398
kret = krb5_kt_close(context, kt);
399
CHECK(kret, "close");
403
static void do_test(krb5_context context, const char *prefix,
406
char *name, *filename;
408
if (asprintf(&filename, "/tmp/kttest.%ld", (long) getpid()) < 0) {
412
if (asprintf(&name, "%s%s", prefix, filename) < 0) {
416
printf("Starting test on %s\n", name);
417
kt_test(context, name);
418
printf("Test on %s passed\n", name);
429
krb5_context context;
430
krb5_error_code kret;
433
if ((kret = krb5_init_context(&context))) {
434
printf("Couldn't initialize krb5 library: %s\n",
435
error_message(kret));
439
/* All keytab types are registered by default -- test for
441
kret = krb5_kt_register(context, &krb5_ktf_writable_ops);
442
if(kret && kret != KRB5_KT_TYPE_EXISTS) {
443
CHECK(kret, "register ktf_writable");
447
do_test(context, "WRFILE:", FALSE);
448
do_test(context, "MEMORY:", TRUE);
450
krb5_free_context(context);
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
462
krb5_keytab_entry * );