err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free);
if (err)
return err;
+ err = k5_key_register(K5_KEY_GSS_KRB5_ERROR_MESSAGE,
+ krb5_gss_delete_error_info);
+ if (err)
+ return err;
#ifndef _WIN32
err = k5_mutex_finish_init(&kg_kdc_flag_mutex);
if (err)
all-unix:: $(SRCS) $(HDRS) $(GSSAPI_KRB5_HDR) includes
all-unix:: all-libobjs
+error_map.h: $(SRCTOP)/util/gen-map.pl Makefile
+ $(PERL) -I$(SRCTOP)/util $(SRCTOP)/util/gen-map.pl -oerror_map.new \
+ NAME=gsserrmap \
+ KEY=OM_uint32 \
+ VALUE="char *" \
+ COMPARE=compare_OM_uint32 \
+ FREEVALUE=free_string
+ $(MV) error_map.new error_map.h
+
clean-unix::
$(RM) $(BUILDTOP)/include/gssapi/gssapi_krb5.h
- -$(RM) gssapi_krb5.h
+ -$(RM) gssapi_krb5.h error_map.h
clean-unix:: clean-libobjs
$(RM) $(ETHDRS) $(ETSRCS)
$(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
$(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_generic.h \
$(srcdir)/../gss_libinit.h ../generic/gssapi_err_generic.h \
- disp_status.c gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h
+ disp_status.c error_map.h gssapiP_krb5.h gssapi_err_krb5.h \
+ gssapi_krb5.h
duplicate_name.so duplicate_name.po $(OUTPRE)duplicate_name.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
/*
- * Copyright 2000, 2004 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2004, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
*/
/*SUPPRESS 29*/
if (*context_handle != GSS_C_NO_CONTEXT) {
- *minor_status = 0;
+ *minor_status = EINVAL;
+ save_error_string(EINVAL, "accept_sec_context called with existing context handle");
krb5_free_context(context);
return(GSS_S_FAILURE);
}
if ((code = krb5_auth_con_init(context, &auth_context))) {
major_status = GSS_S_FAILURE;
+ save_error_info(code, context);
goto fail;
}
if (cred->rcache) {
if (!verifier_cred_handle && cred_handle) {
krb5_gss_release_cred(minor_status, &cred_handle);
}
+ if (major_status && *minor_status && context)
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return (major_status);
}
/*
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
OM_uint32 KRB5_CALLCONV
krb5_gss_register_acceptor_identity(const char *keytab)
{
- size_t len;
char *new, *old;
int err;
if (keytab == NULL)
return GSS_S_FAILURE;
- len = strlen(keytab);
- new = malloc(len + 1);
+ new = strdup(keytab);
if (new == NULL)
return GSS_S_FAILURE;
- strcpy(new, keytab);
err = k5_mutex_lock(&gssint_krb5_keytab_lock);
if (err) {
princ = (krb5_principal) desired_name;
if ((code = krb5_kt_get_entry(context, kt, princ, 0, 0, &entry))) {
(void) krb5_kt_close(context, kt);
- if (code == KRB5_KT_NOTFOUND)
- *minor_status = KG_KEYTAB_NOMATCH;
- else
+ if (code == KRB5_KT_NOTFOUND) {
+ char *errstr = krb5_get_error_message(context, code);
+ krb5_set_error_message(context, KG_KEYTAB_NOMATCH, "%s", errstr);
+ krb5_free_error_message(context, errstr);
+ *minor_status = KG_KEYTAB_NOMATCH;
+ } else
*minor_status = code;
return(GSS_S_CRED_UNAVAIL);
}
k5_mutex_destroy(&cred->lock);
xfree(cred);
/* minor_status set by acquire_accept_cred() */
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(ret);
}
k5_mutex_destroy(&cred->lock);
xfree(cred);
/* minor_status set by acquire_init_cred() */
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(ret);
}
k5_mutex_destroy(&cred->lock);
xfree(cred);
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
k5_mutex_destroy(&cred->lock);
xfree(cred);
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
k5_mutex_destroy(&cred->lock);
xfree(cred);
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ save_error_string(*minor_status, "error saving credentials");
krb5_free_context(context);
return(GSS_S_FAILURE);
}
/*
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
major_status = krb5_gss_validate_cred_1(minor_status, input_cred_handle,
context);
if (GSS_ERROR(major_status)) {
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return major_status;
}
}
if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) {
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return GSS_S_FAILURE;
}
xfree(new_cred);
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
xfree(new_cred);
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
xfree(new_cred);
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
krb5_free_principal(context, new_cred->princ);
xfree(new_cred);
- krb5_free_context(context);
*minor_status = code;
+ save_error_info(*minor_status, context);
+ krb5_free_context(context);
return(GSS_S_FAILURE);
}
} else {
if (new_cred->princ)
krb5_free_principal(context, new_cred->princ);
xfree(new_cred);
- krb5_free_context(context);
*minor_status = code;
+ save_error_info(*minor_status, context);
+ krb5_free_context(context);
return(GSS_S_FAILURE);
}
} else {
if ((code = krb5_timeofday(ctx->k5_context, &now))) {
*minor_status = code;
+ save_error_info(*minor_status, ctx->k5_context);
return(GSS_S_FAILURE);
}
if (code) {
k5_mutex_unlock(&k5creds->lock);
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
code = krb5_cc_store_cred(context, out_ccache, &creds);
krb5_cc_end_seq_get(context, k5creds->ccache, &cursor);
k5_mutex_unlock(&k5creds->lock);
+ *minor_status = code;
+ if (code)
+ save_error_info(*minor_status, context);
krb5_free_context(context);
- if (code) {
- *minor_status = code;
- return(GSS_S_FAILURE);
- } else {
- *minor_status = 0;
- return(GSS_S_COMPLETE);
- }
+ return code ? GSS_S_FAILURE : GSS_S_COMPLETE;
}
if ((major = kg_seal(minor_status, *context_handle, 0,
GSS_C_QOP_DEFAULT,
- &empty, NULL, output_token, KG_TOK_DEL_CTX)))
- return(major);
+ &empty, NULL, output_token, KG_TOK_DEL_CTX))) {
+ save_error_info(*minor_status, context);
+ return(major);
+ }
}
/* invalidate the context handle */
if ((code = krb5_unparse_name(context,
(krb5_principal) input_name, &str))) {
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
/* 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
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);
/*
* lib/gssapi/krb5/duplicate_name.c
*
- * Copyright 1997 by the Massachusetts Institute of Technology.
+ * Copyright 1997,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
princ = (krb5_principal)input_name;
if ((code = krb5_copy_principal(context, princ, &outprinc))) {
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
/*
* lib/gssapi/krb5/export_name.c
*
- * Copyright 1997 by the Massachusetts Institute of Technology.
+ * Copyright 1997, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
&str))) {
if (minor_status)
*minor_status = code;
+ save_error_info(code, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
/*
* lib/gssapi/krb5/export_sec_context.c
*
- * Copyright 1995 by the Massachusetts Institute of Technology.
+ * Copyright 1995, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
gss_ctx_id_t *context_handle;
gss_buffer_t interprocess_token;
{
- krb5_context context;
+ krb5_context context = NULL;
krb5_error_code kret;
OM_uint32 retval;
size_t bufsize, blen;
return (GSS_S_COMPLETE);
error_out:
+ if (retval != GSS_S_COMPLETE)
+ if (kret != 0 && context != 0)
+ save_error_info(kret, context);
if (obuffer && bufsize) {
memset(obuffer, 0, bufsize);
xfree(obuffer);
/*
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
krb5_error_code krb5_gss_use_kdc_context(void);
+/* For error message handling. */
+/* Returns a shared string, not a private copy! */
+extern char *
+krb5_gss_get_error_message(OM_uint32 minor_code);
+extern void
+krb5_gss_save_error_string(OM_uint32 minor_code, char *msg);
+extern void
+krb5_gss_save_error_message(OM_uint32 minor_code, const char *format, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+extern void
+krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx);
+#define get_error_message krb5_gss_get_error_message
+#define save_error_string krb5_gss_save_error_string
+#define save_error_message krb5_gss_save_error_message
+#define save_error_info krb5_gss_save_error_info
+extern void krb5_gss_delete_error_info(void *p);
+
#endif /* _GSSAPIP_KRB5_H_ */
*out_caller_provided_name =
(k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL);
}
-
+
*minor_status = 0;
return GSS_S_COMPLETE;
}
err = errno;
}
}
+ if (err && context)
+ save_error_info(err, context);
if (context)
krb5_free_context(context);
}
if ((code = krb5_copy_principal(context, input, &princ))) {
*minor_status = code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
if (code) {
*minor_status = (OM_uint32) code;
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_BAD_NAME);
}
/*
* lib/gssapi/krb5/import_sec_context.c
*
- * Copyright 1995,2004 by the Massachusetts Institute of Technology.
+ * Copyright 1995,2004,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
if (kret) {
krb5_free_context(context);
*minor_status = kret;
+ save_error_info(*minor_status, context);
return GSS_S_FAILURE;
}
krb5_free_context(context);
if (kret) {
*minor_status = (OM_uint32) kret;
+ save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
/*
- * Copyright 2000,2002, 2003 by the Massachusetts Institute of Technology.
+ * Copyright 2000,2002, 2003, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
*minor_status = kerr;
return GSS_S_FAILURE;
}
- if (GSS_ERROR(kg_sync_ccache_name(context, minor_status)))
+ if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) {
+ save_error_info(*minor_status, context);
+ krb5_free_context(context);
return GSS_S_FAILURE;
+ }
} else {
context = ((krb5_gss_ctx_id_rec *)*context_handle)->k5_context;
}
if (! kg_validate_name(target_name)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ save_error_info(*minor_status, context);
if (*context_handle == GSS_C_NO_CONTEXT)
krb5_free_context(context);
return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
} else {
major_status = krb5_gss_validate_cred(minor_status, claimant_cred_handle);
if (GSS_ERROR(major_status)) {
+ save_error_info(*minor_status, context);
if (*context_handle == GSS_C_NO_CONTEXT)
krb5_free_context(context);
return(major_status);
output_token, ret_flags, time_rec,
context, default_mech);
k5_mutex_unlock(&cred->lock);
- if (*context_handle == GSS_C_NO_CONTEXT)
+ if (*context_handle == GSS_C_NO_CONTEXT) {
+ save_error_info (*minor_status, context);
krb5_free_context(context);
- else
+ } else
((krb5_gss_ctx_id_rec *) *context_handle)->k5_context = context;
} else {
/* mutual_auth doesn't care about the credentials */
if ((code = krb5_timeofday(context, &now))) {
*minor_status = code;
+ save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
ctx->initiate?ctx->here:ctx->there,
&init))) {
*minor_status = code;
+ save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
if (! kg_save_name((gss_name_t) init)) {
&accept))) {
if (init) krb5_free_principal(context, init);
*minor_status = code;
+ save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
if (! kg_save_name((gss_name_t) accept)) {
/*
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
(code = krb5_copy_principal(context, cred->princ, &ret_name))) {
k5_mutex_unlock(&cred->lock);
*minor_status = code;
+ save_error_info(*minor_status, context);
ret = GSS_S_FAILURE;
goto fail;
}
context = ctx->k5_context;
if ((code = krb5_timeofday(context, &now))) {
*minor_status = code;
+ save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
if (code) {
*minor_status = code;
+ save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
/*
* lib/gssapi/krb5/k5sealv3.c
*
- * Copyright 2003,2004 by the Massachusetts Institute of Technology.
+ * Copyright 2003,2004,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
if (err) {
error:
*minor_status = err;
+ save_error_info(*minor_status, context);
return GSS_S_BAD_SIG; /* XXX */
}
if (!valid) {
/*
- * Copyright 2001 by the Massachusetts Institute of Technology.
+ * Copyright 2001, 2007 by the Massachusetts Institute of Technology.
* Copyright 1993 by OpenVision Technologies, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
unsigned int bodysize;
int err;
int toktype2;
+ OM_uint32 ret;
/* validate the context handle */
if (! kg_validate_ctx_id(context_handle)) {
}
if (ctx->proto == 0)
- return kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize,
- message_buffer, conf_state, qop_state,
- toktype);
+ ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize,
+ message_buffer, conf_state, qop_state,
+ toktype);
else
- return gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
- ptr, bodysize, message_buffer,
- conf_state, qop_state, toktype);
+ ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
+ ptr, bodysize, message_buffer,
+ conf_state, qop_state, toktype);
+ if (ret != 0)
+ save_error_info (*minor_status, ctx->k5_context);
+ return ret;
}
free(cred->req_enctypes);
xfree(cred);
- krb5_free_context(context);
*cred_handle = NULL;
if (code3)
*minor_status = code3;
+ if (*minor_status)
+ save_error_info(*minor_status, context);
+ krb5_free_context(context);
return(*minor_status?GSS_S_FAILURE:GSS_S_COMPLETE);
}
/*
- * Copyright 1997 by Massachusetts Institute of Technology
+ * Copyright 1997, 2007 by Massachusetts Institute of Technology
* All Rights Reserved.
*
* Export of this software from the United States of America may
k5_mutex_assert_locked(&cred->lock);
k5_mutex_unlock(&cred->lock);
}
+ save_error_info(*minor_status, context);
krb5_free_context(context);
return maj;
}