Skip to content

Commit

Permalink
ticket: 6763
Browse files Browse the repository at this point in the history
subject: New plugin infrastructure

Merge domain-independent plugin framework code from branches/plugins2,
leaving out the password quality interface.


git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24263 dc483132-0cff-0310-8789-dd5450dbe970
  • Loading branch information
ghudson committed Aug 27, 2010
1 parent e2844df commit a4c99ee
Show file tree
Hide file tree
Showing 8 changed files with 549 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/include/Makefile.in
Expand Up @@ -137,6 +137,7 @@ install-headers-unix install:: krb5/krb5.h profile.h
$(INSTALL_DATA) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.h
$(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h
$(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h
$(INSTALL_DATA) $(srcdir)/krb5/plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)plugin.h
$(INSTALL_DATA) profile.h $(DESTDIR)$(KRB5_INCDIR)$(S)profile.h
$(INSTALL_DATA) $(srcdir)/gssapi.h $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi.h

Expand Down
119 changes: 119 additions & 0 deletions src/include/k5-int.h
Expand Up @@ -168,6 +168,7 @@ typedef INT64_TYPE krb5_int64;
*/
#include <errno.h>
#include "krb5.h"
#include <krb5/plugin.h>
#include "profile.h"

#include "port-sockets.h"
Expand Down Expand Up @@ -205,12 +206,14 @@ typedef INT64_TYPE krb5_int64;
#define KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION "default_principal_expiration"
#define KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS "default_principal_flags"
#define KRB5_CONF_DICT_FILE "dict_file"
#define KRB5_CONF_DISABLE "disable"
#define KRB5_CONF_DISABLE_LAST_SUCCESS "disable_last_success"
#define KRB5_CONF_DISABLE_LOCKOUT "disable_lockout"
#define KRB5_CONF_DNS_LOOKUP_KDC "dns_lookup_kdc"
#define KRB5_CONF_DNS_LOOKUP_REALM "dns_lookup_realm"
#define KRB5_CONF_DNS_FALLBACK "dns_fallback"
#define KRB5_CONF_DOMAIN_REALM "domain_realm"
#define KRB5_CONF_ENABLE_ONLY "enable_only"
#define KRB5_CONF_EXTRA_ADDRESSES "extra_addresses"
#define KRB5_CONF_FORWARDABLE "forwardable"
#define KRB5_CONF_HOST_BASED_SERVICES "host_based_services"
Expand Down Expand Up @@ -245,9 +248,11 @@ typedef INT64_TYPE krb5_int64;
#define KRB5_CONF_MASTER_KDC "master_kdc"
#define KRB5_CONF_MAX_LIFE "max_life"
#define KRB5_CONF_MAX_RENEWABLE_LIFE "max_renewable_life"
#define KRB5_CONF_MODULE "module"
#define KRB5_CONF_NOADDRESSES "noaddresses"
#define KRB5_CONF_NO_HOST_REFERRAL "no_host_referral"
#define KRB5_CONF_PERMITTED_ENCTYPES "permitted_enctypes"
#define KRB5_CONF_PLUGINS "plugins"
#define KRB5_CONF_PREAUTH_MODULE_DIR "preauth_module_dir"
#define KRB5_CONF_PREFERRED_PREAUTH_TYPES "preferred_preauth_types"
#define KRB5_CONF_PROXIABLE "proxiable"
Expand Down Expand Up @@ -1426,6 +1431,118 @@ krb5_authdata_free_internal(krb5_context kcontext,
krb5_authdata_context context, const char *module,
void *ptr);

/*** Plugin framework ***/

/*
* This framework can be used to create pluggable interfaces. Not all existing
* pluggable interface use this framework, but new ones should. A new
* pluggable interface entails:
*
* - An interface ID definition in the list of #defines below.
*
* - A name in the interface_names array in lib/krb5/krb/plugins.c.
*
* - An installed public header file in include/krb5. The public header should
* include <krb5/plugin.h> and should declare a vtable structure for each
* supported major version of the interface.
*
* - A consumer API implementation, located within the code unit which makes
* use of the pluggable interface. The consumer API should consist of:
*
* . An interface-specific handle type which contains a vtable structure for
* the module (or a union of several such structures, if there are multiple
* supported major versions) and, optionally, resource data bound to the
* handle.
*
* . An interface-specific loader function which creates a handle or list of
* handles. A list of handles would be created if the interface is a
* one-to-many interface where the consumer wants to consult all available
* modules; a single handle would be created for an interface where the
* consumer wants to consult a specific module. The loader function should
* use k5_plugin_load or k5_plugin_load_all to produce one or a list of
* vtable initializer functions, and should use those functions to fill in
* the vtable structure for the module (if necessary, trying each supported
* major version starting from the most recent). The loader function can
* also bind resource data into the handle based on caller arguments, if
* appropriate.
*
* . For each plugin method, a wrapper function which accepts a krb5_context,
* a plugin handle, and the method arguments. Wrapper functions should
* invoke the method function contained in the handle's vtable.
*
* - Possibly, built-in implementations of the interface, also located within
* the code unit which makes use of the interface. Built-in implementations
* must be registered with k5_plugin_register before the first call to
* k5_plugin_load or k5_plugin_load_all.
*
* A pluggable interface should have one or more currently supported major
* versions, starting at 1. Each major version should have a current minor
* version, also starting at 1. If new methods are added to a vtable, the
* minor version should be incremented and the vtable stucture should document
* where each minor vtable version ends. If method signatures for a vtable are
* changed, the major version should be incremented.
*
* Plugin module implementations (either built-in or dynamically loaded) should
* define a function named <interfacename>_<modulename>_initvt, matching the
* signature of krb5_plugin_initvt_fn as declared in include/krb5/plugin.h.
* The initvt function should check the given maj_ver argument against its own
* supported major versions, cast the vtable pointer to the appropriate
* interface-specific vtable type, and fill in the vtable methods, stopping as
* appropriate for the given min_ver. Memory for the vtable structure is
* allocated by the caller, not by the module.
*
* Dynamic plugin modules are registered with the framework through the
* [plugins] section of the profile, as described in the admin documentation
* and krb5.conf man page.
*/

/*
* A linked list entry mapping a module name to a module initvt function. The
* entry may also include a dynamic object handle so that it can be released
* when the context is destroyed.
*/
struct plugin_mapping {
char *modname;
krb5_plugin_initvt_fn module;
struct plugin_file_handle *dyn_handle;
struct plugin_mapping *next;
};

/* Holds krb5_context information about each pluggable interface. */
struct plugin_interface {
struct plugin_mapping *modules;
krb5_boolean configured;
};

/* A list of plugin interface IDs. Make sure to increment
* PLUGIN_NUM_INTERFACES when a new interface is added. */
#define PLUGIN_NUM_INTERFACES 0

/* Retrieve the plugin module of type interface_id and name modname,
* storing the result into module. */
krb5_error_code
k5_plugin_load(krb5_context context, int interface_id, const char *modname,
krb5_plugin_initvt_fn *module);

/* Retrieve all plugin modules of type interface_id, storing the result
* into modules. Free the result with k5_plugin_free_handles. */
krb5_error_code
k5_plugin_load_all(krb5_context context, int interface_id,
krb5_plugin_initvt_fn **modules);

/* Release a module list allocated by k5_plugin_load_all. */
void
k5_plugin_free_modules(krb5_context context, krb5_plugin_initvt_fn *modules);

/* Register a plugin module of type interface_id and name modname. */
krb5_error_code
k5_plugin_register(krb5_context context, int interface_id, const char *modname,
krb5_plugin_initvt_fn module);

/* Destroy the module state within context; used by krb5_free_context. */
void
k5_plugin_free_context(krb5_context context);

struct _kdb5_dal_handle; /* private, in kdb5.h */
typedef struct _kdb5_dal_handle kdb5_dal_handle;
struct _kdb_log_context;
Expand Down Expand Up @@ -1480,6 +1597,8 @@ struct _krb5_context {

krb5_trace_callback trace_callback;
void *trace_callback_data;

struct plugin_interface plugins[PLUGIN_NUM_INTERFACES];
};

/* could be used in a table to find an etype and initialize a block */
Expand Down
48 changes: 48 additions & 0 deletions src/include/krb5/plugin.h
@@ -0,0 +1,48 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* <krb5/plugin.h>
*
* Copyright (C) 2010 by the Massachusetts Institute of Technology.
* All rights reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*
* Generic declarations for dynamic modules implementing krb5 plugin modules.
*/

#ifndef KRB5_PLUGIN_H
#define KRB5_PLUGIN_H

/* krb5_plugin_vtable is an abstract type. Module initvt functions will cast
* it to the appropriate interface-specific vtable type. */
typedef struct krb5_plugin_vtable_st *krb5_plugin_vtable;

/*
* krb5_plugin_initvt_fn is the type of all module initvt functions. Based on
* the maj_ver argument, the initvt function should cast vtable to the
* appropriate type and then fill it in. If a vtable has been expanded,
* min_ver indicates which version of the vtable is being filled in.
*/
typedef krb5_error_code
(*krb5_plugin_initvt_fn)(krb5_context context, int maj_ver, int min_ver,
krb5_plugin_vtable vtable);

#endif /* KRB5_PLUGIN_H */
4 changes: 4 additions & 0 deletions src/lib/krb5/error_tables/k5e1_err.et
Expand Up @@ -30,4 +30,8 @@
#
error_table k5e1

error_code KRB5_PLUGIN_VER_NOTSUPP, "Plugin does not support interface version"
error_code KRB5_PLUGIN_BAD_MODULE_SPEC, "Invalid module specifier"
error_code KRB5_PLUGIN_NAME_NOTFOUND, "Plugin module name not found"

end
3 changes: 3 additions & 0 deletions src/lib/krb5/krb/Makefile.in
Expand Up @@ -74,6 +74,7 @@ STLIBOBJS= \
pac.o \
pac_sign.o \
parse.o \
plugin.o \
pr_to_salt.o \
preauth2.o \
gic_opt_set_pa.o \
Expand Down Expand Up @@ -173,6 +174,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \
$(OUTPRE)pac.$(OBJEXT) \
$(OUTPRE)pac_sign.$(OBJEXT) \
$(OUTPRE)parse.$(OBJEXT) \
$(OUTPRE)plugin.$(OBJEXT) \
$(OUTPRE)pr_to_salt.$(OBJEXT) \
$(OUTPRE)preauth2.$(OBJEXT) \
$(OUTPRE)gic_opt_set_pa.$(OBJEXT) \
Expand Down Expand Up @@ -273,6 +275,7 @@ SRCS= $(srcdir)/addr_comp.c \
$(srcdir)/pac.c \
$(srcdir)/pac_sign.c \
$(srcdir)/parse.c \
$(srcdir)/plugin.c \
$(srcdir)/pr_to_salt.c \
$(srcdir)/preauth2.c \
$(srcdir)/gic_opt_set_pa.c \
Expand Down
2 changes: 2 additions & 0 deletions src/lib/krb5/krb/init_ctx.c
Expand Up @@ -273,6 +273,8 @@ krb5_free_context(krb5_context ctx)
ctx->trace_callback(ctx, NULL, ctx->trace_callback_data);
#endif

k5_plugin_free_context(ctx);

ctx->magic = 0;
free(ctx);
}
Expand Down

0 comments on commit a4c99ee

Please sign in to comment.