From 6d2780e121d8305c3acf43c56730884396990854 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Fri, 17 Jun 2011 13:44:26 +0000 Subject: [PATCH] Add k5_plugin_register_dyn internal API git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24969 dc483132-0cff-0310-8789-dd5450dbe970 --- src/config-files/krb5.conf.M | 8 +++- src/include/Makefile.in | 5 ++- src/include/k5-int.h | 11 +++++ src/include/osconf.hin | 3 ++ src/lib/krb5/krb/Makefile.in | 2 +- src/lib/krb5/krb/init_ctx.c | 7 +++ src/lib/krb5/krb/plugin.c | 86 +++++++++++++++++++++++++----------- 7 files changed, 91 insertions(+), 31 deletions(-) diff --git a/src/config-files/krb5.conf.M b/src/config-files/krb5.conf.M index b04d6efd6..33f3d920c 100644 --- a/src/config-files/krb5.conf.M +++ b/src/config-files/krb5.conf.M @@ -284,6 +284,11 @@ true. Setting this flag to false is more secure, but may force users to exclusively use fully qualified domain names when authenticating to services. +.IP plugin_base_dir +If set, determines the base directory where krb5 plugins are located. +The default value is the "krb5/plugins" subdirectory of the krb5 +library directory. + .SH APPDEFAULTS SECTION Each tag in the [appdefaults] section names a Kerberos V5 application @@ -732,8 +737,7 @@ This tag may have multiple values. Each value is a string of the form "modulename:pathname", which causes the shared object located at pathname to be registered as a dynamic module named modulename for the pluggable interface. If pathname is not an absolute path, it will be -treated as relative to the "krb5/plugins" subdirectory of the krb5 -library directory. +treated as relative to the plugin base directory. .IP enable_only This tag may have multiple values. If there are values for this tag, diff --git a/src/include/Makefile.in b/src/include/Makefile.in index ed7d20fbb..d6a9b3c38 100644 --- a/src/include/Makefile.in +++ b/src/include/Makefile.in @@ -65,8 +65,9 @@ PROCESS_REPLACE = -e "s+@KRB5RCTMPDIR+$(KRB5RCTMPDIR)+" \ -e "s+@SBINDIR+$(SBINDIR)+" \ -e "s+@MODULEDIR+$(MODULE_DIR)+" \ -e "s+@GSSMODULEDIR+$(GSS_MODULE_DIR)+" \ - -e 's+@LOCALSTATEDIR+$(LOCALSTATEDIR)+' \ - -e 's+@SYSCONFDIR+$(SYSCONFDIR)+' + -e 's+@LOCALSTATEDIR+$(LOCALSTATEDIR)+' \ + -e 's+@SYSCONFDIR+$(SYSCONFDIR)+' \ + -e 's+@DYNOBJEXT+$(DYNOBJEXT)+' OSCONFSRC = $(srcdir)/osconf.hin diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 0a00f1d28..86ec114b0 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -256,6 +256,7 @@ typedef INT64_TYPE krb5_int64; #define KRB5_CONF_NO_HOST_REFERRAL "no_host_referral" #define KRB5_CONF_PERMITTED_ENCTYPES "permitted_enctypes" #define KRB5_CONF_PLUGINS "plugins" +#define KRB5_CONF_PLUGIN_BASE_DIR "plugin_base_dir" #define KRB5_CONF_PREAUTH_MODULE_DIR "preauth_module_dir" #define KRB5_CONF_PREFERRED_PREAUTH_TYPES "preferred_preauth_types" #define KRB5_CONF_PROXIABLE "proxiable" @@ -1435,6 +1436,15 @@ krb5_error_code k5_plugin_register(krb5_context context, int interface_id, const char *modname, krb5_plugin_initvt_fn module); +/* + * Register a plugin module which is part of the krb5 tree but is built as a + * dynamic plugin. Look for the module in modsubdir relative to the + * context->base_plugin_dir. + */ +krb5_error_code +k5_plugin_register_dyn(krb5_context context, int interface_id, + const char *modname, const char *modsubdir); + /* Destroy the module state within context; used by krb5_free_context. */ void k5_plugin_free_context(krb5_context context); @@ -1496,6 +1506,7 @@ struct _krb5_context { void *trace_callback_data; struct plugin_interface plugins[PLUGIN_NUM_INTERFACES]; + char *plugin_base_dir; }; /* could be used in a table to find an etype and initialize a block */ diff --git a/src/include/osconf.hin b/src/include/osconf.hin index 073ce1422..04f10ce82 100644 --- a/src/include/osconf.hin +++ b/src/include/osconf.hin @@ -59,6 +59,9 @@ #define DEFAULT_LNAME_FILENAME "@PREFIX/lib/krb5.aname" #endif /* _WINDOWS */ +#define DEFAULT_PLUGIN_BASE_DIR "@LIBDIR/krb5/plugins" +#define PLUGIN_EXT "@DYNOBJEXT" + #define DEFAULT_KDB_FILE "@LOCALSTATEDIR/krb5kdc/principal" #define DEFAULT_KEYFILE_STUB "@LOCALSTATEDIR/krb5kdc/.k5." #define KRB5_DEFAULT_ADMIN_ACL "@LOCALSTATEDIR/krb5kdc/krb5_adm.acl" diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 6a0faf29d..6a9371836 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -4,7 +4,7 @@ RUN_SETUP = @KRB5_RUN_ENV@ PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) LOCALINCLUDES = -I$(srcdir)/../os -I$(top_srcdir) -DEFS=-DLIBDIR=\"$(KRB5_LIBDIR)\" +DEFS=-DLIBDIR=\"$(KRB5_LIBDIR)\" -DDYNOBJEXT=\"$(DYNOBJEXT)\" ##DOS##BUILDTOP = ..\..\.. ##DOS##PREFIXDIR=krb diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index 99ff5fcde..657b2dbb3 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -230,6 +230,13 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc) &tmp); ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0; + retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_PLUGIN_BASE_DIR, 0, + DEFAULT_PLUGIN_BASE_DIR, + &ctx->plugin_base_dir); + if (retval) + goto cleanup; + /* * We use a default file credentials cache of 3. See * lib/krb5/krb/ccache/file/fcc.h for a description of the diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c index 446d4f22e..a9d6b06a7 100644 --- a/src/lib/krb5/krb/plugin.c +++ b/src/lib/krb5/krb/plugin.c @@ -136,25 +136,26 @@ parse_modstr(krb5_context context, const char *modstr, * plugins directory. */ static krb5_error_code -expand_relative_modpath(const char *modpath, char **full_modpath_out) +expand_relative_modpath(krb5_context context, const char *modpath, + char **full_modpath_out) { - char *fullpath; + char *path; *full_modpath_out = NULL; /* XXX Unix-specific path handling for now. */ if (*modpath == '/') { /* We already have an absolute path. */ - fullpath = strdup(modpath); - if (fullpath == NULL) + path = strdup(modpath); + if (path == NULL) return ENOMEM; } else { /* Append the relative path to the system plugins directory. */ - if (asprintf(&fullpath, "%s/%s", LIBDIR "/krb5/plugins", modpath) < 0) + if (asprintf(&path, "%s/%s", context->plugin_base_dir, modpath) < 0) return ENOMEM; } - *full_modpath_out = fullpath; + *full_modpath_out = path; return 0; } @@ -195,28 +196,15 @@ filter_builtins(krb5_context context, struct plugin_interface *interface, } } -/* 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) + const char *iname, const char *modname, const char *path) { krb5_error_code ret; - char *modname = NULL, *modpath = NULL, *full_modpath = NULL; char *symname = NULL; struct plugin_file_handle *handle = NULL; void (*initvt_fn)(); - /* 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; - ret = expand_relative_modpath(modpath, &full_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; @@ -225,7 +213,7 @@ register_dyn_module(krb5_context context, struct plugin_interface *interface, } /* Open the plugin and resolve the initvt symbol. */ - ret = krb5int_open_plugin(full_modpath, &handle, &context->err); + ret = krb5int_open_plugin(path, &handle, &context->err); if (ret != 0) goto cleanup; ret = krb5int_get_plugin_func(handle, symname, &initvt_fn, &context->err); @@ -240,15 +228,40 @@ register_dyn_module(krb5_context context, struct plugin_interface *interface, handle = NULL; /* Now owned by the module mapping. */ cleanup: - free(modname); - free(modpath); - free(full_modpath); free(symname); if (handle != NULL) krb5int_close_plugin(handle); return ret; } +/* Register the plugin module given by the profile string mod, if enabled + * according to the values of enable and disable. */ +static krb5_error_code +register_dyn_mapping(krb5_context context, struct plugin_interface *interface, + const char *iname, const char *modstr, char **enable, + char **disable) +{ + krb5_error_code ret; + char *modname = NULL, *modpath = NULL, *fullpath = NULL; + + /* 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; + ret = expand_relative_modpath(context, modpath, &fullpath); + if (ret != 0) + goto cleanup; + if (!module_enabled(modname, enable, disable)) + goto cleanup; + ret = register_dyn_module(context, interface, iname, modname, fullpath); + +cleanup: + free(modname); + free(modpath); + free(fullpath); + return ret; +} + /* Ensure that a plugin interface is configured. id is assumed to be valid. */ static krb5_error_code configure_interface(krb5_context context, int id) @@ -284,8 +297,8 @@ configure_interface(krb5_context context, int id) /* 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); + ret = register_dyn_mapping(context, interface, iname, *mod, + enable, disable); if (ret != 0) return ret; } @@ -380,6 +393,27 @@ k5_plugin_register(krb5_context context, int interface_id, const char *modname, return register_module(context, interface, modname, module, NULL); } +krb5_error_code +k5_plugin_register_dyn(krb5_context context, int interface_id, + const char *modname, const char *modsubdir) +{ + krb5_error_code ret; + struct plugin_interface *interface = get_interface(context, interface_id); + char *path; + + /* Disallow registering plugins after load. */ + if (interface == NULL || interface->configured) + return EINVAL; + if (asprintf(&path, "%s/%s/%s%s", context->plugin_base_dir, modsubdir, + modname, PLUGIN_EXT) < 0) + return ENOMEM; + + ret = register_dyn_module(context, interface, + interface_names[interface_id], modname, path); + free(path); + return ret; +} + void k5_plugin_free_context(krb5_context context) { -- 2.26.2