krb5 commit: Use new KDC authdata interface in kdc_authdata.c

Greg Hudson ghudson at mit.edu
Mon Jun 15 12:56:01 EDT 2015


https://github.com/krb5/krb5/commit/c538feaaaeb63161c87e965f88d3b3f2795aefc9
commit c538feaaaeb63161c87e965f88d3b3f2795aefc9
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Sep 26 12:02:14 2014 -0400

    Use new KDC authdata interface in kdc_authdata.c
    
    Remove the server authdata interface declarations from authdata.h and
    the code to load and invoke old KDC authdata modules.  Add code to
    load and invoke authdata modules using the new kdcauthdata pluggable
    interface.

 src/include/krb5/authdata_plugin.h |  113 -------------
 src/kdc/kdc_authdata.c             |  310 ++++++++----------------------------
 2 files changed, 65 insertions(+), 358 deletions(-)

diff --git a/src/include/krb5/authdata_plugin.h b/src/include/krb5/authdata_plugin.h
index 476105c..3399eea 100644
--- a/src/include/krb5/authdata_plugin.h
+++ b/src/include/krb5/authdata_plugin.h
@@ -31,9 +31,6 @@
  * + Documentation.
  * + Sample code.
  * + Test cases (preferably automated testing under "make check").
- * + Hook into TGS exchange too; will change API.
- * + Examine memory management issues, especially for Windows; may
- *   change API.
  *
  * Other changes that would be nice to have, but not necessarily
  * before making this interface public:
@@ -50,116 +47,6 @@
 #define KRB5_AUTHDATA_PLUGIN_H_INCLUDED
 #include <krb5/krb5.h>
 
-/*
- * While arguments of these types are passed-in, for the most part a
- * authorization data module can treat them as opaque.  If we need
- * keying data, we can ask for it directly.
- */
-struct _krb5_db_entry_new;
-
-/*
- * The function table / structure which an authdata server module must export as
- * "authdata_server_0".  NOTE: replace "0" with "1" for the type and
- * variable names if this gets picked up by upstream.  If the interfaces work
- * correctly, future versions of the table will add either more callbacks or
- * more arguments to callbacks, and in both cases we'll be able to wrap the v0
- * functions.
- */
-/* extern krb5plugin_authdata_ftable_v0 authdata_server_0; */
-typedef struct krb5plugin_authdata_server_ftable_v0 {
-    /* Not-usually-visible name. */
-    char *name;
-
-    /*
-     * Per-plugin initialization/cleanup.  The init function is called
-     * by the KDC when the plugin is loaded, and the fini function is
-     * called before the plugin is unloaded.  Both are optional.
-     */
-    krb5_error_code (*init_proc)(krb5_context, void **);
-    void (*fini_proc)(krb5_context, void *);
-    /*
-     * Actual authorization data handling function.  If this field
-     * holds a null pointer, this mechanism will be skipped, and the
-     * init/fini functions will not be run.
-     *
-     * This function should only modify the field
-     * enc_tkt_reply->authorization_data.  All other values should be
-     * considered inputs only.  And, it should *modify* the field, not
-     * overwrite it and assume that there are no other authdata
-     * plugins in use.
-     *
-     * Memory management: authorization_data is a malloc-allocated,
-     * null-terminated sequence of malloc-allocated pointers to
-     * authorization data structures.  This plugin code currently
-     * assumes the libraries, KDC, and plugin all use the same malloc
-     * pool, which may be a problem if/when we get the KDC code
-     * running on Windows.
-     *
-     * If this function returns a non-zero error code, a message
-     * is logged, but no other action is taken.  Other authdata
-     * plugins will be called, and a response will be sent to the
-     * client (barring other problems).
-     */
-    krb5_error_code (*authdata_proc)(krb5_context,
-                                     struct _krb5_db_entry_new *client,
-                                     krb5_data *req_pkt,
-                                     krb5_kdc_req *request,
-                                     krb5_enc_tkt_part *enc_tkt_reply);
-} krb5plugin_server_authdata_ftable_v0;
-
-typedef krb5plugin_server_authdata_ftable_v0 krb5plugin_authdata_ftable_v0;
-
-typedef struct krb5plugin_authdata_server_ftable_v2 {
-    /* Not-usually-visible name. */
-    char *name;
-
-    /*
-     * Per-plugin initialization/cleanup.  The init function is called
-     * by the KDC when the plugin is loaded, and the fini function is
-     * called before the plugin is unloaded.  Both are optional.
-     */
-    krb5_error_code (*init_proc)(krb5_context, void **);
-    void (*fini_proc)(krb5_context, void *);
-    /*
-     * Actual authorization data handling function.  If this field
-     * holds a null pointer, this mechanism will be skipped, and the
-     * init/fini functions will not be run.
-     *
-     * This function should only modify the field
-     * enc_tkt_reply->authorization_data.  All other values should be
-     * considered inputs only.  And, it should *modify* the field, not
-     * overwrite it and assume that there are no other authdata
-     * plugins in use.
-     *
-     * Memory management: authorization_data is a malloc-allocated,
-     * null-terminated sequence of malloc-allocated pointers to
-     * authorization data structures.  This plugin code currently
-     * assumes the libraries, KDC, and plugin all use the same malloc
-     * pool, which may be a problem if/when we get the KDC code
-     * running on Windows.
-     *
-     * If this function returns a non-zero error code, a message
-     * is logged, but no other action is taken.  Other authdata
-     * plugins will be called, and a response will be sent to the
-     * client (barring other problems).
-     */
-    krb5_error_code (*authdata_proc)(krb5_context,
-                                     unsigned int flags,
-                                     struct _krb5_db_entry_new *client,
-                                     struct _krb5_db_entry_new *server,
-                                     struct _krb5_db_entry_new *tgs,
-                                     krb5_keyblock *client_key,
-                                     krb5_keyblock *server_key,
-                                     krb5_keyblock *tgs_key,
-                                     krb5_data *req_pkt,
-                                     krb5_kdc_req *request,
-                                     krb5_const_principal for_user_princ,
-                                     krb5_enc_tkt_part *enc_tkt_request,
-                                     krb5_enc_tkt_part *enc_tkt_reply);
-} krb5plugin_authdata_server_ftable_v2;
-
-typedef krb5plugin_authdata_server_ftable_v2 krb5plugin_authdata_ftable_v2;
-
 typedef krb5_error_code
 (*authdata_client_plugin_init_proc)(krb5_context context,
                                     void **plugin_context);
diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c
index 410a57a..afe18f0 100644
--- a/src/kdc/kdc_authdata.c
+++ b/src/kdc/kdc_authdata.c
@@ -33,233 +33,75 @@
 #include <syslog.h>
 
 #include <assert.h>
-#include <krb5/authdata_plugin.h>
-
-#if TARGET_OS_MAC
-static const char *objdirs[] = { KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR,
-                                 LIBDIR "/krb5/plugins/authdata",
-                                 NULL }; /* should be a list */
-#else
-static const char *objdirs[] = { LIBDIR "/krb5/plugins/authdata", NULL };
-#endif
-
-/* MIT Kerberos 1.6 (V0) authdata plugin callback */
-typedef krb5_error_code (*authdata_proc_0)(
-    krb5_context,
-    krb5_db_entry *client,
-    krb5_data *req_pkt,
-    krb5_kdc_req *request,
-    krb5_enc_tkt_part * enc_tkt_reply);
-/* MIT Kerberos 1.8 (V2) authdata plugin callback */
-typedef krb5_error_code (*authdata_proc_2)(
-    krb5_context, unsigned int flags,
-    krb5_db_entry *client, krb5_db_entry *server,
-    krb5_db_entry *krbtgt,
-    krb5_keyblock *client_key,
-    krb5_keyblock *server_key,
-    krb5_keyblock *krbtgt_key,
-    krb5_data *req_pkt,
-    krb5_kdc_req *request,
-    krb5_const_principal for_user_princ,
-    krb5_enc_tkt_part *enc_tkt_request,
-    krb5_enc_tkt_part *enc_tkt_reply);
-typedef krb5_error_code (*init_proc)(krb5_context, void **);
-typedef void (*fini_proc)(krb5_context, void *);
-
-typedef struct _krb5_authdata_systems {
-    const char *name;
-#define AUTHDATA_SYSTEM_UNKNOWN -1
-#define AUTHDATA_SYSTEM_V0      0
-#define AUTHDATA_SYSTEM_V2      2
-    int         type;
-    void       *plugin_context;
-    init_proc   init;
-    fini_proc   fini;
-    union {
-        authdata_proc_2 v2;
-        authdata_proc_0 v0;
-    } handle_authdata;
-} krb5_authdata_systems;
-
-static krb5_authdata_systems *authdata_systems;
-static int n_authdata_systems;
-static struct plugin_dir_handle authdata_plugins;
-
-/* Load both v0 and v2 authdata plugins */
-krb5_error_code
-load_authdata_plugins(krb5_context context)
-{
-    void **authdata_plugins_ftables_v0 = NULL;
-    void **authdata_plugins_ftables_v2 = NULL;
-    size_t module_count;
-    size_t i, k;
-    init_proc server_init_proc = NULL;
-    krb5_error_code code;
-
-    /* Attempt to load all of the authdata plugins we can find. */
-    PLUGIN_DIR_INIT(&authdata_plugins);
-    if (PLUGIN_DIR_OPEN(&authdata_plugins) == 0) {
-        if (krb5int_open_plugin_dirs(objdirs, NULL,
-                                     &authdata_plugins, &context->err) != 0) {
-            return KRB5_PLUGIN_NO_HANDLE;
-        }
-    }
-
-    /* Get the method tables provided by the loaded plugins. */
-    authdata_plugins_ftables_v0 = NULL;
-    authdata_plugins_ftables_v2 = NULL;
-    n_authdata_systems = 0;
-
-    if (krb5int_get_plugin_dir_data(&authdata_plugins,
-                                    "authdata_server_2",
-                                    &authdata_plugins_ftables_v2,
-                                    &context->err) != 0 ||
-        krb5int_get_plugin_dir_data(&authdata_plugins,
-                                    "authdata_server_0",
-                                    &authdata_plugins_ftables_v0,
-                                    &context->err) != 0) {
-        code = KRB5_PLUGIN_NO_HANDLE;
-        goto cleanup;
-    }
-
-    /* Count the valid modules. */
-    module_count = 0;
-
-    if (authdata_plugins_ftables_v2 != NULL) {
-        struct krb5plugin_authdata_server_ftable_v2 *ftable;
-
-        for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) {
-            ftable = authdata_plugins_ftables_v2[i];
-            if (ftable->authdata_proc != NULL)
-                module_count++;
-        }
-    }
-
-    if (authdata_plugins_ftables_v0 != NULL) {
-        struct krb5plugin_authdata_server_ftable_v0 *ftable;
+#include <krb5/kdcauthdata_plugin.h>
 
-        for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
-            ftable = authdata_plugins_ftables_v0[i];
-            if (ftable->authdata_proc != NULL)
-                module_count++;
-        }
-    }
-
-    /* Build the complete list of supported authdata options, and
-     * leave room for a terminator entry.
-     */
-    authdata_systems = calloc(module_count + 1, sizeof(krb5_authdata_systems));
-    if (authdata_systems == NULL) {
-        code = ENOMEM;
-        goto cleanup;
-    }
-
-    k = 0;
-
-    /* Add dynamically loaded V2 plugins */
-    if (authdata_plugins_ftables_v2 != NULL) {
-        struct krb5plugin_authdata_server_ftable_v2 *ftable;
+typedef struct kdcauthdata_handle_st {
+    struct krb5_kdcauthdata_vtable_st vt;
+    krb5_kdcauthdata_moddata data;
+} kdcauthdata_handle;
 
-        for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) {
-            krb5_error_code initerr;
-            void *pctx = NULL;
+static kdcauthdata_handle *authdata_modules;
+static size_t n_authdata_modules;
 
-            ftable = authdata_plugins_ftables_v2[i];
-            if (ftable->authdata_proc == NULL) {
-                continue;
-            }
-            server_init_proc = ftable->init_proc;
-            if ((server_init_proc != NULL) &&
-                ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
-                const char *emsg;
-                emsg = krb5_get_error_message(context, initerr);
-                krb5_klog_syslog(LOG_ERR,
-                                 _("authdata %s failed to initialize: %s"),
-                                 ftable->name, emsg);
-                krb5_free_error_message(context, emsg);
-                memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
-
-                continue;
-            }
-
-            authdata_systems[k].name = ftable->name;
-            authdata_systems[k].type = AUTHDATA_SYSTEM_V2;
-            authdata_systems[k].init = server_init_proc;
-            authdata_systems[k].fini = ftable->fini_proc;
-            authdata_systems[k].handle_authdata.v2 = ftable->authdata_proc;
-            authdata_systems[k].plugin_context = pctx;
-            k++;
-        }
+/* Load authdata plugin modules. */
+krb5_error_code
+load_authdata_plugins(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_plugin_initvt_fn *modules = NULL, *mod;
+    kdcauthdata_handle *list, *h;
+    size_t count;
+
+    ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCAUTHDATA, &modules);
+    if (ret)
+        return ret;
+
+    /* Allocate a large enough list of handles. */
+    for (count = 0; modules[count] != NULL; count++);
+    list = calloc(count + 1, sizeof(*list));
+    if (list == NULL) {
+        k5_plugin_free_modules(context, modules);
+        return ENOMEM;
     }
 
-    /* Add dynamically loaded V0 plugins */
-    if (authdata_plugins_ftables_v0 != NULL) {
-        struct krb5plugin_authdata_server_ftable_v0 *ftable;
-
-        for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
-            krb5_error_code initerr;
-            void *pctx = NULL;
-
-            ftable = authdata_plugins_ftables_v0[i];
-            if (ftable->authdata_proc == NULL) {
-                continue;
-            }
-            server_init_proc = ftable->init_proc;
-            if ((server_init_proc != NULL) &&
-                ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
-                const char *emsg;
-                emsg = krb5_get_error_message(context, initerr);
-                krb5_klog_syslog(LOG_ERR,
-                                 _("authdata %s failed to initialize: %s"),
-                                 ftable->name, emsg);
-                krb5_free_error_message(context, emsg);
-                memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
-
+    /* Initialize each module's vtable and module data. */
+    count = 0;
+    for (mod = modules; *mod != NULL; mod++) {
+        h = &list[count];
+        memset(h, 0, sizeof(*h));
+        ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt);
+        if (ret)                /* Version mismatch, keep going. */
+            continue;
+        if (h->vt.init != NULL) {
+            ret = h->vt.init(context, &h->data);
+            if (ret) {
+                kdc_err(context, ret, _("while loading authdata module %s"),
+                        h->vt.name);
                 continue;
             }
-
-            authdata_systems[k].name = ftable->name;
-            authdata_systems[k].type = AUTHDATA_SYSTEM_V0;
-            authdata_systems[k].init = server_init_proc;
-            authdata_systems[k].fini = ftable->fini_proc;
-            authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc;
-            authdata_systems[k].plugin_context = pctx;
-            k++;
         }
+        count++;
     }
 
-    n_authdata_systems = k;
-    /* Add the end-of-list marker. */
-    authdata_systems[k].name = "[end]";
-    authdata_systems[k].type = AUTHDATA_SYSTEM_UNKNOWN;
-    code = 0;
-
-cleanup:
-    if (authdata_plugins_ftables_v2 != NULL)
-        krb5int_free_plugin_dir_data(authdata_plugins_ftables_v2);
-    if (authdata_plugins_ftables_v0 != NULL)
-        krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0);
-
-    return code;
+    authdata_modules = list;
+    n_authdata_modules = count;
+    k5_plugin_free_modules(context, modules);
+    return 0;
 }
 
 krb5_error_code
 unload_authdata_plugins(krb5_context context)
 {
-    int i;
-    if (authdata_systems != NULL) {
-        for (i = 0; i < n_authdata_systems; i++) {
-            if (authdata_systems[i].fini != NULL) {
-                (*authdata_systems[i].fini)(context,
-                                            authdata_systems[i].plugin_context);
-            }
-            memset(&authdata_systems[i], 0, sizeof(authdata_systems[i]));
-        }
-        free(authdata_systems);
-        authdata_systems = NULL;
-        n_authdata_systems = 0;
-        krb5int_close_plugin_dirs(&authdata_plugins);
+    kdcauthdata_handle *h;
+    size_t i;
+
+    for (i = 0; i < n_authdata_modules; i++) {
+        h = &authdata_modules[i];
+        if (h->vt.fini != NULL)
+            h->vt.fini(context, h->data);
     }
+    free(authdata_modules);
+    authdata_modules = NULL;
     return 0;
 }
 
@@ -962,8 +804,9 @@ handle_authdata (krb5_context context,
                  krb5_enc_tkt_part *enc_tkt_request,
                  krb5_enc_tkt_part *enc_tkt_reply)
 {
+    kdcauthdata_handle *h;
     krb5_error_code code = 0;
-    int i;
+    size_t i;
 
     if (request->msg_type == KRB5_TGS_REQ &&
         request->authorization_data.ciphertext.data != NULL) {
@@ -976,39 +819,16 @@ handle_authdata (krb5_context context,
             return code;
     }
 
-    for (i = 0; i < n_authdata_systems; i++) {
-        const krb5_authdata_systems *asys = &authdata_systems[i];
-        if (isflagset(enc_tkt_reply->flags, TKT_FLG_ANONYMOUS))
-            continue;
-
-        switch (asys->type) {
-        case AUTHDATA_SYSTEM_V0:
-            /* V0 was only in AS-REQ code path */
-            if (request->msg_type != KRB5_AS_REQ)
-                continue;
-
-            code = (*asys->handle_authdata.v0)(context, client, req_pkt,
-                                               request, enc_tkt_reply);
-            break;
-        case AUTHDATA_SYSTEM_V2:
-            code = (*asys->handle_authdata.v2)(context, flags,
-                                               client, server, krbtgt,
-                                               client_key, server_key, krbtgt_key,
-                                               req_pkt, request, for_user_princ,
-                                               enc_tkt_request,
-                                               enc_tkt_reply);
-            break;
-        default:
-            code = 0;
-            break;
-        }
-        if (code != 0) {
-            const char *emsg;
-
-            emsg = krb5_get_error_message (context, code);
-            krb5_klog_syslog(LOG_INFO, _("authdata (%s) handling failure: %s"),
-                             asys->name, emsg);
-            krb5_free_error_message (context, emsg);
+    /* Invoke loaded module handlers. */
+    if (!isflagset(enc_tkt_reply->flags, TKT_FLG_ANONYMOUS)) {
+        for (i = 0; i < n_authdata_modules; i++) {
+            h = &authdata_modules[i];
+            code = h->vt.handle(context, h->data, flags, client, server,
+                                krbtgt, client_key, server_key, krbtgt_key,
+                                req_pkt, request, for_user_princ,
+                                enc_tkt_request, enc_tkt_reply);
+            if (code)
+                kdc_err(context, code, "from authdata module %s", h->vt.name);
         }
     }
 


More information about the cvs-krb5 mailing list