X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=display_status.c;h=44b5390c5a11d77c6fba88af4f76cb95c3ef6f35;hb=15c93f06ee6ddefa7e7b095351f6e66698c7cc9e;hp=f931be4e44eeac7a9d29b63c276904d83721bddf;hpb=c3ff83a02d37820b9c70cc3746c72a900dfd85ac;p=mech_eap.git diff --git a/display_status.c b/display_status.c index f931be4..44b5390 100644 --- a/display_status.c +++ b/display_status.c @@ -32,6 +32,96 @@ #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); +} + +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) { + p->message = message; + return; + } + next = &p->next; + } + + p = GSSEAP_CALLOC(1, sizeof(*p)); + if (p == NULL) { + GSSEAP_FREE(message); + return; + } + + p->code = minor; + p->message = message; + + if (p != 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, @@ -40,8 +130,8 @@ gss_display_status(OM_uint32 *minor, OM_uint32 *message_context, gss_buffer_t status_string) { - OM_uint32 major; - krb5_context krbContext; + OM_uint32 major = GSS_S_COMPLETE; + krb5_context krbContext = NULL; const char *errMsg; status_string->length = 0; @@ -56,16 +146,18 @@ gss_display_status(OM_uint32 *minor, 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); - errMsg = krb5_get_error_message(krbContext, status_value); - if (errMsg != NULL) { + errMsg = krb5_get_error_message(krbContext, status_value); + } + + if (errMsg != NULL) major = makeStringBuffer(minor, errMsg, status_string); + + if (krbContext != NULL) krb5_free_error_message(krbContext, errMsg); - } else { - major = GSS_S_COMPLETE; - } - return GSS_S_COMPLETE; + return major; }