summaryrefslogtreecommitdiffstats
path: root/src/lib/gssapi/krb5/disp_status.c
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2007-07-04 05:46:24 +0000
committerKen Raeburn <raeburn@mit.edu>2007-07-04 05:46:24 +0000
commitfcdd2de143971b0f020531479ad18f57874aef30 (patch)
tree8bec355041d9241b90822a13548ca2ec45a9a884 /src/lib/gssapi/krb5/disp_status.c
parente0845c95210ca7cf4a03be23b034a2f29fc078c6 (diff)
downloadkrb5-fcdd2de143971b0f020531479ad18f57874aef30.tar.gz
krb5-fcdd2de143971b0f020531479ad18f57874aef30.tar.xz
krb5-fcdd2de143971b0f020531479ad18f57874aef30.zip
gss krb5 mech enhanced error messages
Save detailed error messages (usually from the krb5 library) in per-thread storage, mapping each error code to the most recently produced message for it. Return the message from display_status. Currently not implemented for a few cases where the krb5 mechanism returns a minor status code of 0, or another value different from the libkrb5 error code. Other functions are available to store a generic string or formatted message, but aren't used much at present. Tested with these errors in context establishment: * missing ccache (libkrb5 shows pathname if FILE: type) * missing keytab (libkrb5 shows pathname if FILE: type) * server principal unknown (libkrb5 shows server principal) ticket: new git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19672 dc483132-0cff-0310-8789-dd5450dbe970
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);