X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=mech_eap%2Fdisplay_status.c;h=8729a96be81e81d19bb3d638664f9344be994fae;hb=refs%2Fheads%2Fddf-name;hp=f931be4e44eeac7a9d29b63c276904d83721bddf;hpb=78fe880838c93aa947babc9ac671c55428f7f5d1;p=moonshot.git diff --git a/mech_eap/display_status.c b/mech_eap/display_status.c index f931be4..8729a96 100644 --- a/mech_eap/display_status.c +++ b/mech_eap/display_status.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, JANET(UK) + * Copyright (c) 2011, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,8 +30,113 @@ * SUCH DAMAGE. */ +/* + * Function for converting mechanism error codes to strings. + */ + #include "gssapiP_eap.h" +static GSSEAP_THREAD_ONCE gssEapStatusInfoKeyOnce = GSSEAP_ONCE_INITIALIZER; +static GSSEAP_THREAD_KEY gssEapStatusInfoKey; + +struct gss_eap_status_info { + OM_uint32 code; + char *message; + struct gss_eap_status_info *next; +}; + +static void +destroyStatusInfo(void *arg) +{ + struct gss_eap_status_info *p = arg, *next; + + for (p = arg; p != NULL; p = next) { + next = p->next; + GSSEAP_FREE(p->message); + GSSEAP_FREE(p); + } +} + +static void +createStatusInfoKey(void) +{ + GSSEAP_KEY_CREATE(&gssEapStatusInfoKey, destroyStatusInfo); +} + +/* + * Associate a message with a mechanism (minor) status code. This function + * takes ownership of the message regardless of success. The message must + * be explicitly cleared, if required, so it is suggested that a specific + * minor code is either always or never associated with a message, to avoid + * dangling (and potentially confusing) error messages. + */ +static void +saveStatusInfoNoCopy(OM_uint32 minor, char *message) +{ + struct gss_eap_status_info **next = NULL, *p; + + GSSEAP_ONCE(&gssEapStatusInfoKeyOnce, createStatusInfoKey); + + p = GSSEAP_GETSPECIFIC(gssEapStatusInfoKey); + for (; p != NULL; p = p->next) { + if (p->code == minor) { + /* Set message in-place */ + if (p->message != NULL) + GSSEAP_FREE(p->message); + p->message = message; + return; + } + next = &p->next; + } + + p = GSSEAP_CALLOC(1, sizeof(*p)); + if (p == NULL) { + if (message != NULL) + GSSEAP_FREE(message); + return; + } + + p->code = minor; + p->message = message; + + if (next != NULL) + *next = p; + else + GSSEAP_SETSPECIFIC(gssEapStatusInfoKey, p); +} + +static const char * +getStatusInfo(OM_uint32 minor) +{ + struct gss_eap_status_info *p; + + GSSEAP_ONCE(&gssEapStatusInfoKeyOnce, createStatusInfoKey); + + for (p = GSSEAP_GETSPECIFIC(gssEapStatusInfoKey); + p != NULL; + p = p->next) { + if (p->code == minor) + return p->message; + } + + return NULL; +} + +void +gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...) +{ + char *s; + int n; + va_list ap; + + va_start(ap, format); + n = vasprintf(&s, format, ap); + va_end(ap); + + if (n >= 0) + saveStatusInfoNoCopy(minor, s); +} + OM_uint32 gss_display_status(OM_uint32 *minor, OM_uint32 status_value, @@ -41,31 +146,41 @@ gss_display_status(OM_uint32 *minor, gss_buffer_t status_string) { OM_uint32 major; - krb5_context krbContext; + krb5_context krbContext = NULL; const char *errMsg; status_string->length = 0; status_string->value = NULL; if (!gssEapIsMechanismOid(mech_type)) { + *minor = GSSEAP_WRONG_MECH; return GSS_S_BAD_MECH; } - if (status_type != GSS_C_MECH_CODE) { + if (status_type != GSS_C_MECH_CODE || + *message_context != 0) { /* we rely on the mechglue for GSS_C_GSS_CODE */ + *minor = 0; return GSS_S_BAD_STATUS; } - /* XXX we need to support RADIUS codes too? */ - GSSEAP_KRB_INIT(&krbContext); + errMsg = getStatusInfo(status_value); + if (errMsg == NULL) { + GSSEAP_KRB_INIT(&krbContext); + + /* Try the com_err message */ + errMsg = krb5_get_error_message(krbContext, status_value); + } - errMsg = krb5_get_error_message(krbContext, status_value); if (errMsg != NULL) { major = makeStringBuffer(minor, errMsg, status_string); - krb5_free_error_message(krbContext, errMsg); } else { major = GSS_S_COMPLETE; + *minor = 0; } - return GSS_S_COMPLETE; + if (krbContext != NULL) + krb5_free_error_message(krbContext, errMsg); + + return major; }