svn rev #24217: branches/plugins2/ src/lib/krb5/krb/

ghudson@MIT.EDU ghudson at MIT.EDU
Thu Jul 29 08:40:08 EDT 2010


http://src.mit.edu/fisheye/changelog/krb5/?cs=24217
Commit By: ghudson
Log Message:
On the plugins2 branch, improve the generic plugin support so that it
does not dlopen/dlsym modules which would later be filtered out.  Also
edit README.BRANCH a little.



Changed Files:
U   branches/plugins2/README.BRANCH
U   branches/plugins2/src/lib/krb5/krb/plugin.c
Modified: branches/plugins2/README.BRANCH
===================================================================
--- branches/plugins2/README.BRANCH	2010-07-27 16:09:45 UTC (rev 24216)
+++ branches/plugins2/README.BRANCH	2010-07-29 12:40:08 UTC (rev 24217)
@@ -111,11 +111,11 @@
 1. Build the branch normally and install it somewhere.
 
 2. cd into the pwqual_combo directory and build it with "make
-   -I/path/to/install/include".  The Makefile probably only works on
-   Linux-based operating systems.
+   INCLUDES=-I/path/to/install/include".  The Makefile probably only
+   works on Linux-based operating systems.
 
 3. Go back to the main build directory and run "make testrealm" to
-   create a functioning environment.
+   spawn a shell within a functioning environment.
 
 4. Add the following configuration to testdir/krb5.master.conf to make
    pwqual_combo discoverable:
@@ -130,23 +130,25 @@
    the setting "dict_file = /tmp/dict".
 
 6. Run kadmin.local and create a policy with "addpol -minlength 4
-testpolicy".  Associated it with the principal user with "modprinc
--policy testpolicy user".
+   testpolicy".  Associated it with the principal user with "modprinc
+   -policy testpolicy user".
 
 7. Inside kadmin.local, try some password change with "cpw user".  You
-should be able to see that all three password quality modules are
-functioning: you won't be able to set passwords shorter than four
-characters long (the policy module), or the passwords "books" or
-"sharks" (the dict module), or passwords named "sharksbooks" or
-"bookssharks" (the combo module).
+   should be able to see that all three password quality modules are
+   functioning: you won't be able to set passwords shorter than four
+   characters long (the policy module), or the passwords "books" or
+   "sharks" (the dict module), or passwords named "sharksbooks" or
+   "bookssharks" (the combo module).
 
 8. Quit out of kadmin.local and edit testdir/krb5.master.conf again.
-Play with the filtering rules by adding, alongside the "module"
-directive, one or more assignments for enable_only and/or disable.
-For instance, if you disable the policy module, you should find that
-(upon restarting kadmin.local) you can set passwords shorter than four
-characters again.
+   Play with the filtering rules by adding, alongside the "module"
+   directive, one or more assignments for enable_only and/or disable.
+   For instance, if you disable the policy module, you should find
+   that (upon restarting kadmin.local) you can set passwords shorter
+   than four characters again.
 
+9. Exit out of the shell to quit out of the test environment.
+
 ----- What's wrong with this branch -----
 
 The krb5 code on this branch is mostly complete, but as a
@@ -179,8 +181,3 @@
   interface.  This constraint is probably fine, but if it needs to be
   revisited, the framework's data model will need to be made a little
   more complicated to allow it.
-
-* Filtering should probably be applied to module mappings before
-  dynamic modules are opened, since dlopen() is not always a cheap
-  operation.  This is an implementation detail of the
-  domain-independent plugin framework.

Modified: branches/plugins2/src/lib/krb5/krb/plugin.c
===================================================================
--- branches/plugins2/src/lib/krb5/krb/plugin.c	2010-07-27 16:09:45 UTC (rev 24216)
+++ branches/plugins2/src/lib/krb5/krb/plugin.c	2010-07-29 12:40:08 UTC (rev 24217)
@@ -133,62 +133,6 @@
     return 0;
 }
 
-/* Open a dynamic object at modpath, look up symname within it, and register
- * the resulting init function as modname. */
-static krb5_error_code
-open_and_register(krb5_context context, struct plugin_interface *interface,
-                  const char *modname, const char *modpath,
-                  const char *symname)
-{
-    krb5_error_code ret;
-    struct plugin_file_handle *handle;
-    void (*initvt_fn)();
-
-    ret = krb5int_open_plugin(modpath, &handle, &context->err);
-    if (ret != 0)
-        return ret;
-
-    ret = krb5int_get_plugin_func(handle, symname, &initvt_fn, &context->err);
-    if (ret != 0) {
-        krb5int_close_plugin(handle);
-        return ret;
-    }
-
-    ret = register_module(context, interface, modname,
-                          (krb5_plugin_initvt_fn)initvt_fn, handle);
-    if (ret != 0)
-        krb5int_close_plugin(handle);
-    return ret;
-}
-
-/* Register the plugins given by the profile strings in modules. */
-static krb5_error_code
-register_dyn_modules(krb5_context context, struct plugin_interface *interface,
-                     const char *iname, char **modules)
-{
-    krb5_error_code ret;
-    char *modname = NULL, *modpath = NULL, *symname = NULL;
-
-    for (; *modules != NULL; modules++) {
-        ret = parse_modstr(context, *modules, &modname, &modpath);
-        if (ret != 0)
-            return ret;
-        if (asprintf(&symname, "%s_%s_initvt", iname, modname) < 0) {
-            free(modname);
-            free(modpath);
-            return ENOMEM;
-        }
-        /* XXX should errors here be fatal, or just ignore the module? */
-        ret = open_and_register(context, interface, modname, modpath, symname);
-        free(modname);
-        free(modpath);
-        free(symname);
-        if (ret != 0)
-            return ret;
-    }
-    return 0;
-}
-
 /* Return true if value is found in list. */
 static krb5_boolean
 find_in_list(char **list, const char *value)
@@ -200,17 +144,25 @@
     return FALSE;
 }
 
-/* Remove any registered modules whose names are not present in enable. */
+/* Return true if module is not filtered out by enable or disable lists. */
+static krb5_boolean
+module_enabled(const char *modname, char **enable, char **disable)
+{
+    return ((enable == NULL || find_in_list(enable, modname)) &&
+            (disable == NULL || !find_in_list(disable, modname)));
+}
+
+/* Remove any registered modules whose names are filtered out. */
 static void
-filter_enable(krb5_context context, struct plugin_interface *interface,
-              char **enable)
+filter_builtins(krb5_context context, struct plugin_interface *interface,
+                char **enable, char **disable)
 {
     struct plugin_mapping *map, **pmap;
 
     pmap = &interface->modules;
     while (*pmap != NULL) {
         map = *pmap;
-        if (!find_in_list(enable, map->modname)) {
+        if (!module_enabled(map->modname, enable, disable)) {
             *pmap = map->next;
             free_plugin_mapping(map);
         } else
@@ -218,22 +170,53 @@
     }
 }
 
-/* Remove any registered modules whose names are present in disable. */
-static void
-filter_disable(krb5_context context, struct plugin_interface *interface,
-               char **disable)
+/* Register the plugin module given by the profile string mod. */
+static krb5_error_code
+register_dyn_module(krb5_context context, struct plugin_interface *interface,
+                    const char *iname, const char *modstr, char **enable,
+                    char **disable)
 {
-    struct plugin_mapping *map, **pmap;
+    krb5_error_code ret;
+    char *modname = NULL, *modpath = NULL, *symname = NULL;
+    struct plugin_file_handle *handle = NULL;
+    void (*initvt_fn)();
 
-    pmap = &interface->modules;
-    while (*pmap != NULL) {
-        map = *pmap;
-        if (find_in_list(disable, map->modname)) {
-            *pmap = map->next;
-            free_plugin_mapping(map);
-        } else
-            pmap = &map->next;
+    /* Parse out the module name and path, and make sure it is enabled. */
+    ret = parse_modstr(context, modstr, &modname, &modpath);
+    if (ret != 0)
+        goto cleanup;
+    if (!module_enabled(modname, enable, disable))
+        goto cleanup;
+
+    /* Construct the initvt symbol name for this interface and module. */
+    if (asprintf(&symname, "%s_%s_initvt", iname, modname) < 0) {
+        symname = NULL;
+        ret = ENOMEM;
+        goto cleanup;
     }
+
+    /* Open the plugin and resolve the initvt symbol. */
+    ret = krb5int_open_plugin(modpath, &handle, &context->err);
+    if (ret != 0)
+        goto cleanup;
+    ret = krb5int_get_plugin_func(handle, symname, &initvt_fn, &context->err);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Create a mapping for the module. */
+    ret = register_module(context, interface, modname,
+                          (krb5_plugin_initvt_fn)initvt_fn, handle);
+    if (ret != 0)
+        goto cleanup;
+    handle = NULL;              /* Now owned by the module mapping. */
+
+cleanup:
+    free(modname);
+    free(modpath);
+    free(symname);
+    if (handle != NULL)
+        krb5int_close_plugin(handle);
+    return ret;
 }
 
 /* Ensure that a plugin interface is configured.  id is assumed to be valid. */
@@ -243,7 +226,7 @@
     krb5_error_code ret;
     struct plugin_interface *interface = &context->plugins[id];
     const char *iname = interface_names[id];
-    char **modules = NULL, **enable = NULL, **disable = NULL;
+    char **modules = NULL, **enable = NULL, **disable = NULL, **mod;
     static const char *path[4];
 
     if (interface->configured)
@@ -266,15 +249,16 @@
     if (ret != 0 && ret != PROF_NO_RELATION)
         goto cleanup;
 
-    if (modules != NULL) {
-        ret = register_dyn_modules(context, interface, iname, modules);
+    /* Remove built-in modules which are filtered out by configuration. */
+    filter_builtins(context, interface, enable, disable);
+
+    /* Create mappings for dynamic modules which aren't filtered out. */
+    for (mod = modules; mod && *mod; mod++) {
+        ret = register_dyn_module(context, interface, iname, *mod,
+                                  enable, disable);
         if (ret != 0)
             return ret;
     }
-    if (enable != NULL)
-        filter_enable(context, interface, enable);
-    if (disable != NULL)
-        filter_disable(context, interface, disable);
 
     ret = 0;
 cleanup:




More information about the cvs-krb5 mailing list