]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Initial enhanced error message support, similar to what I sent to
authorKen Raeburn <raeburn@mit.edu>
Sun, 26 Mar 2006 20:55:59 +0000 (20:55 +0000)
committerKen Raeburn <raeburn@mit.edu>
Sun, 26 Mar 2006 20:55:59 +0000 (20:55 +0000)
krbdev except for some function renaming (krb5_free_error was already
in use, so added _message to everything), and the context is allowed
to be NULL (in which case we fall back to error_message() and storing
no strings) to simplify some code.

Low-level routines in the support library, using a private data
structure; higher-level routines in libkrb5, using a krb5_context.

Added error info strings to the KRB_ERR_GENERIC case in gc_via_tkt.c
and the python sample service location plugin.  Added code to kinit
and kvno to look up and display the strings.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17776 dc483132-0cff-0310-8789-dd5450dbe970

23 files changed:
src/clients/kinit/ChangeLog
src/clients/kinit/kinit.c
src/clients/kvno/ChangeLog
src/clients/kvno/kvno.c
src/include/ChangeLog
src/include/k5-err.h [new file with mode: 0644]
src/include/k5-int.h
src/include/krb5.hin
src/lib/krb5/ChangeLog
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/Makefile.in
src/lib/krb5/krb/gc_via_tkt.c
src/lib/krb5/krb/kerrs.c [new file with mode: 0644]
src/lib/krb5/krb5_libinit.c
src/lib/krb5/libkrb5.exports
src/plugins/locate/python/ChangeLog
src/plugins/locate/python/Makefile.in
src/plugins/locate/python/py-locate.c
src/util/support/ChangeLog
src/util/support/Makefile.in
src/util/support/errors.c [new file with mode: 0644]
src/util/support/libkrb5support.exports
src/util/support/threads.c

index 63d53ffa947f822814a4f5cf7f1c7bacc2da9613..6b97d7a2b8a9a88de5b8899fc5a7a77194275b05 100644 (file)
@@ -1,3 +1,11 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * kinit.c (extended_com_err_fn): New function.
+       (errctx): New variable.
+       (k5_begin): Set errctx.
+       (k5_end): Clear it.
+       (main): Call set_com_err_hook.
+
 2004-07-01  Ken Raeburn  <raeburn@mit.edu>
 
        * kinit.c (k5_kinit): Don't free addresses after calling
index 6ffebadd43e899a994a5c5cf64e23eeb7a2f624a..8160822dae407f3571d245964bdfbb700c8ab66e 100644 (file)
@@ -268,6 +268,18 @@ fprintf(stderr, USAGE_OPT_FMT, indent, col1)
     exit(2);
 }
 
+static krb5_context errctx;
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+                                const char *fmt, va_list args)
+{
+    const char *emsg;
+    emsg = krb5_get_error_message (errctx, code);
+    fprintf (stderr, "%s: %s ", myprog, emsg);
+    krb5_free_error_message (errctx, emsg);
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
 static char *
 parse_options(argc, argv, opts, progname)
     int argc;
@@ -494,6 +506,7 @@ struct k4_data* k4;
        com_err(progname, code, "while initializing Kerberos 5 library");
        return 0;
     }
+    errctx = k5->ctx;
     if (opts->k5_cache_name)
     {
        code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
@@ -591,6 +604,7 @@ k5_end(k5)
        krb5_cc_close(k5->ctx, k5->cc);
     if (k5->ctx)
        krb5_free_context(k5->ctx);
+    errctx = NULL;
     memset(k5, 0, sizeof(*k5));
 }
 
@@ -1098,6 +1112,8 @@ main(argc, argv)
     memset(&k5, 0, sizeof(k5));
     memset(&k4, 0, sizeof(k4));
 
+    set_com_err_hook (extended_com_err_fn);
+
     parse_options(argc, argv, &opts, progname);
 
     got_k5 = k5_begin(&opts, &k5, &k4);
index 0a81427ff3f500924e86900cc757fe04a503d79e..0982dd036b1a724726e4141c3ce10e914654446a 100644 (file)
@@ -1,3 +1,11 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * kvno.c: Include com_err.h.
+       (extended_com_err_fn): New function.
+       (context): New variable.
+       (main): Call set_com_err_hook.
+       (do_v5_kvno): Call com_err instead of fprintf+error_message.
+
 2004-08-31  Tom Yu  <tlyu@mit.edu>
 
        * kvno.M: Update usage.
index c860eb7d427d5654eaccc90d12e5d00d61c74a9e..4accdb4a94be2d132dd29189d6c26943ca4acad5 100644 (file)
@@ -55,12 +55,18 @@ static void do_v4_kvno (int argc, char *argv[]);
 static void do_v5_kvno (int argc, char *argv[], 
                         char *ccachestr, char *etypestr);
 
+#include <com_err.h>
+static void extended_com_err_fn (const char *, errcode_t, const char *,
+                                va_list);
+
 int main(int argc, char *argv[])
 {
     int option;
     char *etypestr = 0, *ccachestr = 0;
     int v4 = 0;
 
+    set_com_err_hook (extended_com_err_fn);
+
     prog = strrchr(argv[0], '/');
     prog = prog ? (prog + 1) : argv[0];
 
@@ -149,10 +155,21 @@ static void do_v4_kvno (int count, char *names[])
 }
 
 #include <krb5.h>
+static krb5_context context;
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+                                const char *fmt, va_list args)
+{
+    const char *emsg;
+    emsg = krb5_get_error_message (context, code);
+    fprintf (stderr, "%s: %s ", myprog, emsg);
+    krb5_free_error_message (context, emsg);
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+}
+
 static void do_v5_kvno (int count, char *names[], 
                         char * ccachestr, char *etypestr)
 {
-    krb5_context context;
     krb5_error_code ret;
     int i, errors;
     krb5_enctype etype;
@@ -203,16 +220,16 @@ static void do_v5_kvno (int count, char *names[],
        ret = krb5_parse_name(context, names[i], &in_creds.server);
        if (ret) {
            if (!quiet)
-               fprintf(stderr, "%s: %s while parsing principal name\n",
-                       names[i], error_message(ret));
+               com_err(prog, ret, "while parsing principal name %s", names[i]);
            errors++;
            continue;
        }
 
        ret = krb5_unparse_name(context, in_creds.server, &princ);
        if (ret) {
-           fprintf(stderr, "%s: %s while printing principal name\n",
-                   names[i], error_message(ret));
+           com_err(prog, ret,
+                   "while formatting parsed principal name for '%s'",
+                   names[i]);
            errors++;
            continue;
        }
@@ -224,8 +241,7 @@ static void do_v5_kvno (int count, char *names[],
        krb5_free_principal(context, in_creds.server);
 
        if (ret) {
-           fprintf(stderr, "%s: %s while getting credentials\n",
-                   princ, error_message(ret));
+           com_err(prog, ret, "while getting credentials for %s", princ);
 
            krb5_free_unparsed_name(context, princ);
 
@@ -236,9 +252,7 @@ static void do_v5_kvno (int count, char *names[],
        /* we need a native ticket */
        ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
        if (ret) {
-           fprintf(stderr, "%s: %s while decoding ticket\n",
-                   princ, error_message(ret));
-
+           com_err(prog, ret, "while decoding ticket for %s", princ);
            krb5_free_creds(context, out_creds);
            krb5_free_unparsed_name(context, princ);
 
index cf62126c9e884737c88ad0cab59f4cda0921a021..b5c4654a4f5a61b16d297ee7e457222ad50c4358 100644 (file)
@@ -1,3 +1,12 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * krb5.hin (krb5_set_error_message, krb5_vset_error_message,
+       krb5_get_error_message, krb5_free_error_message,
+       krb5_clear_error_message): Declare.
+       * k5-err.h: New file.
+       * k5-int.h: Include it.
+       (struct _krb5_context): Add new field ERR.
+
 2006-03-11  Ken Raeburn  <raeburn@mit.edu>
 
        * adm.h, adm_defs.h, adm_proto.h, copyright.h, kdb.h, kdb_dbc.h,
diff --git a/src/include/k5-err.h b/src/include/k5-err.h
new file mode 100644 (file)
index 0000000..0ac2080
--- /dev/null
@@ -0,0 +1,23 @@
+#define _(X) (X)
+#define KRB5_CALLCONV
+struct errinfo {
+    long code;
+    const char *msg;
+    char scratch_buf[1024];
+};
+
+void
+krb5int_set_error (struct errinfo *ep,
+                  long code,
+                  const char *fmt, ...);
+void
+krb5int_vset_error (struct errinfo *ep, long code,
+                   const char *fmt, va_list args);
+char *
+krb5int_get_error (struct errinfo *ep, long code);
+void
+krb5int_free_error (struct errinfo *ep, char *msg);
+void
+krb5int_clear_error (struct errinfo *ep);
+void
+krb5int_set_error_info_callout_fn (const char *(KRB5_CALLCONV *f)(long));
index ff8b342057ef361c90372f78288422468e173a2e..4b455f9fbe5b909116b3048099bf6b8466c8a9dd 100644 (file)
@@ -169,6 +169,9 @@ typedef INT64_TYPE krb5_int64;
 /* Get mutex support; currently used only for the replay cache.  */
 #include "k5-thread.h"
 
+/* Get error info support.  */
+#include "k5-err.h"
+
 /* krb5/krb5.h includes many other .h files in the krb5 subdirectory.
    The ones that it doesn't include, we include below.  */
 
@@ -1067,6 +1070,9 @@ struct _krb5_context {
     struct plugin_dir_handle libkrb5_plugins;
     struct krb5plugin_service_locate_ftable *vtbl;
     void (**locate_fptrs)(void);
+
+    /* error detail info */
+    struct errinfo err;
 };
 
 /* could be used in a table to find an etype and initialize a block */
index eaaedec8f154e12feb77b1609bc94a115405f45c..d786e6770c3a7e1b23e445b4d7bd001b20d4b6dd 100644 (file)
@@ -2536,6 +2536,21 @@ typedef krb5_int32 krb5_prompt_type;
 krb5_prompt_type* KRB5_CALLCONV krb5_get_prompt_types
        (krb5_context context);
 
+/* Error reporting */
+void
+krb5_set_error_message (krb5_context, krb5_error_code, const char *, ...);
+#ifdef va_start
+void
+krb5_vset_error_message (krb5_context, krb5_error_code, const char *, va_list);
+#endif
+char *
+krb5_get_error_message (krb5_context, krb5_error_code);
+void
+krb5_free_error_message (krb5_context, char *);
+void
+krb5_clear_error_message (krb5_context);
+
+
 #if TARGET_OS_MAC
 #    pragma options align=reset
 #endif
index f7849aea51652e9feb5d9d78b3fff30144e104dc..6cfd3e644c4d2a340ed82906f8d278233ff5495f 100644 (file)
@@ -1,3 +1,10 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * krb5_libinit.c (krb5int_lib_init): Register callback function
+       for lower-level error-info support routines.
+       (krb5int_lib_fini): Clear the callback function.
+       * libkrb5.exports: Export new error-message functions.
+
 2005-11-14  Jeffrey Altman <jaltman@mit.edu>
 
        * krb5_libinit.c: include k5-int.h instead of krb5.h
index ba3211c4cfbde8386202b495f14788ad79c65c3c..4b5062d950896682354c27ccc263911ca91c19ac 100644 (file)
@@ -1,3 +1,11 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * kerrs.c: New file.
+       * Makefile.in (SRCS, OBJS, STLIBOBJS): Add it.
+
+       * gc_via_tkt.c (krb5_get_cred_via_tkt): If the KDC returns
+       KRB_ERR_GENERIC, store the e-text field as the error message.
+
 2006-03-13  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.in (check-unix): Use RUN_SETUP for t_deltat.
index 05249cabb62932b63aee97df5e5a3fffceddf417..2a3d09de6ebb26c13756c0582822abc5975ac01f 100644 (file)
@@ -55,6 +55,7 @@ STLIBOBJS= \
        init_ctx.o      \
        init_keyblock.o \
        kdc_rep_dc.o    \
+       kerrs.o         \
        kfree.o         \
        mk_cred.o       \
        mk_error.o      \
@@ -140,7 +141,8 @@ OBJS=       $(OUTPRE)addr_comp.$(OBJEXT)    \
        $(OUTPRE)init_ctx.$(OBJEXT)     \
        $(OUTPRE)init_keyblock.$(OBJEXT) \
        $(OUTPRE)kdc_rep_dc.$(OBJEXT)   \
-       $(OUTPRE)kfree.$(OBJEXT)                \
+       $(OUTPRE)kerrs.$(OBJEXT)                \
+       $(OUTPRE)kfree.$(OBJEXT)        \
        $(OUTPRE)mk_cred.$(OBJEXT)      \
        $(OUTPRE)mk_error.$(OBJEXT)     \
        $(OUTPRE)mk_priv.$(OBJEXT)      \
@@ -226,6 +228,7 @@ SRCS=       $(srcdir)/addr_comp.c   \
        $(srcdir)/init_ctx.c    \
        $(srcdir)/init_keyblock.c \
        $(srcdir)/kdc_rep_dc.c  \
+       $(srcdir)/kerrs.c       \
        $(srcdir)/kfree.c       \
        $(srcdir)/mk_cred.c     \
        $(srcdir)/mk_error.c    \
index 1008d1f9294ba5168b70e7cac7a2293af6ca4979..a1ed6e90d28b52d415575b8fd8dc3c37961436ed 100644 (file)
@@ -171,6 +171,33 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
            goto error_4;
 
        retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
+       if (err_reply->text.length > 0) {
+           const char *m;
+           switch (err_reply->error) {
+           case KRB_ERR_GENERIC:
+               krb5_set_error_message(context, retval,
+                                      "KDC returned error string: %s",
+                                      err_reply->text.data);
+               break;
+           default:
+#if 0 /* We should stop the KDC from sending back this text, because
+        if the local language doesn't match the KDC's language, we'd
+        just wind up printing out the error message in two languages.
+        Well, when we get some localization.  Which is already
+        happening in KfM.  */
+               m = error_message(retval);
+               /* Special case: MIT KDC may return this same string
+                  in the e-text field.  */
+               if (strlen (m) == err_reply->text.length-1
+                   && !strcmp(m, err_reply->text.data))
+                   break;
+               krb5_set_error_message(context, retval,
+                                      "%s (KDC supplied additional data: %s)",
+                                      m, err_reply->text.data);
+#endif
+               break;
+           }
+       }
 
        krb5_free_error(context, err_reply);
        goto error_4;
diff --git a/src/lib/krb5/krb/kerrs.c b/src/lib/krb5/krb/kerrs.c
new file mode 100644 (file)
index 0000000..8439e23
--- /dev/null
@@ -0,0 +1,48 @@
+/* foo */
+#include <stdarg.h>
+#include "k5-int.h"
+
+void
+krb5_set_error_message (krb5_context ctx, krb5_error_code code,
+                       const char *fmt, ...)
+{
+    va_list args;
+    if (ctx == NULL)
+       return;
+    va_start (args, fmt);
+    krb5int_vset_error (&ctx->err, code, fmt, args);
+    va_end (args);
+}
+
+void
+krb5_vset_error_message (krb5_context ctx, krb5_error_code code,
+                        const char *fmt, va_list args)
+{
+    if (ctx == NULL)
+       return;
+    krb5int_vset_error (&ctx->err, code, fmt, args);
+}
+
+char *
+krb5_get_error_message (krb5_context ctx, krb5_error_code code)
+{
+    if (ctx == NULL)
+       return error_message(code);
+    return krb5int_get_error (&ctx->err, code);
+}
+
+void
+krb5_free_error_message (krb5_context ctx, char *msg)
+{
+    if (ctx == NULL)
+       return;
+    krb5int_free_error (&ctx->err, msg);
+}
+
+void
+krb5_clear_error_message (krb5_context ctx)
+{
+    if (ctx == NULL)
+       return;
+    krb5int_clear_error (&ctx->err);
+}
index 6771776cecce9e0dd3179e6431b158b4b0590f12..fce97ffb2e2b27dd49f93b80cdffa5a334a07d59 100644 (file)
@@ -31,6 +31,8 @@ int krb5int_lib_init(void)
 {
     int err;
 
+    krb5int_set_error_info_callout_fn (error_message);
+
 #ifdef SHOW_INITFINI_FUNCS
     printf("krb5int_lib_init\n");
 #endif
@@ -55,6 +57,7 @@ int krb5int_lib_init(void)
     err = k5_mutex_finish_init(&krb5int_us_time_mutex);
     if (err)
        return err;
+
     return 0;
 }
 
@@ -98,6 +101,7 @@ void krb5int_lib_fini(void)
     remove_error_table(&et_asn1_error_table);
     remove_error_table(&et_k524_error_table);
 #endif
+    krb5int_set_error_info_callout_fn (0);
 }
 
 /* Still exists because it went into the export list on Windows.  But
index f16b45cf803082aeb9ae3cbebee52ef75b2a51ff..8831bf78151c1200df14ebd7d88d8462a4fcd982 100644 (file)
@@ -726,3 +726,8 @@ profile_update_file_data
 profile_update_relation
 profile_verify_node
 profile_write_tree_file
+krb5_set_error_message
+krb5_vset_error_message
+krb5_get_error_message
+krb5_free_error_message
+krb5_clear_error_message
index 897919e11059ad44729ea4f57acfd9610caf2524..db471def6434be3a6c8b3a3fbe4b60b69fc2c4cb 100644 (file)
@@ -1,3 +1,11 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * Makefile.in (SHLIB_EXPLIBS, SHLIB_EXPDEPS): Add krb5 lib.
+       * py-locate.c (sctx): New variable.
+       (my_init, lookup): Call krb5_set_error_message instead of fprintf
+       in most cases.  Use sctx to pass context (not thread safe!), and
+       store it as "blob" value.
+
 2006-03-07  Ken Raeburn  <raeburn@mit.edu>
 
        * py-locate.c: Include k5-locate.h instead of k5-plugin.h.
index 46a83fede4264a48df49b73b31dadac9a4e40ada..1d0b959647600e66bd9a92adb0636ede12c04e5e 100644 (file)
@@ -10,8 +10,8 @@ SO_EXT=.so
 RELDIR=../plugins/locate/python
 MODULE_INSTALL_DIR = $(KRB5_LIBKRB5_MODULE_DIR)
 
-SHLIB_EXPDEPS=
-SHLIB_EXPLIBS= -lpython2.3
+SHLIB_EXPDEPS= $(KRB5_DEPLIB)
+SHLIB_EXPLIBS= -lpython2.3 $(KRB5_LIB)
 
 SHLIB_DIRS=-L$(TOPLIBD)
 SHLIB_RDIRS=$(KRB5_LIBDIR)
@@ -34,9 +34,10 @@ clean-unix:: clean-libs clean-libobjs
 # the Makefile.in file
 #
 py-locate.so py-locate.po $(OUTPRE)py-locate.$(OBJEXT): \
-  py-locate.c $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-int.h \
-  $(BUILDTOP)/include/krb5/osconf.h $(SRCTOP)/include/k5-platform.h \
+  py-locate.c $(BUILDTOP)/include/autoconf.h $(SRCTOP)/include/k5-int.h \
+  $(BUILDTOP)/include/osconf.h $(SRCTOP)/include/k5-platform.h \
   $(SRCTOP)/include/k5-thread.h $(BUILDTOP)/include/krb5.h \
   $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h $(SRCTOP)/include/port-sockets.h \
-  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+  $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/k5-err.h \
+  $(SRCTOP)/include/k5-locate.h $(SRCTOP)/include/kdb.h \
   $(SRCTOP)/include/k5-plugin.h
index 548210a6bde8bcb7d8af9fad5baa658ce5945071..f5dc629328ec7499b20d9c781217816212755228 100644 (file)
@@ -79,6 +79,8 @@ MAKE_FINI_FUNCTION(my_fini);
 
 #define F      (strchr(__FILE__, '/') ? 1 + strrchr(__FILE__, '/') : __FILE__)
 
+static krb5_context sctx;      /* XXX ugly hack! */
+
 int
 my_init (void)
 {
@@ -88,8 +90,13 @@ my_init (void)
     Py_Initialize ();
 //    fprintf(stderr, "trying to load %s\n", SCRIPT_PATH);
     f = fopen(SCRIPT_PATH, "r");
-    if (f == NULL)
+    if (f == NULL) {
+       if (sctx)
+           krb5_set_error_message(sctx, -1,
+                                  "couldn't open Python script %s (%s)",
+                                  SCRIPT_PATH, strerror(errno));
        return -1;
+    }
     PyRun_SimpleFile (f, SCRIPT_PATH);
     fclose(f);
     mainmodule = PyModule_GetDict(PyImport_AddModule("__main__"));
@@ -128,7 +135,7 @@ ctxinit (krb5_context ctx, void **blobptr)
        interpreter, this would be a good place for it; the blob could
        be allocated to hold the reference to the interpreter
        instance.  */
-    *blobptr = 0;
+    *blobptr = ctx;
     return 0;
 }
 
@@ -164,10 +171,12 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
 
 //    fprintf(stderr, "%s:%d: lookup(%d,%s,%d,%d)\n", F, __LINE__,
 //         svc, realm, socktype, family);
+    sctx = blob;               /* XXX: Not thread safe!  */
     i = CALL_INIT_FUNCTION (my_init);
     if (i) {
-       fprintf(stderr, "%s:%d: module initialization failed %d\n",
-               F, __LINE__, i);
+#if 0
+       fprintf(stderr, "%s:%d: module initialization failed\n", F, __LINE__);
+#endif
        return i;
     }
     if (locatefn == 0)
@@ -187,7 +196,13 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
 
     py_result = PyObject_CallObject (locatefn, arglist);
     Py_DECREF (arglist);
-    if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; }
+    if (PyErr_Occurred()) {
+       fprintf(stderr,"%s:%d: python error\n", F, __LINE__);
+       PyErr_Print();
+       krb5_set_error_message(blob, -1,
+                              "Python evaluation error, see stderr");
+       return -1;
+    }
     if (py_result == 0) {
        fprintf(stderr, "%s:%d: returned null object\n", F, __LINE__);
        return -1;
@@ -197,6 +212,8 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
     if (! PyList_Check (py_result)) {
        Py_DECREF (py_result);
        fprintf(stderr, "%s:%d: returned non-list, non-False\n", F, __LINE__);
+       krb5_set_error_message(blob, -1,
+                              "Python script error -- returned non-list, non-False result");
        return -1;
     }
     listsize = PyList_Size (py_result);
@@ -211,20 +228,24 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
 
        answer = PyList_GetItem (py_result, i);
        if (! PyTuple_Check (answer)) {
-           fprintf(stderr, "%s:%d: item %d non-tuple\n", F, __LINE__, i);
+           krb5_set_error_message(blob, -1,
+                                  "Python script error -- returned item %d not a tuple", i);
            /* leak?  */
            return -1;
        }
        if (PyTuple_Size (answer) != 3) {
-           fprintf(stderr, "%s:%d: item %d tuple size %d should be 3\n", F, __LINE__, i,
-                   PyTuple_Size (answer));
+           krb5_set_error_message(blob, -1,
+                                  "Python script error -- returned tuple %d size %d should be 3",
+                                  i, PyTuple_Size (answer));
            /* leak?  */
            return -1;
        }
        field = PyTuple_GetItem (answer, 0);
        if (! PyString_Check (field)) {
            /* leak?  */
-           fprintf(stderr, "%s:%d: item %d first component not a string\n", F, __LINE__, i);
+           krb5_set_error_message(blob, -1,
+                                  "Python script error -- first component of tuple %d is not a string",
+                                  i);
            return -1;
        }
        hoststr = PyString_AsString (field);
@@ -235,14 +256,17 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
            sprintf(portbuf, "%ld", PyInt_AsLong (field));
            portstr = portbuf;
        } else {
-           fprintf(stderr, "%s:%d: item %d second component neither string nor int\n",
-                   F, __LINE__, i);
+           krb5_set_error_message(blob, -1,
+                                  "Python script error -- second component of tuple %d neither a string nor an integer",
+                                  i);
            /* leak?  */
            return -1;
        }
        field = PyTuple_GetItem (answer, 2);
        if (! PyInt_Check (field)) {
-           fprintf(stderr, "%s:%d: item %d third component not int\n", F, __LINE__, i);
+           krb5_set_error_message(blob, -1,
+                                  "Python script error -- third component of tuple %d not an integer",
+                                  i);
            /* leak?  */
            return -1;
        }
@@ -252,16 +276,18 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
        case SOCK_DGRAM:
            /* okay */
            if (socktype != 0 && socktype != thissocktype) {
-               fprintf(stderr, "%s:%d: item %d socket type %d should be %d\n",
-                       F, __LINE__, i, thissocktype, socktype);
+               krb5_set_error_message(blob, -1,
+                                      "Python script error -- tuple %d has socket type %d, should only have %d",
+                                      i, thissocktype, socktype);
                /* leak?  */
                return -1;
            }
            break;
        default:
            /* 0 is not acceptable */
-           fprintf(stderr, "%s:%d: item %d socket type %d invalid\n", F, __LINE__, i,
-                   thissocktype);
+           krb5_set_error_message(blob, -1,
+                                  "Python script error -- tuple %d has invalid socket type %d",
+                                  i, thissocktype);
            /* leak?  */
            return -1;
        }
index 295f42f123ff9d7c61ec245990125e5c9eb3cc0a..d1fae1dbedf57d7eb85b0c207d6752a86e209fd8 100644 (file)
@@ -1,3 +1,11 @@
+2006-03-26  Ken Raeburn  <raeburn@mit.edu>
+
+       * errors.c: New file.
+       * Makefile.in (SRCS, LIBOBJS, STLIBOBJS): Add it.
+       * threads.c (krb5int_thread_support_init): Call krb5int_err_init
+       to initialize the new file.
+       * libkrb5support.exports: Add the new symbols.
+
 2006-03-13  Ken Raeburn  <raeburn@mit.edu>
 
        * plugins.c (krb5int_get_plugin_dir_data): If dirhandle is null or
index e6c75f525092a1bf230d706ffb8069152d83cb80..2e96a88db73d43721cf57beebd9b9ef4f0b059de 100644 (file)
@@ -28,12 +28,14 @@ STLIBOBJS= \
        threads.o \
        init-addrinfo.o \
        plugins.o \
+       errors.o \
        fake-addrinfo.o
 
 LIBOBJS= \
        $(OUTPRE)threads.$(OBJEXT) \
        $(OUTPRE)init-addrinfo.$(OBJEXT) \
        $(OUTPRE)plugins.$(OBJEXT) \
+       $(OUTPRE)errors.$(OBJEXT) \
        $(OUTPRE)fake-addrinfo.$(OBJEXT)
 
 STOBJLISTS=OBJS.ST
@@ -45,6 +47,7 @@ LOCALINCLUDES=-I. -I$(srcdir)
 SRCS=\
        $(srcdir)/threads.c \
        $(srcdir)/init-addrinfo.c \
+       $(srcdir)/errors.c \
        $(srcdir)/fake-addrinfo.c
 SHLIB_EXPDEPS =
 # Add -lm if dumping thread stats, for sqrt.
diff --git a/src/util/support/errors.c b/src/util/support/errors.c
new file mode 100644 (file)
index 0000000..185cb42
--- /dev/null
@@ -0,0 +1,134 @@
+/* Can't include krb5.h here, or k5-int.h which includes it, because
+   krb5.h needs to be generated with error tables, after util/et,
+   which builds after this directory.  */
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "k5-err.h"
+
+#include "k5-thread.h"
+#include "k5-platform.h"
+
+/* It would be nice to just use error_message() always.  Pity that
+   it's defined in a library that depends on this one, and we're not
+   allowed to make circular dependencies.  */
+/* We really want a rwlock here, since we should hold it while calling
+   the function and copying out its results.  But I haven't
+   implemented shims for rwlock yet.  */
+static k5_mutex_t krb5int_error_info_support_mutex =
+    K5_MUTEX_PARTIAL_INITIALIZER;
+static const char *(KRB5_CALLCONV *fptr)(long); /* = &error_message */
+
+int
+krb5int_err_init (void)
+{
+    return k5_mutex_finish_init (&krb5int_error_info_support_mutex);
+}
+#define initialize()   krb5int_call_thread_support_init()
+#define lock()         k5_mutex_lock(&krb5int_error_info_support_mutex)
+#define unlock()       k5_mutex_unlock(&krb5int_error_info_support_mutex)
+
+void
+krb5int_set_error (struct errinfo *ep, long code, const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    krb5int_vset_error (ep, code, fmt, args);
+    va_end (args);
+}
+
+void
+krb5int_vset_error (struct errinfo *ep, long code,
+                   const char *fmt, va_list args)
+{
+    if (ep->msg && ep->msg != ep->scratch_buf) {
+       free (ep->msg);
+       ep->msg = NULL;
+    }
+    ep->code = code;
+#ifdef HAVE_VASPRINTF
+    {
+       char *str = NULL;
+       if (vasprintf(&str, fmt, args) >= 0 && str != NULL) {
+           ep->msg = str;
+           return;
+       }
+    }
+#endif
+    vsnprintf(ep->scratch_buf, sizeof(ep->scratch_buf), fmt, args);
+    ep->msg = ep->scratch_buf;
+}
+
+char *
+krb5int_get_error (struct errinfo *ep, long code)
+{
+    char *r, *r2;
+    if (code != ep->code)
+       krb5int_clear_error (ep);
+    if (ep->msg) {
+       r = ep->msg;
+       ep->msg = NULL;
+       return r;
+    }
+    if (initialize() != 0) {
+       strncpy(ep->scratch_buf, _("Kerberos library initialization failure"),
+               sizeof(ep->scratch_buf));
+       ep->scratch_buf[sizeof(ep->scratch_buf)-1] = 0;
+       ep->msg = NULL;
+       return ep->scratch_buf;
+    }
+    lock();
+    if (fptr == NULL) {
+       unlock();
+       r = strerror (code);
+       if (r) {
+           if (strlen (r) < sizeof (ep->scratch_buf)
+               || (r2 = strdup (r)) == NULL) {
+               strncpy (ep->scratch_buf, r, sizeof(ep->scratch_buf));
+               return ep->scratch_buf;
+           } else
+               return r2;
+       }
+    format_number:
+       sprintf (ep->scratch_buf, _("error %ld"), code);
+       return ep->scratch_buf;
+    }
+    r = fptr(code);
+    if (r == NULL) {
+       unlock();
+       goto format_number;
+    }
+    r2 = strdup (r);
+    if (r2 == NULL) {
+       strncpy(ep->scratch_buf, r, sizeof(ep->scratch_buf));
+       unlock();
+       return ep->scratch_buf;
+    } else {
+       unlock();
+       return r2;
+    }
+}
+
+void
+krb5int_free_error (struct errinfo *ep, char *msg)
+{
+    if (msg != ep->scratch_buf)
+       free (msg);
+}
+
+void
+krb5int_clear_error (struct errinfo *ep)
+{
+    krb5int_free_error (ep, ep->msg);
+    ep->msg = NULL;
+}
+
+void
+krb5int_set_error_info_callout_fn (const char *(KRB5_CALLCONV *f)(long))
+{
+    initialize();
+    lock();
+    fptr = f;
+    unlock();
+}
index 1d7bc717f7d805f600745cbea7ff56e2f1adaae2..00ce5c3e3c35e5325f20c147d317c63278d4faaa 100644 (file)
@@ -25,3 +25,9 @@ krb5int_mutex_alloc
 krb5int_mutex_free
 krb5int_mutex_lock
 krb5int_mutex_unlock
+krb5int_set_error
+krb5int_vset_error
+krb5int_get_error
+krb5int_free_error
+krb5int_clear_error
+krb5int_set_error_info_callout_fn
index d0697bd93bc27cc80d57e08a73d3c0c6059b1f3d..7dc2e48284fda8839135e7e46882fb64e8ddeb22 100644 (file)
@@ -453,6 +453,10 @@ int krb5int_thread_support_init (void)
     if (err)
        return err;
 
+    err = krb5int_err_init();
+    if (err)
+       return err;
+
     return 0;
 }