]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add err_fmt profile parameter
authorNicolas Williams <nico@cryptonector.com>
Wed, 12 Nov 2014 21:50:53 +0000 (15:50 -0600)
committerGreg Hudson <ghudson@mit.edu>
Sun, 7 Dec 2014 20:11:02 +0000 (15:11 -0500)
Support the err_fmt relation in [libdefaults] which allows custom
error message formatting.

[ghudson@mit.edu: maintain alphabetical order in documentation and
reword docs; simplify err_fmt_fmt; expand commit message]

ticket: 8047 (new)

doc/admin/conf_files/krb5_conf.rst
src/include/k5-int.h
src/lib/krb5/krb/copy_ctx.c
src/lib/krb5/krb/init_ctx.c
src/lib/krb5/krb/kerrs.c

index 6636c2fc818961f68fe6fee8b2dc67f0c5ddaea3..3b51905e0797449bc8c9fdb5ab4d3c43110cf677 100644 (file)
@@ -206,6 +206,11 @@ The libdefaults section may contain any of the following relations:
     data), and anything the fake KDC sends will not be trusted without
     verification using some secret that it won't know.
 
+**err_fmt**
+    This relation allows for custom error message formatting.  If a
+    value is set, error messages will be formatted by substituting a
+    normal error message for %M and an error code for %C in the value.
+
 **extra_addresses**
     This allows a computer to use multiple local addresses, in order
     to allow Kerberos to work in a network that uses NATs while still
@@ -363,7 +368,6 @@ The libdefaults section may contain any of the following relations:
     credentials will fail if the client machine does not have a
     keytab.  The default value is false.
 
-
 .. _realms:
 
 [realms]
index 0970af7796749681550d2e80d5a6b5b41ca5ccd5..a1ea25aac08270eaddd57fe26006bf6d0eecbca7 100644 (file)
@@ -211,6 +211,7 @@ typedef unsigned char   u_char;
 #define KRB5_CONF_DNS_LOOKUP_REALM             "dns_lookup_realm"
 #define KRB5_CONF_DOMAIN_REALM                 "domain_realm"
 #define KRB5_CONF_ENABLE_ONLY                  "enable_only"
+#define KRB5_CONF_ERR_FMT                      "err_fmt"
 #define KRB5_CONF_EXTRA_ADDRESSES              "extra_addresses"
 #define KRB5_CONF_FORWARDABLE                  "forwardable"
 #define KRB5_CONF_HOST_BASED_SERVICES          "host_based_services"
@@ -1187,6 +1188,7 @@ struct _krb5_context {
 
     /* error detail info */
     struct errinfo err;
+    char *err_fmt;
 
     /* For Sun iprop code; does this really have to be here?  */
     struct _kdb_log_context *kdblog_context;
index 322c288f4f4194bdc1ed137e1a1ebbeeb1ca50f6..c09965ebf148f3cbce9d9816925444c2b3b68a1b 100644 (file)
@@ -85,6 +85,9 @@ krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
     nctx->kdblog_context = NULL;
     nctx->trace_callback = NULL;
     nctx->trace_callback_data = NULL;
+    nctx->err_fmt = NULL;
+    if (ctx->err_fmt != NULL)
+        nctx->err_fmt = strdup(ctx->err_fmt);   /* It's OK if this fails */
     nctx->plugin_base_dir = NULL;
     nctx->os_context.default_ccname = NULL;
 
index 6548f365d13cbfbd697a81de67d662619eac2156..a39362745b4d183e966726dc9027bb0774d2bf70 100644 (file)
@@ -281,6 +281,10 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
     ctx->prompt_types = 0;
     ctx->use_conf_ktypes = 0;
     ctx->udp_pref_limit = -1;
+
+    /* It's OK if this fails */
+    (void)profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
+                             KRB5_CONF_ERR_FMT, NULL, NULL, &ctx->err_fmt);
     *context_out = ctx;
     return 0;
 
@@ -308,6 +312,7 @@ krb5_free_context(krb5_context ctx)
     }
 
     krb5_clear_error_message(ctx);
+    free(ctx->err_fmt);
 
 #ifndef DISABLE_TRACING
     if (ctx->trace_callback)
index 9e263356d1192e599f6cd020ee4dedd396aa0a29..0146d9a411e07876857ef30f712a637a200030fd 100644 (file)
@@ -135,16 +135,58 @@ krb5_copy_error_message(krb5_context dest_ctx, krb5_context src_ctx)
     }
 }
 
+/* Re-format msg using the format string err_fmt.  Return an allocated result,
+ * or NULL if err_fmt is NULL or on allocation failure. */
+static char *
+err_fmt_fmt(const char *err_fmt, long code, const char *msg)
+{
+    struct k5buf buf;
+    const char *p, *s;
+
+    if (err_fmt == NULL)
+        return NULL;
+
+    k5_buf_init_dynamic(&buf);
+
+    s = err_fmt;
+    while ((p = strchr(s, '%')) != NULL) {
+        k5_buf_add_len(&buf, s, p - s);
+        s = p;
+        if (p[1] == '\0')
+            break;
+        else if (p[1] == 'M')
+            k5_buf_add(&buf, msg);
+        else if (p[1] == 'C')
+            k5_buf_add_fmt(&buf, "%ld", code);
+        else if (p[1] == '%')
+            k5_buf_add(&buf, "%");
+        else
+            k5_buf_add_fmt(&buf, "%%%c", p[1]);
+        s += 2;
+    }
+    k5_buf_add(&buf, s);        /* Remainder after last token */
+    return buf.data;
+}
+
 const char * KRB5_CALLCONV
 krb5_get_error_message(krb5_context ctx, krb5_error_code code)
 {
+    const char *std, *custom;
+
 #ifdef DEBUG
     if (ERROR_MESSAGE_DEBUG())
         fprintf(stderr, "krb5_get_error_message(%p, %ld)\n", ctx, (long)code);
 #endif
     if (ctx == NULL)
         return error_message(code);
-    return k5_get_error(&ctx->err, code);
+
+    std = k5_get_error(&ctx->err, code);
+    custom = err_fmt_fmt(ctx->err_fmt, code, std);
+    if (custom != NULL) {
+        free((char *)std);
+        return custom;
+    }
+    return std;
 }
 
 void KRB5_CALLCONV