From: Ezra Peisach Date: Sun, 4 Feb 2007 03:08:47 +0000 (+0000) Subject: Add a new program to perform various tests on the WRFILE: and MEMORY: keytabs X-Git-Tag: krb5-1.7-alpha1~1294 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ed446c3772b5f626e55fa38d302dc9c628db5a08;p=krb5.git Add a new program to perform various tests on the WRFILE: and MEMORY: keytabs I developed this program to test functionality of the MEMORY keytab - which resulted in the numerous fixes that have been committed recently. Tests all functioanlity of keytabs except for krb5_kt_default() and krb5_kt_read_service_key() - although essential functionality tested. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19142 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/krb5/keytab/Makefile.in b/src/lib/krb5/keytab/Makefile.in index 806719053..0a375c954 100644 --- a/src/lib/krb5/keytab/Makefile.in +++ b/src/lib/krb5/keytab/Makefile.in @@ -4,6 +4,10 @@ mydir=lib/krb5/keytab BUILDTOP=$(REL)..$(S)..$(S).. DEFS= +RUN_SETUP = @KRB5_RUN_ENV@ +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + ##DOS##BUILDTOP = ..\..\.. ##DOS##PREFIXDIR=keytab ##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst @@ -44,6 +48,9 @@ SRCS= \ $(srcdir)/kt_srvtab.c \ $(srcdir)/read_servi.c +EXTRADEPSRCS= \ + $(srcdir)/t_keytab.c + all-windows:: $(OBJFILE) ##DOS$(OBJFILE): $(OBJS) @@ -53,6 +60,17 @@ all-windows:: $(OBJFILE) all-unix:: all-libobjs clean-unix:: clean-libobjs +check-unix:: t_keytab + KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\ + $(RUN_SETUP) $(VALGRIND) ./t_keytab + +T_KEYTAB_OBJS = t_keytab.o +t_keytab: $(T_KEYTAB_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_KEYTAB_OBJS) $(KRB5_BASE_LIBS) + +clean-unix:: + $(RM) t_keytab t_keytab.o + clean-windows:: @echo Making clean in krb5\keytab $(RM) $(OBJFILE) @@ -124,14 +142,15 @@ kt_file.so kt_file.po $(OUTPRE)kt_file.$(OBJEXT): $(BUILDTOP)/include/autoconf.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ $(SRCTOP)/include/socket-utils.h kt_file.c -kt_memory.so kt_memory.po $(OUTPRE)kt_memory.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ - $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ - $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \ - $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ - $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ - $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ - $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ - $(SRCTOP)/include/socket-utils.h kt_memory.c +kt_memory.so kt_memory.po $(OUTPRE)kt_memory.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + kt_memory.c kt_srvtab.so kt_srvtab.po $(OUTPRE)kt_srvtab.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ @@ -150,3 +169,12 @@ read_servi.so read_servi.po $(OUTPRE)read_servi.$(OBJEXT): \ $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ read_servi.c +t_keytab.so t_keytab.po $(OUTPRE)t_keytab.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + t_keytab.c diff --git a/src/lib/krb5/keytab/t_keytab.c b/src/lib/krb5/keytab/t_keytab.c new file mode 100644 index 000000000..63e4689d8 --- /dev/null +++ b/src/lib/krb5/keytab/t_keytab.c @@ -0,0 +1,425 @@ +/* + * lib/krb5/keytab/t_keytab.c + * + * Copyright (C) 2007 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * + * A set of tests for the keytab interface + */ + + +#include "k5-int.h" +#include "autoconf.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include + + +int debug=0; + +extern const krb5_kt_ops krb5_ktf_writable_ops; + +#define KRB5_OK 0 + +#define CHECK(kret,msg) \ + if (kret != KRB5_OK) {\ + com_err(msg, kret, ""); \ + fflush(stderr);\ + exit(1);\ + } else if(debug) printf("%s went ok\n", msg); + + +#define CHECK_STR(str,msg) \ + if (str == 0) {\ + com_err(msg, kret, "");\ + exit(1);\ + } else if(debug) printf("%s went ok\n", msg); + +static void test_misc(krb5_context context) +{ + /* Tests for certain error returns */ + krb5_error_code kret; + krb5_keytab ktid; + char defname[BUFSIZ]; + char *name; + + fprintf(stderr, "Testing miscellaneous error conditions\n"); + + kret = krb5_kt_resolve(context, "unknown_method_ep:/tmp/name", &ktid); + if (kret != KRB5_KT_UNKNOWN_TYPE) { + CHECK(kret, "resolve unknown type"); + } + + /* Test length limits on krb5_kt_default_name */ + kret = krb5_kt_default_name(context, defname, sizeof(defname)); + CHECK(kret, "krb5_kt_default_name error"); + + /* Now allocate space - without the null... */ + name = malloc(strlen(defname)); + if(!name) { + fprintf(stderr, "Out of memory in testing\n"); + exit(1); + } + kret = krb5_kt_default_name(context, name, strlen(defname)); + free(name); + if (kret != KRB5_CONFIG_NOTENUFSPACE) { + CHECK(kret, "krb5_kt_default_name limited"); + } +} + +static void kt_test(krb5_context context, const char *name) +{ + krb5_error_code kret; + krb5_keytab kt; + char *type; + char buf[BUFSIZ]; + char *p; + krb5_keytab_entry kent; + krb5_principal princ; + krb5_kt_cursor cursor; + int cnt; + + kret = krb5_kt_resolve(context, name, &kt); + CHECK(kret, "resolve"); + + type = krb5_kt_get_type(context, kt); + CHECK_STR(type, "getting kt type"); + printf(" Type is: %s\n", type); + + kret = krb5_kt_get_name(context, kt, buf, sizeof(buf)); + CHECK(kret, "get_name"); + printf(" Name is: %s\n", buf); + + /* Check that length checks fail */ + /* The buffer is allocated too small - to allow for valgrind test of + overflows + */ + p = malloc(strlen(buf)); + kret = krb5_kt_get_name(context, kt, p, 1); + if(kret != KRB5_KT_NAME_TOOLONG) { + CHECK(kret, "get_name - size 1"); + } + + + kret = krb5_kt_get_name(context, kt, p, strlen(buf)); + if(kret != KRB5_KT_NAME_TOOLONG) { + CHECK(kret, "get_name"); + } + free(p); + + /* Try to lookup unknown principal - when keytab does not exist*/ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + if((kret != KRB5_KT_NOTFOUND) && (kret != ENOENT)) { + CHECK(kret, "Getting non-existant entry"); + } + + + /* =================== Add entries to keytab ================= */ + /* + * Add the following for this principal + * enctype 1, kvno 1, key = "1" + * enctype 2, kvno 1, key = "1" + * enctype 1, kvno 2, key = "2" + */ + memset(&kent, 0, sizeof(kent)); + kent.magic = KV5M_KEYTAB_ENTRY; + kent.principal = princ; + kent.timestamp = 327689; + kent.vno = 1; + kent.key.magic = KV5M_KEYBLOCK; + kent.key.enctype = 1; + kent.key.length = 1; + kent.key.contents = (krb5_octet *) "1"; + + + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding initial entry"); + + kent.key.enctype = 2; + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding second entry"); + + kent.key.enctype = 1; + kent.vno = 2; + kent.key.contents = (krb5_octet *) "2"; + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding third entry"); + + /* Free memory */ + krb5_free_principal(context, princ); + + /* ============== Test iterating over contents of keytab ========= */ + + kret = krb5_kt_start_seq_get(context, kt, &cursor); + CHECK(kret, "Start sequence get"); + + + memset(&kent, 0, sizeof(kent)); + cnt = 0; + while((kret = krb5_kt_next_entry(context, kt, &kent, &cursor)) == 0) { + if(((kent.vno != 1) && (kent.vno != 2)) || + ((kent.key.enctype != 1) && (kent.key.enctype != 2)) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Error in read contents\n"); + exit(1); + } + + if((kent.magic != KV5M_KEYTAB_ENTRY) || + (kent.key.magic != KV5M_KEYBLOCK)) { + fprintf(stderr, "Magic number in sequence not proper\n"); + exit(1); + } + + cnt++; + krb5_free_keytab_entry_contents(context, &kent); + } + if (kret != KRB5_KT_END) { + CHECK(kret, "getting next entry"); + } + + if(cnt != 3) { + fprintf(stderr, "Mismatch in number of entries in keytab"); + } + + kret = krb5_kt_end_seq_get(context, kt, &cursor); + CHECK(kret, "End sequence get"); + + + /* ========================== get_entry tests ============== */ + + /* Try to lookup unknown principal - now that keytab exists*/ + kret = krb5_parse_name(context, "test3/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + if((kret != KRB5_KT_NOTFOUND)) { + CHECK(kret, "Getting non-existant entry"); + } + + krb5_free_principal(context, princ); + + /* Try to lookup known principal */ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did not specify an enctype or kvno */ + if (!krb5_principal_compare(context, princ, kent.principal) || + ((kent.vno != 1) && (kent.vno != 2)) || + ((kent.key.enctype != 1) && (kent.key.enctype != 2)) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + exit(1); + } + + krb5_free_keytab_entry_contents(context, &kent); + + /* Try to lookup a specific enctype - but unspecified kvno - should give + * max kvno + */ + kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did specified an enctype */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + /* Try to lookup unspecified enctype, but a specified kvno */ + + kret = krb5_kt_get_entry(context, kt, princ, 2, 0, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did not specify a kvno */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + + + /* Try to lookup specified enctype and kvno */ + + kret = krb5_kt_get_entry(context, kt, princ, 1, 1, &kent); + CHECK(kret, "looking up principal"); + + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 1) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + + /* Try to lookup specified enctype and kvno - that does not exist*/ + + kret = krb5_kt_get_entry(context, kt, princ, 3, 1, &kent); + if(kret != KRB5_KT_KVNONOTFOUND) { + CHECK(kret, "looking up specific principal, kvno, enctype"); + } + + + + + krb5_free_principal(context, princ); + + /* ========================= krb5_kt_remove_entry =========== */ + /* Lookup the keytab entry w/ 2 kvno - and delete version 2 - + ensure gone */ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we are looking for max(kvno) and enc=1 */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + /* Delete it */ + kret = krb5_kt_remove_entry(context, kt, &kent); + CHECK(kret, "Removing entry"); + + krb5_free_keytab_entry_contents(context, &kent); + /* And ensure gone */ + + kret = krb5_kt_get_entry(context, kt, princ, 0, 1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - kvno should now be 1 - we deleted 2 */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 1) || (kent.key.enctype != 1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Delete principal check failed\n"); + + exit(1); + + } + krb5_free_keytab_entry_contents(context, &kent); + + krb5_free_principal(context, princ); + + /* ======================= Finally close ======================= */ + + kret = krb5_kt_close(context, kt); + CHECK(kret, "close"); + +} + +static void do_test(krb5_context context, const char *prefix, + krb5_boolean delete) +{ + char name[300], filename[300]; + + sprintf(filename, "/tmp/kttest.%ld", (long) getpid()); + sprintf(name, "%s%s", prefix, filename); + printf("Starting test on %s\n", name); + kt_test(context, name); + printf("Test on %s passed\n", name); + if(delete) + unlink(filename); + +} + +int +main (void) +{ + krb5_context context; + krb5_error_code kret; + + + if ((kret = krb5_init_context(&context))) { + printf("Couldn't initialize krb5 library: %s\n", + error_message(kret)); + exit(1); + } + + /* All keytab types are registered by default -- test for + redundant error */ + kret = krb5_kt_register(context, &krb5_ktf_writable_ops); + if(kret && kret != KRB5_KT_TYPE_EXISTS) { + CHECK(kret, "register ktf_writable"); + } + + test_misc(context); + do_test(context, "WRFILE:", FALSE); + do_test(context, "MEMORY:", TRUE); + + krb5_free_context(context); + return 0; + +} + + +#if 0 +/* remove and add are functions, so that they can return NOWRITE + if not a writable keytab */ +krb5_error_code KRB5_CALLCONV krb5_kt_remove_entry + (krb5_context, + krb5_keytab, + krb5_keytab_entry * ); + + + +#endif