summaryrefslogtreecommitdiffstats
path: root/src/lib/gssapi/krb5/disp_status.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/gssapi/krb5/disp_status.c')
-rw-r--r--src/lib/gssapi/krb5/disp_status.c133
1 files changed, 131 insertions, 2 deletions
diff --git a/src/lib/gssapi/krb5/disp_status.c b/src/lib/gssapi/krb5/disp_status.c
index 1988d50c67..9a0399d78b 100644
--- a/src/lib/gssapi/krb5/disp_status.c
+++ b/src/lib/gssapi/krb5/disp_status.c
@@ -26,6 +26,130 @@
/* XXXX internationalization!! */
+static inline int
+compare_OM_uint32 (OM_uint32 a, OM_uint32 b)
+{
+ if (a < b)
+ return -1;
+ else if (a == b)
+ return 0;
+ else
+ return 1;
+}
+static inline void
+free_string (char *s)
+{
+ free(s);
+}
+#include "error_map.h"
+#include <stdio.h>
+char *get_error_message(OM_uint32 minor_code)
+{
+ gsserrmap *p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
+ char *msg = 0;
+#ifdef DEBUG
+ fprintf(stderr, "%s(%lu, p=%p)", __func__, (unsigned long) minor_code,
+ (void *) p);
+#endif
+ if (p) {
+ char **v = gsserrmap_find(p, minor_code);
+ if (v) {
+ msg = *v;
+#ifdef DEBUG
+ fprintf(stderr, " FOUND!");
+#endif
+ }
+ }
+ if (msg == 0)
+ msg = error_message(minor_code);
+#ifdef DEBUG
+ fprintf(stderr, " -> %p/%s\n", (void *) msg, msg);
+#endif
+ return msg;
+}
+#define save_error_string_nocopy gss_krb5_save_error_string_nocopy
+static int save_error_string_nocopy(OM_uint32 minor_code, char *msg)
+{
+ gsserrmap *p;
+ int ret;
+
+#ifdef DEBUG
+ fprintf(stderr, "%s(%lu, %s)", __func__, (unsigned long) minor_code, msg);
+#endif
+ p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
+ if (!p) {
+ p = malloc(sizeof(*p));
+ if (p == NULL) {
+ ret = 1;
+ goto fail;
+ }
+ if (gsserrmap_init(p) != 0) {
+ free(p);
+ p = NULL;
+ ret = 1;
+ goto fail;
+ }
+ if (k5_setspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE, p) != 0) {
+ gsserrmap_destroy(p);
+ free(p);
+ p = NULL;
+ ret = 1;
+ goto fail;
+ }
+ }
+ ret = gsserrmap_replace_or_insert(p, minor_code, msg);
+fail:
+#ifdef DEBUG
+ fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS");
+#endif
+ return ret;
+}
+void save_error_string(OM_uint32 minor_code, char *msg)
+{
+ char *s = strdup(msg);
+ if (s) {
+ if (save_error_string_nocopy(minor_code, s) != 0)
+ free(s);
+ }
+}
+void save_error_message(OM_uint32 minor_code, 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) {
+ if (save_error_string_nocopy(minor_code, s) != 0)
+ free(s);
+ }
+}
+void krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx)
+{
+ char *s;
+
+#ifdef DEBUG
+ fprintf(stderr, "%s(%lu, ctx=%p)\n", __func__,
+ (unsigned long) minor_code, (void *)ctx);
+#endif
+ s = krb5_get_error_message(ctx, minor_code);
+#ifdef DEBUG
+ fprintf(stderr, "%s(%lu, ctx=%p) saving: %s\n", __func__,
+ (unsigned long) minor_code, (void *)ctx, s);
+#endif
+ save_error_string(minor_code, s);
+ /* The get_error_message call above resets the error message in
+ ctx. Put it back, in case we make this call again *sigh*. */
+ krb5_set_error_message(ctx, minor_code, "%s", s);
+ krb5_free_error_message(ctx, s);
+}
+void krb5_gss_delete_error_info(void *p)
+{
+ gsserrmap_destroy(p);
+}
+
/**/
OM_uint32
@@ -59,8 +183,13 @@ krb5_gss_display_status(minor_status, status_value, status_type,
return(GSS_S_FAILURE);
}
- return(g_display_com_err_status(minor_status, status_value,
- status_string));
+ /* If this fails, there's not much we can do... */
+ if (g_make_string_buffer(krb5_gss_get_error_message(status_value),
+ status_string) != 0)
+ *minor_status = ENOMEM;
+ else
+ *minor_status = 0;
+ return 0;
} else {
*minor_status = 0;
return(GSS_S_BAD_STATUS);