summaryrefslogtreecommitdiff
path: root/portable
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2010-02-09 16:00:04 -0800
committerRuss Allbery <rra@stanford.edu>2010-02-09 16:00:04 -0800
commitd05f66dbff10b525d37f60ee01d5b9f94bf5192e (patch)
tree36657983c619cfb7260781b2607ead4afc3ad866 /portable
parentccf1cd7efa90bdcbe834e0d4ca144289cca97fd7 (diff)
Update util code and import Kerberos portability glue
Use the Kerberos portability layer from rra-c-util 3.0 and avoid Kerberos API calls deprecated on Heimdal. Break util/util.h into separate header files and update all source files accordingly. The test suite is not yet updated. That will come in subsequent commits.
Diffstat (limited to 'portable')
-rw-r--r--portable/krb5-extra.c108
-rw-r--r--portable/krb5.h74
2 files changed, 182 insertions, 0 deletions
diff --git a/portable/krb5-extra.c b/portable/krb5-extra.c
new file mode 100644
index 0000000..09a717b
--- /dev/null
+++ b/portable/krb5-extra.c
@@ -0,0 +1,108 @@
+/*
+ * Portability glue functions for Kerberos.
+ *
+ * This file provides definitions of the interfaces that portable/krb5.h
+ * ensures exist if the function wasn't available in the Kerberos libraries.
+ * Everything in this file will be protected by #ifndef. If the native
+ * Kerberos libraries are fully capable, this file will be skipped.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * This work is hereby placed in the public domain by its author.
+ */
+
+#include <config.h>
+#include <portable/krb5.h>
+#include <portable/system.h>
+
+#include <errno.h>
+
+/* Figure out what header files to include for error reporting. */
+#if !defined(HAVE_KRB5_GET_ERROR_MESSAGE) && !defined(HAVE_KRB5_GET_ERR_TEXT)
+# if !defined(HAVE_KRB5_GET_ERROR_STRING)
+# if defined(HAVE_IBM_SVC_KRB5_SVC_H)
+# include <ibm_svc/krb5_svc.h>
+# elif defined(HAVE_ET_COM_ERR_H)
+# include <et/com_err.h>
+# else
+# include <com_err.h>
+# endif
+# endif
+#endif
+
+/* Used for unused parameters to silence gcc warnings. */
+#define UNUSED __attribute__((__unused__))
+
+/*
+ * This string is returned for unknown error messages. We use a static
+ * variable so that we can be sure not to free it.
+ */
+static const char error_unknown[] = "unknown error";
+
+
+#ifndef HAVE_KRB5_GET_ERROR_MESSAGE
+/*
+ * Given a Kerberos error code, return the corresponding error. Prefer the
+ * Kerberos interface if available since it will provide context-specific
+ * error information, whereas the error_message() call will only provide a
+ * fixed message.
+ */
+const char *
+krb5_get_error_message(krb5_context ctx UNUSED, krb5_error_code code UNUSED)
+{
+ const char *msg = NULL;
+
+# if defined(HAVE_KRB5_GET_ERROR_STRING)
+ msg = krb5_get_error_string(ctx);
+# elif defined(HAVE_KRB5_GET_ERR_TEXT)
+ msg = krb5_get_err_text(ctx, code);
+# elif defined(HAVE_KRB5_SVC_GET_MSG)
+ krb5_svc_get_msg(code, (char **) &msg);
+# else
+ msg = error_message(code);
+# endif
+ if (msg == NULL)
+ return error_unknown;
+ else
+ return msg;
+}
+#endif /* !HAVE_KRB5_GET_ERROR_MESSAGE */
+
+
+#ifndef HAVE_KRB5_FREE_ERROR_MESSAGE
+/*
+ * Free an error string if necessary. If we returned a static string, make
+ * sure we don't free it.
+ *
+ * This code assumes that the set of implementations that have
+ * krb5_free_error_message is a subset of those with krb5_get_error_message.
+ * If this assumption ever breaks, we may call the wrong free function.
+ */
+static void
+krb5_free_error_message(krb5_context ctx UNUSED, const char *msg)
+{
+ if (msg == error_unknown)
+ return;
+# if defined(HAVE_KRB5_GET_ERROR_STRING)
+ krb5_free_error_string(ctx, (char *) msg);
+# elif defined(HAVE_KRB5_SVC_GET_MSG)
+ krb5_free_string(ctx, (char *) msg);
+# endif
+}
+#endif /* !HAVE_KRB5_FREE_ERROR_MESSAGE */
+
+
+#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+/*
+ * Allocate and initialize a krb5_get_init_creds_opt struct. This code
+ * assumes that an all-zero bit pattern will create a NULL pointer.
+ */
+krb5_error_code
+krb5_get_init_creds_opt_alloc(krb5_context ctx, krb5_get_init_creds_opt **opts)
+{
+ *opts = calloc(1, sizeof(krb5_get_init_creds_opt));
+ if (*opts == NULL)
+ return errno;
+ krb5_get_init_creds_opt_init(*opts);
+ return 0;
+}
+#endif /* !HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC */
diff --git a/portable/krb5.h b/portable/krb5.h
new file mode 100644
index 0000000..117f5ce
--- /dev/null
+++ b/portable/krb5.h
@@ -0,0 +1,74 @@
+/*
+ * Portability wrapper around krb5.h.
+ *
+ * This header includes krb5.h and then adjusts for various portability
+ * issues, primarily between MIT Kerberos and Heimdal, so that code can be
+ * written to a consistent API.
+ *
+ * Unfortunately, due to the nature of the differences between MIT Kerberos
+ * and Heimdal, it's not possible to write code to either one of the APIs and
+ * adjust for the other one. In general, this header tries to make available
+ * the Heimdal API and fix it for MIT Kerberos, but there are places where MIT
+ * Kerberos requires a more specific call. For those cases, it provides the
+ * most specific interface.
+ *
+ * For example, MIT Kerberos has krb5_free_unparsed_name() whereas Heimdal
+ * prefers the generic krb5_xfree(). In this case, this header provides
+ * krb5_free_unparsed_name() for both APIs since it's the most specific call.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ * This work is hereby placed in the public domain by its author.
+ */
+
+#ifndef PORTABLE_KRB5_H
+#define PORTABLE_KRB5_H 1
+
+#include <config.h>
+#include <portable/macros.h>
+
+#include <krb5.h>
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all portability functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * krb5_{get,free}_error_message are the preferred APIs for both current MIT
+ * and current Heimdal, but there are tons of older APIs we may have to fall
+ * back on for earlier versions.
+ *
+ * This function should be called immediately after the corresponding error
+ * without any intervening Kerberos calls. Otherwise, the correct error
+ * message and supporting information may not be returned.
+ */
+#ifndef HAVE_KRB5_GET_ERROR_MESSAGE
+const char *krb5_get_error_message(krb5_context, krb5_error_code);
+#endif
+#ifndef HAVE_KRB5_FREE_ERROR_MESSAGE
+void krb5_free_error_message(krb5_context, const char *);
+#endif
+
+/*
+ * Both current MIT and current Heimdal prefer _opt_alloc, but older versions
+ * of both require allocating your own struct and calling _opt_init.
+ */
+#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context,
+ krb5_get_init_creds_opt **);
+#endif
+
+/* Heimdal-specific. */
+#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS
+#define krb5_get_init_creds_opt_set_default_flags(c, p, r, o) /* empty */
+#endif
+
+/* Heimdal: krb5_kt_free_entry, MIT: krb5_free_keytab_entry_contents. */
+#ifndef HAVE_KRB5_KT_FREE_ENTRY
+# define krb5_kt_free_entry(c, e) krb5_free_keytab_entry_contents((c), (e))
+#endif
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+#endif /* !PORTABLE_KRB5_H */