diff options
author | Ken Raeburn <raeburn@mit.edu> | 2007-08-16 22:55:06 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@mit.edu> | 2007-08-16 22:55:06 +0000 |
commit | c15ec7751a7d7c1d97dbeb1dd88dda2a328515e0 (patch) | |
tree | 824bd8c158b1c5b72913515953c7e8576399d912 /src/lib/gssapi/generic | |
parent | 9db2f5eb745287654117e70032d05dd9f5a91a3f (diff) | |
download | krb5-c15ec7751a7d7c1d97dbeb1dd88dda2a328515e0.zip krb5-c15ec7751a7d7c1d97dbeb1dd88dda2a328515e0.tar.gz krb5-c15ec7751a7d7c1d97dbeb1dd88dda2a328515e0.tar.bz2 |
remap mechanism-specific status codes in mechglue/spnego
This patch creates a mapping in the mechglue/spnego code to modify
mechanism status codes when passing them back to the application, so
that mechglue's display_status dispatcher can determine the correct
mechanism to dispatch to.
This is part of the "get enhanced error messages from gssapi
applications" project; ticket 5590 has updates to the Kerberos 5
mechanism to extract enhanced error messages (when there are any) from
the Kerberos library.
util/gen.pl, util/t_*.pm: New code generation script and templates.
lib/gssapi/generic: Add a new, global mapping that enumerates the
{mechOID,status} pairs as they're seen, allowing a magic mechOID value
to indicate com_err error codes from mechglue and spnego, and
reserving status code 0 for unknown errors. Preload the Kerberos
"wrong principal" error code once for each mechanism OID used for
Kerberos, so the entries get fixed positions (1-3) in the table.
lib/gssapi/gss_libinit.c: Call the initializer and destructor
functions.
lib/gssapi/mechglue, lib/gssapi/spnego: Enter all mechanism-generated
or locally-generated status codes into the mapping table, and return
the table index to the application. Do the reverse in display_status,
to get the messages from the mechanism..
lib/rpc: Define new function gssrpcint_printf to use for debugging
instead of printf, to redirect output away from dejagnu; add a couple
more debugging calls. Check for minor status codes 1-3 now instead of
KRB5KRB_AP_WRONG_PRINC.
tests/dejagnu/krb-standalone/gssftp.exp: Test getting more detailed
error messages back, by having the ftp client attempt to authenticate
to a non-existent service, and examining the error message for the
service principal name.
ticket: new
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19831 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/gssapi/generic')
-rw-r--r-- | src/lib/gssapi/generic/Makefile.in | 21 | ||||
-rw-r--r-- | src/lib/gssapi/generic/gssapiP_generic.h | 5 | ||||
-rw-r--r-- | src/lib/gssapi/generic/maptest.c | 54 | ||||
-rw-r--r-- | src/lib/gssapi/generic/util_errmap.c | 190 |
4 files changed, 270 insertions, 0 deletions
diff --git a/src/lib/gssapi/generic/Makefile.in b/src/lib/gssapi/generic/Makefile.in index e63be6b..6d66396 100644 --- a/src/lib/gssapi/generic/Makefile.in +++ b/src/lib/gssapi/generic/Makefile.in @@ -70,6 +70,7 @@ SRCS = \ $(srcdir)/rel_buffer.c \ $(srcdir)/rel_oid_set.c \ $(srcdir)/util_buffer.c \ + $(srcdir)/util_errmap.c \ $(srcdir)/util_ordering.c \ $(srcdir)/util_set.c \ $(srcdir)/util_token.c \ @@ -83,6 +84,7 @@ OBJS = \ $(OUTPRE)rel_buffer.$(OBJEXT) \ $(OUTPRE)rel_oid_set.$(OBJEXT) \ $(OUTPRE)util_buffer.$(OBJEXT) \ + $(OUTPRE)util_errmap.$(OBJEXT) \ $(OUTPRE)util_ordering.$(OBJEXT) \ $(OUTPRE)util_set.$(OBJEXT) \ $(OUTPRE)util_token.$(OBJEXT) \ @@ -96,6 +98,7 @@ STLIBOBJS = \ rel_buffer.o \ rel_oid_set.o \ util_buffer.o \ + util_errmap.o \ util_ordering.o \ util_set.o \ util_token.o \ @@ -110,6 +113,19 @@ $(OBJS): $(EXPORTED_HEADERS) $(ETHDRS) all-unix:: $(EXPORTED_HEADERS) $(ETHDRS) $(HDRS) all-unix:: all-libobjs +errmap.h: $(SRCTOP)/util/gen.pl $(SRCTOP)/util/t_array.pm \ + $(SRCTOP)/util/t_enum.pm $(SRCTOP)/util/t_tsenum.pm + $(PERL) -w -I$(SRCTOP)/util $(SRCTOP)/util/gen.pl tsenum errmap.h \ + NAME=mecherrmap TYPE="struct mecherror" COMPARE=mecherror_cmp \ + COPY=mecherror_copy PRINT=mecherror_print + +maptest.h: $(SRCTOP)/util/gen.pl $(SRCTOP)/util/t_array.pm \ + $(SRCTOP)/util/t_enum.pm $(SRCTOP)/util/t_tsenum.pm + $(PERL) -w -I$(SRCTOP)/util $(SRCTOP)/util/gen.pl tsenum maptest.h \ + NAME=foo TYPE=elt COMPARE=eltcmp COPY=eltcp PRINT=eltprt +maptest.o: maptest.c maptest.h +maptest: maptest.o + $(CC_LINK) -o maptest maptest.o $(SUPPORT_LIB) ##DOS##LIBOBJS = $(OBJS) @@ -180,6 +196,11 @@ util_buffer.so util_buffer.po $(OUTPRE)util_buffer.$(OBJEXT): \ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \ gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \ util_buffer.c +util_errmap.so util_errmap.po $(OUTPRE)util_errmap.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \ + errmap.h gssapiP_generic.h gssapi_err_generic.h gssapi_generic.h \ + util_errmap.c util_ordering.so util_ordering.po $(OUTPRE)util_ordering.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-thread.h \ diff --git a/src/lib/gssapi/generic/gssapiP_generic.h b/src/lib/gssapi/generic/gssapiP_generic.h index e34055b..1ec5417 100644 --- a/src/lib/gssapi/generic/gssapiP_generic.h +++ b/src/lib/gssapi/generic/gssapiP_generic.h @@ -255,4 +255,9 @@ OM_uint32 generic_gss_str_to_oid gss_OID * /* oid */ ); +OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc *oid); +int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, + OM_uint32 *mech_minor); +OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode); + #endif /* _GSSAPIP_GENERIC_H_ */ diff --git a/src/lib/gssapi/generic/maptest.c b/src/lib/gssapi/generic/maptest.c new file mode 100644 index 0000000..b884eed --- /dev/null +++ b/src/lib/gssapi/generic/maptest.c @@ -0,0 +1,54 @@ +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> + +typedef struct { int a, b; } elt; +static int eltcp(elt *dest, elt src) +{ + *dest = src; + return 0; +} +static int eltcmp(elt left, elt right) +{ + if (left.a < right.a) + return -1; + if (left.a > right.a) + return 1; + if (left.b < right.b) + return -1; + if (left.b > right.b) + return 1; + return 0; +} +static void eltprt(elt v, FILE *f) +{ + fprintf(f, "{%d,%d}", v.a, v.b); +} + +#include "maptest.h" + +foo foo1; + +int main () +{ + int err; + elt v1 = { 1, 2 }, v2 = { 3, 4 }; + long idx; + int added; + + err = foo_init(&foo1); + assert(err == 0); + err = foo_find_or_append(&foo1, v1, &idx, &added); + assert(err == 0); + printf("v1: idx=%ld added=%d\n", idx, added); + err = foo_find_or_append(&foo1, v2, &idx, &added); + assert(err == 0); + printf("v2: idx=%ld added=%d\n", idx, added); + err = foo_find_or_append(&foo1, v2, &idx, &added); + assert(err == 0); + printf("v2: idx=%ld added=%d\n", idx, added); + err = foo_find_or_append(&foo1, v1, &idx, &added); + assert(err == 0); + printf("v1: idx=%ld added=%d\n", idx, added); + return 0; +} diff --git a/src/lib/gssapi/generic/util_errmap.c b/src/lib/gssapi/generic/util_errmap.c new file mode 100644 index 0000000..24975cc --- /dev/null +++ b/src/lib/gssapi/generic/util_errmap.c @@ -0,0 +1,190 @@ +#include "gssapiP_generic.h" +#include <string.h> +#include <unistd.h> + +/* The mapping table is 0-based, but let's export codes that are + 1-based, keeping 0 for errors or unknown errors. + + The elements in the mapping table currently have separate copies of + each OID stored. This is a bit wasteful, but we are assuming the + table isn't likely to grow very large. */ + +struct mecherror { + gss_OID_desc mech; + OM_uint32 code; +}; + +static inline int +mecherror_cmp(struct mecherror m1, struct mecherror m2) +{ + if (m1.code < m2.code) + return -1; + if (m1.code > m2.code) + return 1; + if (m1.mech.length < m2.mech.length) + return -1; + if (m1.mech.length > m2.mech.length) + return 1; + if (m1.mech.length == 0) + return 0; + return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length); +} + +static inline int +mecherror_copy(struct mecherror *dest, struct mecherror src) +{ + *dest = src; + if (src.mech.length) { + dest->mech.elements = malloc(src.mech.length); + if (dest->mech.elements == NULL) + return ENOMEM; + } + memcpy(dest->mech.elements, src.mech.elements, src.mech.length); + return 0; +} + +static void +mecherror_print(struct mecherror value, FILE *f) +{ + OM_uint32 minor; + gss_buffer_desc str; + static const struct { + const char *oidstr, *name; + } mechnames[] = { + { "{ 1 2 840 113554 1 2 2 }", "krb5-new" }, + { "{ 1 3 5 1 5 2 }", "krb5-old" }, + { "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" }, + { "{ 1 3 6 1 5 5 2 }", "spnego" }, + }; + int i; + + fprintf(f, "%lu@", (unsigned long) value.code); + + if (value.mech.length == 0) { + fprintf(f, "(com_err)"); + return; + } + if (generic_gss_oid_to_str(&minor, &value.mech, &str)) { + fprintf(f, "(error in conversion)"); + return; + } + /* Note: generic_gss_oid_to_str returns a null-terminated string. */ + for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) { + if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) { + fprintf(f, "%s", mechnames[i].name); + break; + } + } + if (i == sizeof(mechnames)/sizeof(mechnames[0])) + fprintf(f, "%s", (char *) str.value); + generic_gss_release_buffer(&minor, &str); +} + +#include "errmap.h" +#include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */ + +static mecherrmap m; + +int gssint_mecherrmap_init(void) +{ + int err; + OM_uint32 n; + + err = mecherrmap_init(&m); + if (err) + return err; + + /* This is *so* gross. + + The RPC code depends on being able to recognize the "wrong + principal" minor status return from the Kerberos mechanism. + But a totally generic enumeration of status codes as they come + up makes that impossible. So "register" that status code + early, and always with the same value. + + Of course, to make things worse, we're treating each mechanism + OID separately, and there are three for Kerberos. */ + { + /* Declare here to avoid including header files not generated + yet. */ + extern const gss_OID_desc *const gss_mech_krb5; + extern const gss_OID_desc *const gss_mech_krb5_old; + extern const gss_OID_desc *const gss_mech_krb5_wrong; + + const OM_uint32 wrong_princ = (OM_uint32) KRB5KRB_AP_WRONG_PRINC; + + n = gssint_mecherrmap_map(wrong_princ, gss_mech_krb5); + if (n <= 0) + return ENOMEM; + n = gssint_mecherrmap_map(wrong_princ, gss_mech_krb5_old); + if (n <= 0) + return ENOMEM; + n = gssint_mecherrmap_map(wrong_princ, gss_mech_krb5_wrong); + if (n <= 0) + return ENOMEM; + } + + return 0; +} + +/* Currently the enumeration template doesn't handle freeing + element storage when destroying the collection. */ +static int free_one(size_t i, struct mecherror value, void *p) +{ + if (value.mech.length && value.mech.elements) + free(value.mech.elements); + return 0; +} + +void gssint_mecherrmap_destroy(void) +{ + mecherrmap_foreach(&m, free_one, NULL); + mecherrmap_destroy(&m); +} + +OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid) +{ + struct mecherror me; + int err, added; + long idx; + + me.code = minor; + me.mech = *oid; + err = mecherrmap_find_or_append(&m, me, &idx, &added); + if (err) { + return 0; + } + return idx+1; +} + +static gss_OID_desc no_oid = { 0, 0 }; +OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode) +{ + return gssint_mecherrmap_map(errcode, &no_oid); +} + +int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, + OM_uint32 *mech_minor) +{ + struct mecherror me; + int err; + long size; + + if (minor == 0) { + return EINVAL; + } + err = mecherrmap_size(&m, &size); + if (err) { + return err; + } + if (minor > size) { + return EINVAL; + } + err = mecherrmap_get(&m, minor-1, &me); + if (err) { + return err; + } + *mech_oid = me.mech; + *mech_minor = me.code; + return 0; +} |