diff options
| author | Marc Horowitz <marc@mit.edu> | 1996-07-22 20:49:46 +0000 |
|---|---|---|
| committer | Marc Horowitz <marc@mit.edu> | 1996-07-22 20:49:46 +0000 |
| commit | edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1 (patch) | |
| tree | 6c2974a97b448c040fa4a31708ec5e02f187526c /src/kadmin/keytab | |
| parent | 013bb1391582ed9e653ae706e398ddb8d08cfcc9 (diff) | |
| download | krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.gz krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.xz krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.zip | |
this commit includes all the changes on the OV_9510_INTEGRATION and
OV_MERGE branches. This includes, but is not limited to, the new openvision
admin system, and major changes to gssapi to add functionality, and bring
the implementation in line with rfc1964. before committing, the
code was built and tested for netbsd and solaris.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@8774 dc483132-0cff-0310-8789-dd5450dbe970
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 |
