aboutsummaryrefslogtreecommitdiff
path: root/client/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/error.c')
-rw-r--r--client/error.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/client/error.c b/client/error.c
new file mode 100644
index 0000000..e95b284
--- /dev/null
+++ b/client/error.c
@@ -0,0 +1,121 @@
+/* $Id$
+**
+** Error handling for the wallet client.
+**
+** Provides versions of die and warn that take a Kerberos context and a
+** Kerberos error code and append the Kerberos error message to the provided
+** formatted message.
+**
+** Written by Russ Allbery <rra@stanford.edu>
+** Copyright 2006, 2007, 2008
+** Board of Trustees, Leland Stanford Jr. University
+**
+** See LICENSE for licensing terms.
+*/
+
+#include <config.h>
+
+#include <krb5.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <krb5.h>
+#if !defined(HAVE_KRB5_GET_ERROR_MESSAGE) && !defined(HAVE_KRB5_GET_ERR_TEXT)
+# 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
+
+#include <client/internal.h>
+#include <util/util.h>
+
+/* 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";
+
+
+/*
+** 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.
+*/
+static const char *
+get_error(krb5_context ctx, krb5_error_code code)
+{
+ const char *msg = NULL;
+
+#if defined(HAVE_KRB5_GET_ERROR_MESSAGE)
+ msg = krb5_get_error_message(ctx, code);
+#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, &msg);
+#else
+ msg = error_message(code);
+#endif
+ if (msg == NULL)
+ return error_unknown;
+ else
+ return msg;
+}
+
+
+/*
+** Free an error string if necessary.
+*/
+static void
+free_error(krb5_context ctx, const char *msg)
+{
+ if (msg == error_unknown)
+ return;
+#if defined(HAVE_KRB5_FREE_ERROR_MESSAGE)
+ krb5_free_error_message(ctx, msg);
+#elif defined(HAVE_KRB5_SVC_GET_MSG)
+ krb5_free_string((char *) msg);
+#endif
+}
+
+
+/*
+** Report a Kerberos error and exit.
+*/
+void
+die_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
+{
+ const char *k5_msg = NULL;
+ char *message;
+ va_list args;
+
+ k5_msg = get_error(ctx, code);
+ va_start(args, format);
+ if (xasprintf(&message, format, args) < 0)
+ die("internal error: unable to format error message");
+ va_end(args);
+ die("%s: %s\n", message, k5_msg);
+}
+
+
+/*
+** Report a Kerberos error.
+*/
+void
+warn_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
+{
+ const char *k5_msg = NULL;
+ char *message;
+ va_list args;
+
+ k5_msg = get_error(ctx, code);
+ va_start(args, format);
+ if (xasprintf(&message, format, args) < 0)
+ die("internal error: unable to format error message");
+ va_end(args);
+ warn("%s: %s\n", message, k5_msg);
+ free(message);
+ free_error(ctx, k5_msg);
+}