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(&params.FIELD, params_in->FIELD,             \
                    &params.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

Reply via email to