tags 588968 patch thanks Hi. MIT Kerberos will include support for some hook like this in 1.9. It happens that I just ported the patch for Russ's plugin to 1.8.3. It's fairly non-invasive. I'd be willing to apply it to unstable if you will sign up to the task of convincing the release team that we should get a freeze exception for this.
This patch is tested only to the extent to make sure it doesn't break anything.
>From e155bf1afc9a2c105cf4dfb25768da457b5ec18b Mon Sep 17 00:00:00 2001 From: Sam Hartman <hartm...@debian.org> Date: Tue, 24 Aug 2010 21:14:26 -0400 Subject: [PATCH] kadm5: Add krb5-sync support Patch in support for krb5-sync from git://git.eyrie.org/kerberos/krb5-sync.git --- src/configure.in | 2 + src/lib/kadm5/admin.h | 2 +- src/lib/kadm5/alt_prof.c | 4 +- src/lib/kadm5/server_internal.h | 3 + src/lib/kadm5/srv/Makefile.in | 2 +- src/lib/kadm5/srv/server_init.c | 9 ++ src/lib/kadm5/srv/svr_principal.c | 161 ++++++++++++++++++++++++++++++++++++- 7 files changed, 177 insertions(+), 6 deletions(-) diff --git a/src/configure.in b/src/configure.in index e353065..269ed4c 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1041,6 +1041,8 @@ else fi AC_SUBST(ldap_plugin_dir) AC_SUBST(LDAP) +AC_CHECK_LIB(dl, dlopen, DL_LIB=-ldl) +AC_SUBST(DL_LIB) # We really should look for and use python-config. PYTHON_LIB= diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h index 8fad111..9016162 100644 --- a/src/lib/kadm5/admin.h +++ b/src/lib/kadm5/admin.h @@ -241,9 +241,9 @@ typedef struct _kadm5_config_params { specified in the database module section of the config file. */ char * dbname; + char * pwupdate_plugin; /* dummy fields to preserve abi for now */ - char * admin_dbname_was_here; char * admin_lockfile_was_here; char * admin_keytab; diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index 7d28738..df460b3 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -619,7 +619,7 @@ krb5_error_code kadm5_get_config_params(context, use_kdc_config, GET_STRING_PARAM(dbname, KADM5_CONFIG_DBNAME, KRB5_CONF_DATABASE_NAME, DEFAULT_KDB_FILE); - params.admin_dbname_was_here = NULL; + params.pwupdate_plugin = NULL; params.admin_lockfile_was_here = NULL; /* never set KADM5_CONFIG_ADBNAME, KADM5_CONFIG_ADB_LOCKFILE */ @@ -640,7 +640,7 @@ krb5_error_code kadm5_get_config_params(context, use_kdc_config, /* Get the name of the dict file */ GET_STRING_PARAM(dict_file, KADM5_CONFIG_DICT_FILE, KRB5_CONF_DICT_FILE, NULL); - + GET_STRING_PARAM(pwupdate_plugin, 0, "pwupdate_plugin", NULL); #define GET_PORT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ get_port_param(¶ms.FIELD, params_in->FIELD, \ ¶ms.mask, params_in->mask, BIT, \ diff --git a/src/lib/kadm5/server_internal.h b/src/lib/kadm5/server_internal.h index 3276b27..394cda1 100644 --- a/src/lib/kadm5/server_internal.h +++ b/src/lib/kadm5/server_internal.h @@ -94,6 +94,9 @@ int init_dict(kadm5_config_params *); int find_word(const char *word); void destroy_dict(void); +int init_pwupdate(krb5_context, kadm5_config_params *); +void destroy_pwupdate(void); + /* XXX this ought to be in libkrb5.a, but isn't */ kadm5_ret_t krb5_copy_key_data_contents(krb5_context context, krb5_key_data *from, diff --git a/src/lib/kadm5/srv/Makefile.in b/src/lib/kadm5/srv/Makefile.in index 9e8b26f..d5807c5 100644 --- a/src/lib/kadm5/srv/Makefile.in +++ b/src/lib/kadm5/srv/Makefile.in @@ -22,7 +22,7 @@ SHLIB_EXPDEPS=\ $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ $(COM_ERR_DEPLIB) $(SUPPORT_LIBDEP) SHLIB_EXPLIBS = -lgssrpc -lgssapi_krb5 -lkdb5 $(KDB5_DB_LIB) \ - -lkrb5 -lk5crypto $(SUPPORT_LIB) -lcom_err @GEN_LIB@ + -lkrb5 -lk5crypto $(SUPPORT_LIB) -lcom_err @GEN_LIB@ @DL_LIB@ SHLIB_DIRS=-L$(TOPLIBD) SHLIB_RDIRS=$(KRB5_LIBDIR) RELDIR=kadm5/srv diff --git a/src/lib/kadm5/srv/server_init.c b/src/lib/kadm5/srv/server_init.c index 557ef0a..b96108e 100644 --- a/src/lib/kadm5/srv/server_init.c +++ b/src/lib/kadm5/srv/server_init.c @@ -326,6 +326,14 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass, return ret; } + ret = init_pwupdate(handle->context, &handle->params); + if (ret) { + krb5_db_fini(handle->context); + krb5_free_principal(handle->context, handle->current_caller); + krb5_free_context(handle->context); + free(handle); + return ret; + } *server_handle = (void *) handle; return KADM5_OK; @@ -338,6 +346,7 @@ kadm5_ret_t kadm5_destroy(void *server_handle) CHECK_HANDLE(server_handle); destroy_dict(); + destroy_pwupdate(); adb_policy_close(handle); krb5_db_fini(handle->context); diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 469a8e8..aaf71a0 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -31,6 +31,8 @@ static char *rcsid = "$Header$"; #define VALGRIND_CHECK_DEFINED(LVALUE) ((void)0) #endif +#include <dlfcn.h> +#include <syslog.h> extern krb5_principal master_princ; extern krb5_principal hist_princ; extern krb5_keyblock master_keyblock; @@ -56,6 +58,7 @@ kadm5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_pr VALGRIND_CHECK_DEFINED(*inprinc); *tempprinc = *inprinc; + nelems = (int) krb5_princ_size(context, inprinc); tempprinc->data = krb5_db_alloc(context, NULL, nelems * sizeof(krb5_data)); if (tempprinc->data == 0) { @@ -116,6 +119,17 @@ kadm5_free_principal(krb5_context context, krb5_principal val) krb5_db_free(context, val); } +static void *update_handle = NULL; +static int (*d_pwupdate_init)(krb5_context, void **) = NULL; +static int (*d_pwupdate_precommit_password)(void *, krb5_principal, char *, + int, char *, int) = NULL; +static int (*d_pwupdate_postcommit_password)(void *, krb5_principal, char *, + int, char *, int) = NULL; +static int (*d_pwupdate_postcommit_status)(void *, krb5_principal, int, + char *, int) = NULL; +static int (*d_pwupdate_close)(void *) = NULL; +static void *pwupdate_context = NULL; + /* * XXX Functions that ought to be in libkrb5.a, but aren't. */ @@ -354,6 +368,25 @@ kadm5_create_principal_3(void *server_handle, return(ret); } + /* + * If we have a precommit password update entry point, call that now + * before any database modifications. + */ + + if (d_pwupdate_precommit_password) { + char errstr[256]; + + ret = (*d_pwupdate_precommit_password)(pwupdate_context, + entry->principal, password, + strlen(password), errstr, + sizeof(errstr)); + if (ret) { + krb5_klog_syslog(LOG_ERR, "External password update failed: " + "%s (%d)", errstr, ret); + return ret; + } + } + if ((ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now))) { krb5_db_free_principal(handle->context, &kdb, 1); if (mask & KADM5_POLICY) @@ -475,6 +508,18 @@ kadm5_create_principal_3(void *server_handle, return(ret); } + if (d_pwupdate_postcommit_password) { + char errstr[256]; + + ret = (*d_pwupdate_postcommit_password)(pwupdate_context, + entry->principal, password, + strlen(password), errstr, + sizeof(errstr)); + if (ret) + krb5_klog_syslog(LOG_ERR, "WARNING: External password update " + "failed: %s (%d)", errstr, ret); + } + if (mask & KADM5_POLICY) (void) kadm5_free_policy_ent(handle->lhandle, &polent); @@ -666,8 +711,22 @@ kadm5_modify_principal(void *server_handle, KADM5_REF_COUNT))))) goto done; - if ((mask & KADM5_ATTRIBUTES)) + if ((mask & KADM5_ATTRIBUTES)) { + if (d_pwupdate_postcommit_status + && ((kdb.attributes & KRB5_KDB_DISALLOW_ALL_TIX) != + (entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX))) { + char errstr[256]; + int enabled = (entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX) == 0; + + ret = (*d_pwupdate_postcommit_status)(pwupdate_context, + entry->principal, enabled, + errstr, sizeof(errstr)); + if (ret) + krb5_klog_syslog(LOG_ERR, "External status update failed: " + "%s (%d)", errstr, ret); + } kdb.attributes = entry->attributes; + } if ((mask & KADM5_MAX_LIFE)) kdb.max_life = entry->max_life; if ((mask & KADM5_PRINC_EXPIRE_TIME)) @@ -1390,11 +1449,30 @@ kadm5_chpass_principal_3(void *server_handle, if (ret) goto done; + /* + * If we have a precommit password update entry point, call that now + * before any database modifications. + */ + + if (d_pwupdate_precommit_password) { + char errstr[256]; + + ret = (*d_pwupdate_precommit_password)(pwupdate_context, principal, + password, strlen(password), + errstr, sizeof(errstr)); + if (ret) { + krb5_klog_syslog(LOG_ERR, "External password update failed: " + "%s (%d)", errstr, ret); + goto done; + } + } + ret = krb5_dbe_cpw(handle->context, act_mkey, n_ks_tuple?ks_tuple:handle->params.keysalts, n_ks_tuple?n_ks_tuple:handle->params.num_keysalts, password, 0 /* increment kvno */, keepold, &kdb); + if (ret) goto done; @@ -1517,6 +1595,17 @@ kadm5_chpass_principal_3(void *server_handle, if ((ret = kdb_put_entry(handle, &kdb, &adb))) goto done; + if (d_pwupdate_postcommit_password) { + char errstr[256]; + + ret = (*d_pwupdate_postcommit_password)(pwupdate_context, principal, + password, strlen(password), + errstr, sizeof(errstr)); + if (ret) + krb5_klog_syslog(LOG_ERR, "WARNING: External password update " + "failed: %s (%d)", errstr, ret); + } + ret = KADM5_OK; done: if (!hist_added && hist.key_data) @@ -1575,7 +1664,7 @@ kadm5_randkey_principal_3(void *server_handle, if (keepold) return KADM5_PROTECT_PRINCIPAL; ks_tuple = n_ks_tuple ? ks_tuple : handle->params.keysalts, - n_ks_tuple = 1; + n_ks_tuple = 1; } if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) @@ -2236,3 +2325,71 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle, return KADM5_OK; } + +/* + * Function: init_pwupdate + * + * Initialize the password update module (if we have one) + * + * Right now all we do is look for a module named "pwupdate.so" in the + * same directory as the database. Later on this should be cleaned up. + */ + +int +init_pwupdate(krb5_context context, kadm5_config_params *params) +{ + int ret; + + if (params->pwupdate_plugin) { + update_handle = dlopen(params->pwupdate_plugin, RTLD_NOW); + + if (! update_handle) { + krb5_klog_syslog(LOG_ERR, "ERROR: Unable to load plugin " + "\"%s\": %s", params->pwupdate_plugin, + dlerror()); + return KADM5_FAILURE; + } + + d_pwupdate_init = dlsym(update_handle, "pwupdate_init"); + d_pwupdate_precommit_password = dlsym(update_handle, + "pwupdate_precommit_password"); + d_pwupdate_postcommit_password = dlsym(update_handle, + "pwupdate_postcommit_password"); + d_pwupdate_postcommit_status = dlsym(update_handle, + "pwupdate_postcommit_status"); + d_pwupdate_close = dlsym(update_handle, "pwupdate_close"); + + if (d_pwupdate_init == NULL + || d_pwupdate_close == NULL + || (d_pwupdate_precommit_password == NULL && + d_pwupdate_postcommit_password == NULL && + d_pwupdate_postcommit_status == NULL)) { + krb5_klog_syslog(LOG_ERR, "ERROR: Needed symbols missing in " + "pwupdate plugin"); + dlclose(update_handle); + update_handle = NULL; + return KADM5_FAILURE; + } + + ret = (*d_pwupdate_init)(context, &pwupdate_context); + + if (ret != 0) { + krb5_klog_syslog(LOG_ERR, "ERROR: Password update plugin " + "initialization failed with code %d", ret); + dlclose(update_handle); + update_handle = NULL; + return KADM5_FAILURE; + } + + krb5_klog_syslog(LOG_INFO, "Password update plugin \"%s\" initialized", + params->pwupdate_plugin); + } + return KADM5_OK; +} + +void +destroy_pwupdate(void) +{ + if (d_pwupdate_close) + (*d_pwupdate_close)(pwupdate_context); +} -- 1.7.1