diff options
Diffstat (limited to 'src/kadmin/keytab')
| -rw-r--r-- | src/kadmin/keytab/ChangeLog | 13 | ||||
| -rw-r--r-- | src/kadmin/keytab/Makefile.in | 19 | ||||
| -rw-r--r-- | src/kadmin/keytab/Makefile.ov | 30 | ||||
| -rw-r--r-- | src/kadmin/keytab/configure.in | 12 | ||||
| -rw-r--r-- | src/kadmin/keytab/keytab.c | 528 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/ChangeLog | 4 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/Makefile.ov | 21 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/add-princs.tcl | 12 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/config/unix.exp | 46 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/del-princs.tcl | 24 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/helpers.exp | 132 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/keytab.0/ChangeLog | 4 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/keytab.0/adding.exp | 119 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/keytab.0/keytab-spec.exp | 47 | ||||
| -rw-r--r-- | src/kadmin/keytab/unit-test/keytab.0/removing.exp | 125 |
15 files changed, 1136 insertions, 0 deletions
diff --git a/src/kadmin/keytab/ChangeLog b/src/kadmin/keytab/ChangeLog new file mode 100644 index 000000000..5aeb2a44e --- /dev/null +++ b/src/kadmin/keytab/ChangeLog @@ -0,0 +1,13 @@ +Thu Jul 18 20:41:14 1996 Marc Horowitz <marc@mit.edu> + + * keytab.c (etype_string): ifdef'd out reference to des3 + +Mon Jul 15 16:59:35 1996 Marc Horowitz <marc@mit.edu> + + * keytab.c (main): the default keytab name logic was inappropriate + for beta6, since it ignores the env vars, etc. This version still + has the problem that the default keytab probably isn't writeable. + +Wed Jul 10 01:27:44 1996 Marc Horowitz <marc@mit.edu> + + * Makefile.in, configure.in: added autoconf support diff --git a/src/kadmin/keytab/Makefile.in b/src/kadmin/keytab/Makefile.in new file mode 100644 index 000000000..74426a51f --- /dev/null +++ b/src/kadmin/keytab/Makefile.in @@ -0,0 +1,19 @@ +CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE) + +PROG = kadm5_keytab +OBJS = keytab.o + +all:: $(PROG).local $(PROG) + +$(PROG).local: $(OBJS) $(SRVDEPLIBS) + $(CC) $(LDFLAGS) $(LDARGS) -o $(PROG).local $(OBJS) $(SRVLIBS) + +$(PROG): $(OBJS) $(CLNTDEPLIBS) + $(CC) $(LDFLAGS) $(LDARGS) -o $(PROG) $(OBJS) $(CLNTLIBS) + +install:: + $(INSTALL_PROGRAM) $(PROG).local ${DESTDIR}$(ADMIN_BINDIR)/$(PROG) + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG) + +clean:: + $(RM) $(PROG).local $(PROG) $(OBJS) diff --git a/src/kadmin/keytab/Makefile.ov b/src/kadmin/keytab/Makefile.ov new file mode 100644 index 000000000..15cd6d5d9 --- /dev/null +++ b/src/kadmin/keytab/Makefile.ov @@ -0,0 +1,30 @@ +# +# Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. +# +# $Id$ +# $Source$ +# + +TOP = .. +include $(TOP)/config.mk/template + +SRCS = keytab.c +OBJS = keytab.o +PROG = ovsec_edit_keytab + +LIBS = $(LIBADMCLNT) $(LIBCOM_ERR) $(LIBGSSAPI_KRB5) $(LIBRPCLIB) \ + $(LIBDYN) $(LIBDB) $(LIBKRB5) $(LIBCRYPTO) $(LIBISODE) \ + $(BSDLIB) $(NETLIB) + +expand InstallAdmin + +PROG = ovsec_edit_keytab.local +LIBS = $(LIBADMSRV) $(LIBGSSAPI_KRB5) $(LIBKDB5) $(LIBKRB5) $(NDBMLIB) \ + $(LIBRPCLIB) $(LIBDYN) $(LIBDB) $(LIBKRB5) $(LIBCRYPTO) \ + $(LIBCOM_ERR) $(BSDLIB) $(NETLIB) + +expand InstallAdmin + +SUBDIRS = unit-test +expand SubdirTarget + diff --git a/src/kadmin/keytab/configure.in b/src/kadmin/keytab/configure.in new file mode 100644 index 000000000..0e043f7e5 --- /dev/null +++ b/src/kadmin/keytab/configure.in @@ -0,0 +1,12 @@ +AC_INIT(keytab.c) +CONFIG_RULES +AC_PROG_INSTALL +USE_KADMCLNT_LIBRARY +USE_GSSAPI_LIBRARY +USE_KADMSRV_LIBRARY +USE_GSSRPC_LIBRARY +USE_DYN_LIBRARY +USE_KDB5_LIBRARY +KRB5_LIBRARIES +V5_USE_SHARED_LIB +V5_AC_OUTPUT_MAKEFILE diff --git a/src/kadmin/keytab/keytab.c b/src/kadmin/keytab/keytab.c new file mode 100644 index 000000000..2561252ef --- /dev/null +++ b/src/kadmin/keytab/keytab.c @@ -0,0 +1,528 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <krb5.h> +#include <k5-int.h> +#include <kadm5/admin.h> + +int add_principal(char *keytab_str, krb5_keytab keytab, char *me_str, + char *princ_str, int create); +int remove_principal(char *keytab_str, krb5_keytab keytab, char + *princ_str, char *kvno_str); +static char *etype_string(krb5_enctype enctype); + +krb5_context context; +char *whoami; +int quiet; + +void usage() +{ + fprintf(stderr, "Usage: ovsec_edit_keytab [-k[eytab] keytab] [-q] cmd\n"); + fprintf(stderr, " cmds are:\t-a[dd] [-c[reate] [-p principal] principal\n"); + fprintf(stderr, "\t\t-c[hange] [-p principal] principal\n"); + fprintf(stderr, "\t\t-r[emove] principal [kvno|\"all\"|\"old\"]\n"); + exit(1); +} + +main(int argc0, char **argv0) +{ + extern krb5_kt_ops krb5_ktf_writable_ops; + krb5_keytab keytab = 0; + char *me_str, *princ_str, *keytab_str, *kvno_str; + char keytab_buf[1024]; + int argc, code, did_something, create; + char **argv; + + whoami = strrchr(argv0[0], '/') ? strrchr(argv0[0], '/') + 1 : argv0[0]; + + if (code = krb5_init_context(&context)) { + com_err(whoami, code, "while initializing krb5 context"); + exit(1); + } + + krb5_init_ets(context); + + /* register the WRFILE keytab type and set it as the default */ + if (code = krb5_kt_register(context, &krb5_ktf_writable_ops)) { + com_err(whoami, code, + "while registering writable key table functions"); + exit(1); + } + + /* process non-action arguments first */ + argc = argc0-1; + argv = argv0+1; + while (argc) { + if (strncmp(*argv, "-k", 2) == 0) { + argc--; argv++; + if (!argc) usage(); + + if (keytab == NULL) { + if (strchr(*argv, ':') != NULL) { + keytab_str = strdup(*argv); + if (keytab_str == NULL) { + com_err(whoami, ENOMEM, + "while creating keytab name"); + exit(1); + } + } else { + keytab_str = (char *) + malloc(strlen("WRFILE:")+strlen(*argv)+1); + if (keytab_str == NULL) { + com_err(whoami, ENOMEM, + "while creating keytab name"); + exit(1); + } + sprintf(keytab_str, "WRFILE:%s", *argv); + } + + code = krb5_kt_resolve(context, keytab_str, &keytab); + if (code != 0) { + com_err(whoami, code, "while resolving keytab %s", + keytab_str); + exit(1); + } + } else { + usage(); + } + } else if (strcmp(*argv, "-q") == 0) { + quiet++; + } + /* otherwise ignore the argument, for now */ + argc--; argv++; + } + + if (keytab == NULL) { + code = krb5_kt_default(context, &keytab); + if (code != 0) { + com_err(whoami, code, "while opening default keytab"); + exit(1); + } + code = krb5_kt_get_name(context, keytab, + keytab_buf, sizeof(keytab_buf)); + keytab_str = keytab_buf; + } + + argc = argc0-1; + argv = argv0+1; + + did_something = 0; + + /* now process the action arguments */ + while (argc) { + if (strncmp(*argv, "-k", 2) == 0) { + /* if there is no keytab argument the previous loop */ + /* would have called usage(), so just skip it */ + argc--; argv++; + } else if (strcmp(*argv, "-q") == 0) { + /* skip it */ + } else if (strncmp(*argv, "-a", 2) == 0 || + strncmp(*argv, "-c", 2) == 0) { + did_something++; + + argc--; argv++; + if (!argc) usage(); + + me_str = NULL; + create = 0; + while (argc) { + if (strcmp(*argv, "-p") == 0) { + argc--; argv++; + if (argc < 1) usage(); + + me_str = *argv; + } else if (strncmp(*argv, "-c", 2) == 0) { + create++; + } else + break; + argc--; argv++; + } + if (argc != 1) usage(); + + code = add_principal(keytab_str, keytab, me_str ? me_str : + *argv, *argv, create); + break; + } else if (strncmp(*argv, "-r", 2) == 0) { + did_something++; + + argc--; argv++; + if (!argc) usage(); + princ_str = *argv; + if (argc > 0) { + argc--; + argv++; + kvno_str = *argv; + } else + kvno_str = NULL; + + code = remove_principal(keytab_str, keytab, princ_str, + kvno_str); + break; + } else { + fprintf(stderr, "%s: Unknown command line option %s.\n", + whoami, *argv); + usage(); + } + + argc--; argv++; + } + + /* argv ends up pointing at the last recognized argument */ + if (!did_something || argc > 1) + usage(); + + /* use argc as temp */ + argc = krb5_kt_close(context, keytab); + if (argc != 0) { + com_err(whoami, argc, "while closing keytab"); + code = argc; + } + + free(keytab_str); + + return (code != 0); +} + +int add_principal(char *keytab_str, krb5_keytab keytab, char *me_str, + char *princ_str, int create) +{ + kadm5_principal_ent_rec princ_rec; + krb5_principal me, princ; + krb5_keytab_entry new_entry; + krb5_keyblock *keys; + void *handle; + int code, code2, mask, nkeys, i; + + (void) memset((char *)&princ_rec, 0, sizeof(princ_rec)); + + me = princ = NULL; + handle = NULL; + keys = NULL; + nkeys = 0; + + code = krb5_parse_name(context, me_str, &me); + if (code != 0) { + com_err(whoami, code, "while parsing -p principal name %s", + me_str); + goto cleanup; + } + + code = krb5_parse_name(context, princ_str, &princ); + if (code != 0) { + com_err(whoami, code, "while parsing -add principal name %s", + princ_str); + goto cleanup; + } + + /* first try using the keytab */ + code = kadm5_init_with_skey(me_str, keytab_str, + KADM5_ADMIN_SERVICE, + NULL, /* default configuration */ + KADM5_STRUCT_VERSION, + KADM5_API_VERSION_2, &handle); + if (code != 0) { + /* KRB5_KT_NOTFOUND and ENOENT are not "errors" because this */ + /* program does not require the keytab entry to exist */ + if (code != KRB5_KT_NOTFOUND && code != ENOENT) { + if (code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN) + fprintf(stderr, "%s: Principal %s does not exist.\n", + whoami, me_str); + else + com_err(whoami, code, "while authenticating as principal " + "%s from keytab", me_str); + } + + code2 = kadm5_init_with_password(me_str, NULL, + KADM5_ADMIN_SERVICE, + NULL, + KADM5_STRUCT_VERSION, + KADM5_API_VERSION_2, + &handle); + if (code2 != 0) { + if (code2 != code) /* don't dup error messages */ { + com_err(whoami, code2, "while authenticating as " + "principal %s from password", me_str); + } + goto cleanup; + } + } + + if (create) { + /* always try to create and just ignore dup errors because it */ + /* reduces duplicate code... and how often will this happen? */ + + /* be sure to create the principal with the secure sequence */ + /* of events as specified in the functional spec */ + + princ_rec.principal = princ; + princ_rec.attributes = KRB5_KDB_DISALLOW_ALL_TIX; + mask = KADM5_PRINCIPAL | KADM5_ATTRIBUTES; + code = kadm5_create_principal(handle, &princ_rec, + mask, "dummy"); + if (code == KADM5_DUP) { + printf("%s: Principal %s already exists.\n", + whoami, princ_str); + } else if (code != 0) { + if (code == KADM5_AUTH_ADD) { + fprintf(stderr, "%s: Operation requires " + "``add'' and ``modify'' privileges while creating " + "principal.\n", whoami); + } else { + com_err(whoami, code, "while creating " + "principal %s.", princ_str); + } + goto cleanup; + } else if (!quiet) + printf("%s: Created principal %s.\n", whoami, princ_str); + } + + code = kadm5_randkey_principal(handle, princ, &keys, &nkeys); + if (code != 0) { + if (code == KADM5_UNK_PRINC) { + fprintf(stderr, "%s: Principal %s does not exist.\n", + whoami, princ_str); + } else + com_err(whoami, code, "while changing %s's key", + princ_str); + goto cleanup; + } + + code = kadm5_get_principal(handle, princ, &princ_rec, + KADM5_PRINCIPAL_NORMAL_MASK); + if (code != 0) { + com_err(whoami, code, "while retrieving principal"); + goto cleanup; + } + + if (create) { + /* complete the secure principal-creation sequence */ + princ_rec.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; + mask = KADM5_ATTRIBUTES; + code = kadm5_modify_principal(handle, &princ_rec, mask); + if (code != 0) { + if (code == KADM5_AUTH_ADD) { + fprintf(stderr, "%s: Operation requires " + "``add'' and ``modify'' privileges while creating " + "principal.\n", whoami); + } else + com_err(whoami, code, "while modifying newly created " + "principal"); + (void) kadm5_free_principal_ent(handle, &princ_rec); + goto cleanup; + } + } + + for (i = 0; i < nkeys; i++) { + memset((char *) &new_entry, 0, sizeof(new_entry)); + new_entry.principal = princ; + new_entry.key = keys[i]; + new_entry.vno = princ_rec.kvno; + + code = krb5_kt_add_entry(context, keytab, &new_entry); + if (code != 0) { + com_err(whoami, code, "while adding key to keytab"); + (void) kadm5_free_principal_ent(handle, &princ_rec); + goto cleanup; + } + + if (!quiet) + printf("%s: Entry for principal %s with kvno %d, " + "encryption type %s added to keytab %s.\n", + whoami, princ_str, princ_rec.kvno, + etype_string(keys[i].enctype), keytab_str); + } + + code = kadm5_free_principal_ent(handle, &princ_rec); + if (code != 0) { + com_err(whoami, code, "while freeing principal entry"); + goto cleanup; + } + +cleanup: + if (handle) { + code2 = kadm5_destroy(handle); + if (code2 != 0) { + com_err(whoami, code2, "while closing admin server connection"); + } + } + if (nkeys) { + for (i = 0; i < nkeys; i++) + krb5_free_keyblock(context, &keys[i]); + free(keys); + } + if (me) + krb5_free_principal(context, me); + if (princ) + krb5_free_principal(context, princ); + + return code; +} + +int remove_principal(char *keytab_str, krb5_keytab keytab, char + *princ_str, char *kvno_str) +{ + krb5_principal princ; + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + enum { UNDEF, SPEC, HIGH, ALL, OLD } mode; + int code, kvno, did_something; + + code = krb5_parse_name(context, princ_str, &princ); + if (code != 0) { + com_err(whoami, code, "while parsing principal name %s", + princ_str); + return code; + } + + mode = UNDEF; + if (kvno_str == NULL) { + mode = HIGH; + kvno = 0; + } else if (strcmp(kvno_str, "all") == 0) { + mode = ALL; + kvno = 0; + } else if (strcmp(kvno_str, "old") == 0) { + mode = OLD; + kvno = 0; + } else { + mode = SPEC; + kvno = atoi(kvno_str); + } + + /* kvno is set to specified value for SPEC, 0 otherwise */ + code = krb5_kt_get_entry(context, keytab, princ, kvno, 0, &entry); + if (code != 0) { + if (code == ENOENT) { + fprintf(stderr, "%s: Keytab %s does not exist.\n", + whoami, keytab_str); + } else if (code == KRB5_KT_NOTFOUND) { + if (mode != SPEC) + fprintf(stderr, "%s: No entry for principal " + "%s exists in keytab %s\n", + whoami, princ_str, keytab_str); + else + fprintf(stderr, "%s: No entry for principal " + "%s with kvno %d exists in keytab " + "%s.\n", whoami, princ_str, kvno, + keytab_str); + } else { + com_err(whoami, code, "while retrieving highest kvno " + "from keytab"); + } + return code; + } + + /* set kvno to spec'ed value for SPEC, highest kvno otherwise */ + kvno = entry.vno; + krb5_kt_free_entry(context, &entry); + + code = krb5_kt_start_seq_get(context, keytab, &cursor); + if (code != 0) { + com_err(whoami, code, "while starting keytab scan"); + return code; + } + + did_something = 0; + while ((code = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) { + if (krb5_principal_compare(context, princ, entry.principal) && + ((mode == ALL) || + (mode == SPEC && entry.vno == kvno) || + (mode == OLD && entry.vno != kvno) || + (mode == HIGH && entry.vno == kvno))) { + + /* + * Ack! What a kludge... the scanning functions lock + * the keytab so entries cannot be removed while they + * are operating. + */ + code = krb5_kt_end_seq_get(context, keytab, &cursor); + if (code != 0) { + com_err(whoami, code, "while temporarily ending " + "keytab scan"); + return code; + } + code = krb5_kt_remove_entry(context, keytab, &entry); + if (code != 0) { + com_err(whoami, code, "while deleting entry from keytab"); + return code; + } + code = krb5_kt_start_seq_get(context, keytab, &cursor); + if (code != 0) { + com_err(whoami, code, "while restarting keytab scan"); + return code; + } + + did_something++; + if (!quiet) + printf("%s: Entry for principal %s with kvno %d " + "removed from keytab %s.\n", whoami, + princ_str, entry.vno, keytab_str); + } + krb5_kt_free_entry(context, &entry); + } + if (code && code != KRB5_KT_END) { + com_err(whoami, code, "while scanning keytab"); + return code; + } + if (code = krb5_kt_end_seq_get(context, keytab, &cursor)) { + com_err(whoami, code, "while ending keytab scan"); + return code; + } + + /* + * If !did_someting then mode must be OLD or we would have + * already returned with an error. But check it anyway just to + * prevent unexpected error messages... + */ + if (!did_something && mode == OLD) { + fprintf(stderr, "%s: There is only one entry for principal " + "%s in keytab %s\n", whoami, princ_str, keytab_str); + return 1; + } + + return 0; +} + +/* + * etype_string(enctype): return a string representation of the + * encryption type. XXX copied from klist.c; this should be a + * library function, or perhaps just #defines + */ +static char *etype_string(enctype) + krb5_enctype enctype; +{ + static char buf[12]; + + switch (enctype) { + case ENCTYPE_DES_CBC_CRC: + return "DES-CBC-CRC"; + break; + case ENCTYPE_DES_CBC_MD4: + return "DES-CBC-MD4"; + break; + case ENCTYPE_DES_CBC_MD5: + return "DES-CBC-MD5"; + break; +#if 0 + case ENCTYPE_DES3_CBC_MD5: + return "DES3-CBC-MD5"; + break; +#endif + default: + sprintf(buf, "etype %d", enctype); + return buf; + break; + } +} diff --git a/src/kadmin/keytab/unit-test/ChangeLog b/src/kadmin/keytab/unit-test/ChangeLog new file mode 100644 index 000000000..69df6be92 --- /dev/null +++ b/src/kadmin/keytab/unit-test/ChangeLog @@ -0,0 +1,4 @@ +Mon Jul 15 17:03:28 1996 Marc Horowitz <marc@mit.edu> + + * Makefile.ov (unit-test-body): ovsec_adm_keytab is now + kadm5_keytab diff --git a/src/kadmin/keytab/unit-test/Makefile.ov b/src/kadmin/keytab/unit-test/Makefile.ov new file mode 100644 index 000000000..1b3366d8b --- /dev/null +++ b/src/kadmin/keytab/unit-test/Makefile.ov @@ -0,0 +1,21 @@ +# +# $Id$ +# + +TOP = ../.. +include $(TOP)/config.mk/template + +unit-test:: unit-test-setup unit-test-body unit-test-cleanup + +unit-test-body:: + $(CLNTTCL) ./del-princs.tcl + $(RUNTEST) KEYTAB=../kadm5_keytab \ + KLIST=../../../clients/klist/klist \ + QUALNAME=../../testing/scripts/qualname --tool keytab + +unit-test-setup:: + $(START_SERVERS) + $(CLNTTCL) ./add-princs.tcl + +unit-test-cleanup:: + $(STOP_SERVERS) diff --git a/src/kadmin/keytab/unit-test/add-princs.tcl b/src/kadmin/keytab/unit-test/add-princs.tcl new file mode 100644 index 000000000..247a4382b --- /dev/null +++ b/src/kadmin/keytab/unit-test/add-princs.tcl @@ -0,0 +1,12 @@ +source $env(TCLUTIL) + +ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \ + $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle + +ovsec_kadm_create_principal $server_handle [simple_principal kttest1] \ + {OVSEC_KADM_PRINCIPAL} kttest1 + +ovsec_kadm_create_principal $server_handle [simple_principal kttest2] \ + {OVSEC_KADM_PRINCIPAL} kttest2 + +ovsec_kadm_destroy $server_handle diff --git a/src/kadmin/keytab/unit-test/config/unix.exp b/src/kadmin/keytab/unit-test/config/unix.exp new file mode 100644 index 000000000..bc07d4f6e --- /dev/null +++ b/src/kadmin/keytab/unit-test/config/unix.exp @@ -0,0 +1,46 @@ +set klist $KLIST +set hostname hostname +set qualname $QUALNAME + +set rm /bin/rm + +if {[info commands exp_version] != {}} { + set exp_version_4 [regexp {^4} [exp_version]] +} else { + set exp_version_4 [regexp {^4} [expect_version]] +} + +# Backward compatibility until we're using expect 5 everywhere +if {$exp_version_4} { + global wait_error_index wait_errno_index wait_status_index + set wait_error_index 0 + set wait_errno_index 1 + set wait_status_index 1 +} else { + set wait_error_index 2 + set wait_errno_index 3 + set wait_status_index 3 +} + +proc keytab_version {} { + global KEYTAB + puts "$KEYTAB version unknown" +} + +proc keytab_load {} { + # +} + +proc keytab_exit {} { + # +} + +proc keytab_start { args } { + global KEYTAB + global spawn_id + + verbose "% $KEYTAB $args" 1 + eval spawn $KEYTAB $args +} + + diff --git a/src/kadmin/keytab/unit-test/del-princs.tcl b/src/kadmin/keytab/unit-test/del-princs.tcl new file mode 100644 index 000000000..9b9cab5c4 --- /dev/null +++ b/src/kadmin/keytab/unit-test/del-princs.tcl @@ -0,0 +1,24 @@ +source $env(TCLUTIL) + +proc check_err {error} { + if {! [string match {*OVSEC_KADM_UNK_PRINC*} $error]} { + error $error + } +} + +proc delprinc {princ} { + global server_handle + + catch {ovsec_kadm_delete_principal $server_handle $princ} + if {[info exists errorInfo]} { + check_err $errorInfo + } +} + +ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \ + $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle + +delprinc dne1 +delprinc dne2 + +ovsec_kadm_destroy $server_handle diff --git a/src/kadmin/keytab/unit-test/helpers.exp b/src/kadmin/keytab/unit-test/helpers.exp new file mode 100644 index 000000000..a9f7ca402 --- /dev/null +++ b/src/kadmin/keytab/unit-test/helpers.exp @@ -0,0 +1,132 @@ +# +# $Id$ +# + +# +# Create a keytab "name" with an entry for each element in the array +# "entries". If "name" already exists it is destroyed. Connections +# to the admin server are made as the principal "admin" with the +# password "password". +# +proc setup_keytab { testname ktname admin password entries } { + global klist rm + global wait_error_index wait_status_index + global verbose + + verbose "setting up test: $testname" 1 + + if {[regexp {(.+):(.+)} $ktname dummy type filename] == 0} { + set filename $ktname + } + + if {[file exists $filename] && [catch "exec $rm $filename"] != 0} { + error "$testname: cannot delete keytab file $filename"; + } + + if {$type == "WRFILE"} { + set type "FILE" + } + + foreach entry $entries { + keytab_run "$testname setup" \ + "-k $ktname -a -p $admin $entry" 0 { + "Enter password:" { + send "$password\n" + } + } + # if "Enter password:" needs to be optional: + # { timeout { } } + } + + if {$verbose > 1} { + if {[file exists $filename]} { + puts "% exec $klist -k $type:$filename\n" + if {[catch "exec $klist -k $type:$filename"] != 0} { + error "$testname: $klist failed" + } + } + } +} + +# +# Run $KEYTAB with args ktargs. Each element of args is treated as an +# expect block for the process, in turn. If all elements match and +# then eof occurs with exit status status, the test passes; otherwise +# it fails. +# +proc keytab_run { testname ktargs status args } { + global spawn_id timeout + global wait_error_index wait_status_index + global progname + + verbose "running $progname for test: $testname" 2 + + eval keytab_start $ktargs + + # wait for eof after exps + lappend args { eof { verbose $expect_out(buffer) 2 } } + + foreach exp $args { + uplevel 1 "expect { + $exp + timeout { close; fail \"$testname: timeout\"; return } + eof { fail \"$testname: eof before expected message\"; return } + }" + } + + set ret [wait] + verbose "% Exit $ret" 2 + + if {[lindex $ret $wait_error_index] == -1} { + fail "$testname: wait returned error [lindex $ret $wait_errno_index]" + } else { + if { [lindex $ret $wait_status_index] == $status || + (($status<0) && ([lindex $ret $wait_status_index] == ($status+256))) } { + pass "$testname" + } else { + fail "$testname: unexpected return status [lindex $ret $wait_status_index], should be $status" + } + } +} + + +proc klist_check { testname ktname args } { + global klist + + if {[regexp {(.+):(.+)} $ktname dummy type filename] == 0} { + set filename $ktname + } + + set lines [list "^Keytab name: (WR)?FILE:$filename" \ + "^KVNO Principal" "^---- -------"] + + foreach entry $args { + if {[lindex $entry 1] == 0} { + set line "^ *\[0-9\]+ [lindex $entry 0]" + } else { + set line "^ *[lindex $entry 1] [lindex $entry 0]" + } + lappend lines $line + } + + set kl [open "|$klist -k FILE:$filename" r] + + while {[gets $kl line] >= 0} { + if {([llength $lines] == 0) || + ([regexp [lindex $lines 0] $line] == 0)} { + fail "$testname: klist check: \ + [lindex $lines 0] does not match $line" + } + set lines [lrange $lines 1 end] + } + if {[catch "close $kl" msg] != 0} { + fail "$testname: klist: $msg" + return + } + + if {[llength $lines] == 0} { + pass "$testname: klist check" + } else { + fail "$testname: klist check: too few entries in keytab" + } +} diff --git a/src/kadmin/keytab/unit-test/keytab.0/ChangeLog b/src/kadmin/keytab/unit-test/keytab.0/ChangeLog new file mode 100644 index 000000000..1b807089a --- /dev/null +++ b/src/kadmin/keytab/unit-test/keytab.0/ChangeLog @@ -0,0 +1,4 @@ +Mon Jul 15 17:09:01 1996 Marc Horowitz <marc@mit.edu> + + * keytab-spec.exp: use /krb5/v5srvtab, since /krb5 is the test + dir. diff --git a/src/kadmin/keytab/unit-test/keytab.0/adding.exp b/src/kadmin/keytab/unit-test/keytab.0/adding.exp new file mode 100644 index 000000000..159ac638b --- /dev/null +++ b/src/kadmin/keytab/unit-test/keytab.0/adding.exp @@ -0,0 +1,119 @@ +# +# $Id$ +# + +set timeout 20 + +load_lib "helpers.exp" + +if {[regexp {(.*/)?([^/]*)} $KEYTAB dummy dir progname] == 0} { + error "cannot set progname from $KEYTAB" +} + +set ktscratch_file /tmp/keytab_test +set ktscratch WRFILE:$ktscratch_file +set ktarg "-k $ktscratch" +set add_admin "$ktarg -a -p admin" +set pwprompt { "Enter password:" { send "admin\n" } } + +setup_keytab "A1,A6" $ktscratch admin admin {} +keytab_run "A1,A6" "$add_admin kttest1" 0 "$pwprompt" { + -re \ + "$progname: Entry.*kttest1.*kvno \[0-9\]+.*keytab $ktscratch." {} +} +klist_check "A1,A6" $ktscratch {kttest1 0} + +setup_keytab "A2" $ktscratch admin admin {} +keytab_run "A2" "-q $add_admin kttest1" 0 "$pwprompt" { + -re + "$progname: Entry.*kttest1.*kvno \[0-9\]+.*keytab $ktscratch." { + close; fail "A2: -q"; return } + eof { break } +} +klist_check "A2" $ktscratch {kttest1 0} + +setup_keytab "A3" $ktscratch admin admin {kttest1 kttest1} +set kvno_key1 [exec $klist -k -K FILE:$ktscratch_file | \ + awk "/kttest1/ && NR==4 {print \$1 \" \" \$3}"] +set kvno_key2 [exec $klist -k -K FILE:$ktscratch_file | \ + awk "/kttest1/ && NR==5 {print \$1 \" \" \$3}"] +if {[lindex $kvno_key1 1] == [lindex $kvno_key2 1]} { + fail "A3: key compare" +} else { + klist_check "A3" $ktscratch "kttest1 [lindex $kvno_key1 0]" \ + "kttest1 [expr [lindex $kvno_key1 0]+1]" +} + +setup_keytab "A7" $ktscratch admin admin {} +keytab_run "A7" "$add_admin does-not-exist" 1 "$pwprompt" { + -re + "$progname: Principal does-not-exist does not exist." {} +} + +setup_keytab "A4,A10,A11,A13,A15" $ktscratch admin admin { kttest1 kttest2} +keytab_run "A4,A10,A11,A13,A15" "$ktarg -a kttest1" 0 +keytab_run "A4,A10,A11,A13,A15" "$ktarg -a kttest2" 0 +keytab_run "A4,A10,A11,A13,A15" "$ktarg -a kttest1" 0 +keytab_run "A4,A10,A11,A13,A15" "$ktarg -a kttest2" 0 +klist_check "A4,A10,A11,A13,A15" $ktscratch { kttest1 0 } \ + { kttest2 0 } { kttest1 0 } { kttest2 0 } { kttest1 0 } { kttest2 0 } + +setup_keytab "A12" $ktscratch admin admin {} +keytab_run "A12" "$ktarg -a -p admin/get-add kttest1" 1 "$pwprompt" { + "Operation requires ``change-password'' privilege while changing" {} +} + +setup_keytab "A14" $ktscratch admin admin {} +# assume the exit status won't be -1, so if the password prompt +# doesn't appear the test will fail +keytab_run "A14" "$ktarg -a kttest1" -1 { + "Enter password:" { send "\n"; expect eof; pass "A14: no -p"; return } +} + +setup_keytab "A16" $ktscratch admin admin {} +keytab_run "A16" "$ktarg -a -p does-not-exist kttest1" 1 { + "$progname: Principal does-not-exist does not exist." {} +} + +setup_keytab "A17" $ktscratch admin admin { kttest1 kttest2} +keytab_run "A17" "$ktarg -a -p kttest2 kttest1" 1 { + "Enter password:" { close; fail "A17: no password prompt"; return } + default { break } +} + +setup_keytab "A18" $ktscratch admin admin { } +keytab_run "A18" "$ktarg -a -c -p admin dne1" 0 "$pwprompt" { + "$progname: Created principal dne1" {} +} { + -re + "$progname: Entry.*dne1.*kvno \[0-9\]+.*keytab $ktscratch." {} +} +klist_check "A18" $ktscratch {dne1 0} + +setup_keytab "A19" $ktscratch admin admin {} +keytab_run "A9" "-q $ktarg -a -c -p admin dne2" 0 "$pwprompt" { + "$progname: Created principal dne2" { close; fail "A19: -q"; return } + eof { break } +} +klist_check "A19" $ktscratch {dne2 0} + +setup_keytab "A21" $ktscratch admin admin {} +keytab_run "A21" "$ktarg -a -c -p admin kttest1" 0 "$pwprompt" { + "$progname: Principal kttest1 already exists." {} +} { + -re \ + "$progname: Entry.*kttest1.*kvno \[0-9\]+.*keytab $ktscratch." {} +} +klist_check "A21" $ktscratch {kttest1 0} + +setup_keytab "A22" $ktscratch admin admin {} +keytab_run "A22" "$ktarg -a -c -p admin/modify kttest1" 1 "$pwprompt" { + "Operation requires ``add'' and ``modify'' privileges while creating" {} +} + +setup_keytab "A23" $ktscratch admin admin {} +keytab_run "A23" "$ktarg -a -c -p admin/get kttest1" 1 "$pwprompt" { + "Operation requires ``add'' and ``modify'' privileges while creating" {} +} + +exec rm -f $ktscratch_file diff --git a/src/kadmin/keytab/unit-test/keytab.0/keytab-spec.exp b/src/kadmin/keytab/unit-test/keytab.0/keytab-spec.exp new file mode 100644 index 000000000..8da80eb69 --- /dev/null +++ b/src/kadmin/keytab/unit-test/keytab.0/keytab-spec.exp @@ -0,0 +1,47 @@ +# +# $Id$ +# + +set timeout 10 + +load_lib "helpers.exp" + +if {[regexp {(.*/)?([^/]*)} $KEYTAB dummy dir progname] == 0} { + error "cannot set progname from $KEYTAB" +} + +set hname [exec $hostname] +set qname [exec $qualname $hname] + +set testfile1 /tmp/keytab-test1 +set testfile2 /tmp/keytab-test2 + +if {[info exists env(KRB5_KTNAME)]} { + set ktname_orig $env(KRB5_KTNAME) + unset env(KRB5_KTNAME) +} + +setup_keytab "K1" WRFILE:/krb5/v5srvtab admin admin "host/$qname" +klist_check "K1" FILE:/krb5/v5srvtab "host/$qname 0" +keytab_run "K1" "-a host/$qname" 0 +klist_check "K1" FILE:/krb5/v5srvtab "host/$qname 0" "host/$qname 0" +keytab_run "K1" "-r host/$qname old" 0 +klist_check "K1" FILE:/krb5/v5srvtab "host/$qname 0" + +if {[info exists ktname_orig]} { + set env(KRB5_KTNAME) $ktname_orig +} + +setup_keytab "K2" WRFILE:$testfile1 admin admin {} +keytab_run "K2" "-k WRFILE:$testfile1 -a -p admin kttest1" 0 { + "Enter password:" { send "admin\n" } +} +klist_check "K2" FILE:$testfile1 "kttest1 0" + +setup_keytab "K2" WRFILE:$testfile2 admin admin {} +keytab_run "K3" "-k $testfile2 -a -p admin kttest1" 0 { + "Enter password:" { send "admin\n" } +} +klist_check "K3" FILE:$testfile2 "kttest1 0" + +exec rm -f $testfile1 $testfile2 diff --git a/src/kadmin/keytab/unit-test/keytab.0/removing.exp b/src/kadmin/keytab/unit-test/keytab.0/removing.exp new file mode 100644 index 000000000..a7a50f045 --- /dev/null +++ b/src/kadmin/keytab/unit-test/keytab.0/removing.exp @@ -0,0 +1,125 @@ +# +# $Id$ +# + +set timeout 10 + +load_lib "helpers.exp" + +if {[regexp {(.*/)?([^/]*)} $KEYTAB dummy dir progname] == 0} { + error "cannot set progname from $KEYTAB" +} + +set ktscratch_file /tmp/keytab_test +set ktscratch WRFILE:$ktscratch_file +set ktarg "-k $ktscratch" + +# Get the kvnos we will need later +setup_keytab "setup" $ktscratch admin admin { kttest1 kttest2 } +set kvno1 [exec $klist -k -K FILE:$ktscratch_file | \ + awk "/kttest1/ {print \$1}"] +set kvno2 [exec $klist -k -K FILE:$ktscratch_file | \ + awk "/kttest2/ {print \$1}"] + +setup_keytab "R1" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +keytab_run "R1" "$ktarg -r kttest1" 0 { + -re + "$progname: Entry for principal kttest1 with kvno \[0-9\]+\ + removed from keytab $ktscratch" {} +} +klist_check "R1" $ktscratch + +setup_keytab "R2" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +keytab_run "R2" "$ktarg -q -r kttest1" 0 { + -re + "$progname: Entry for principal kttest1 with kvno \[0-9\]+\ + removed from keytab $ktscratch" { close; fail "R2: -q"; return } + eof { break } +} +klist_check "R2" $ktscratch + +setup_keytab "R3" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +klist_check "R3" $ktscratch "kttest1 $kvno1" +keytab_run "R3" "$ktarg -r kttest1 $kvno1" 0 +klist_check "R3" $ktscratch + +setup_keytab "R4" $ktscratch admin admin { kttest1 kttest1 kttest1 } +set kvno1 [expr $kvno1+3] +klist_check "R4" $ktscratch "kttest1 [expr $kvno1-2]" \ + "kttest1 [expr $kvno1-1]" "kttest1 $kvno1" +keytab_run "R4" "$ktarg -r kttest1" 0 +klist_check "R4" $ktscratch "kttest1 [expr $kvno1-2]" \ + "kttest1 [expr $kvno1-1]" + +setup_keytab "R5" $ktscratch admin admin { kttest1 kttest1 kttest1 } +set kvno1 [expr $kvno1+3] +keytab_run "R5" "$ktarg -r kttest1 old" 0 +klist_check "R5" $ktscratch "kttest1 $kvno1" + +setup_keytab "R6" $ktscratch admin admin { kttest1 kttest1 kttest1 } +set kvno1 [expr $kvno1+3] +keytab_run "R6" "$ktarg -r kttest1 old" 0 +klist_check "R6" $ktscratch "kttest1 $kvno1" + +setup_keytab "R7" $ktscratch admin admin { kttest1 kttest1 kttest1 } +set kvno1 [expr $kvno1+3] +keytab_run "R7" "$ktarg -r kttest1 all" 0 { + "$progname: Entry for principal kttest1" {} +} { + "$progname: Entry for principal kttest1" {} +} { + "$progname: Entry for principal kttest1" {} +} +klist_check "R7" $ktscratch + +setup_keytab "R8" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +keytab_run "R8" "$ktarg -r kttest2" 1 { + "$progname: No entry for principal kttest2 exists in keytab" {} +} +klist_check "R8" $ktscratch "kttest1 $kvno1" + +setup_keytab "R9" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +keytab_run "R9" "$ktarg -r kttest2 1" 1 { + "$progname: No entry for principal kttest2 with kvno 1 exists in keytab" {} +} +klist_check "R9" $ktscratch "kttest1 $kvno1" + +setup_keytab "R10" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +keytab_run "R10" "$ktarg -r kttest2 all" 1 { + "$progname: No entry for principal kttest2 exists in keytab" {} +} +klist_check "R10" $ktscratch "kttest1 $kvno1" + +setup_keytab "R11" $ktscratch admin admin { kttest1 } +set kvno1 [expr $kvno1+1] +keytab_run "R11" "$ktarg -r kttest1 old" 1 { + "$progname: There is only one entry for principal kttest1 in keytab" {} +} +klist_check "R11" $ktscratch "kttest1 $kvno1" + +setup_keytab "R13" $ktscratch admin admin { kttest1 kttest2 kttest1 } +set kvno1 [expr $kvno1+2] +set kvno2 [expr $kvno2+1] +keytab_run "R13" "$ktarg -r kttest2 $kvno2" 0 +klist_check "R13" $ktscratch "kttest1 [expr $kvno1-1]" "kttest1 $kvno1" + +setup_keytab "R14" $ktscratch admin admin { kttest1 kttest2 kttest1 kttest2 } +set kvno1 [expr $kvno1+2] +set kvno2 [expr $kvno2+2] +keytab_run "R14" "$ktarg -r kttest1 all" 0 +klist_check "R14" $ktscratch "kttest2 [expr $kvno2-1]" "kttest2 $kvno2" + +setup_keytab "R15" $ktscratch admin admin { kttest1 kttest2 kttest1 kttest2 } +set kvno1 [expr $kvno1+2] +set kvno2 [expr $kvno2+2] +keytab_run "R15" "$ktarg -r kttest1 old" 0 +klist_check "R15" $ktscratch "kttest2 [expr $kvno2-1]" \ + "kttest1 $kvno1" "kttest2 $kvno2" + +exec rm -f $ktscratch_file |
