[Freeipa-devel] [PATCH] 0021 slapi-nis should allow password update on a virtual entry

Alexander Bokovoy abokovoy at redhat.com
Wed Jun 15 15:54:56 UTC 2016


On Wed, 15 Jun 2016, thierry bordaz wrote:
>>From 6cd06b9004f8ab72e13c26742d11ee31d30bbc79 Mon Sep 17 00:00:00 2001
>From: Thierry Bordaz <tbordaz at redhat.com>
>Date: Mon, 13 Jun 2016 18:13:04 +0200
>Subject: [PATCH] slapi-nis should allow password update on a virtual entry
>
>During password modification ext. op (1.3.6.1.4.1.4203.1.11.1),
>if the target entry is in the compat tree, slapi-nis should
>remap the entry to the real entry.
>
>This needs to be done in a pre-op extop that calls the callback
>function handling a given OID.
>The password mod. callback does a reverse mapping of
>extop USERID and set it in SLAPI_TARGET_SDN.
>---
> configure.ac   |   1 +
> src/back-sch.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/back-sch.h |  16 +++++
> src/plug-sch.c |  24 +++++++
> 4 files changed, 258 insertions(+)
>
>diff --git a/configure.ac b/configure.ac
>index 5b10376..9ce6bcf 100644
>--- a/configure.ac
>+++ b/configure.ac
>@@ -113,6 +113,7 @@ dirsrv)
> 			SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN,
> 			SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN,
> 			SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN,
>+			SLAPI_PLUGIN_PRE_EXTOP_FN,
> 			NULL]
> 		       ,,,
> 		       [AC_INCLUDES_DEFAULT
>diff --git a/src/back-sch.c b/src/back-sch.c
>index 32b1d9e..f9ab812 100644
>--- a/src/back-sch.c
>+++ b/src/back-sch.c
>@@ -54,6 +54,8 @@
> #include "map.h"
> #include "back-sch.h"
> 
>+backend_extop_handlers_t extop_handlers[] = {{EXTOP_PASSWD_OID, (IFP) backend_passwdmod_extop}, 
>+					    {NULL, NULL}};
> static void
> backend_entries_to_return_push(struct backend_search_cbdata *cbdata, Slapi_Entry *e);
> 
>@@ -2223,6 +2225,203 @@ done_with_lock:
> 	return ret;
> }
> 
>+/* This callback handles EXTOP_PASSWD_OID "1.3.6.1.4.1.4203.1.11.1"
>+ * If the extop defines a USERID, it sets SLAPI_TARGET_SDN to
>+ * the reverse mapping of the USERID.
>+ *
>+ * If it is not possible to retrieve USERID in the ber
>+ * then value of SLAPI_TARGET_SDN is unchanged.
>+ *
>+ * Else the value of SLAPI_TARGET_SDN is freed and replaced
>+ * either by the USERID or the reverse mapping of USERID (if it exists)
>+ */
>+static int
>+backend_passwdmod_extop(Slapi_PBlock *pb)
>+{
>+	struct backend_entry_data *data;
>+	struct plugin_state *state;
>+	Slapi_DN *sdn = NULL;
>+	char *extopdn;
>+	char *ndn;
>+	char *username = NULL;
>+	char *group = NULL;
>+	const char *entry_group = NULL;
>+	char *set = NULL;
>+	const char *entry_set = NULL;
>+	struct berval	*extop_value = NULL;
>+	BerElement	*ber = NULL;
>+	ber_tag_t	tag = 0;
>+        ber_len_t	len = (ber_len_t) -1;
>+	
>+	if (wrap_get_call_level() > 0) {
>+		return 0;
>+	}
>+
>+	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
>+	if (state->ready_to_serve == 0) {
>+		/* No data to serve yet */
>+		goto free_and_return;
>+	}
>+	/* Retrieve the original DN from the ber request */
>+	/* Get the ber value of the extended operation */
>+	slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
>+	if (!BV_HAS_DATA(extop_value)) {
>+		goto free_and_return;
>+	}
>+
>+        if ((ber = ber_init(extop_value)) == NULL) {
>+		goto free_and_return;
>+	}
>+        
>+	/* Format of request to parse
>+	 *
>+	 * PasswdModifyRequestValue ::= SEQUENCE {
>+	 * userIdentity    [0]  OCTET STRING OPTIONAL
>+	 * oldPasswd       [1]  OCTET STRING OPTIONAL
>+	 * newPasswd       [2]  OCTET STRING OPTIONAL }
>+	 *
>+	 * The request value field is optional. If it is
>+	 * provided, at least one field must be filled in.
>+	 */
>+
>+	/* ber parse code */
>+	if ( ber_scanf( ber, "{") == LBER_ERROR ) {
>+		/* The request field wasn't provided.  We'll
>+		 * now try to determine the userid and verify
>+		 * knowledge of the old password via other
>+		 * means.
>+		 */
>+		goto free_and_return;
>+	} else {
>+		tag = ber_peek_tag( ber, &len);
>+	}
>+
>+	/* identify userID field by tags */
>+	if (tag == LDAP_EXTOP_PASSMOD_TAG_USERID ) {
>+
>+		if ( ber_scanf( ber, "a", &extopdn) == LBER_ERROR ) {
>+			slapi_ch_free_string(&extopdn);
>+			goto free_and_return;
>+		}
>+
>+                slapi_log_error(SLAPI_LOG_PLUGIN, "backend_passwdmod_extop",
>+			"extopdn = %s\n", extopdn ? extopdn : "<unknown>" );
>+		
>+		/* Free the current target_DN */
>+		slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
>+		if (sdn) {
>+			const char *olddn;
>+			olddn = slapi_sdn_get_ndn(sdn);
>+			slapi_log_error(SLAPI_LOG_PLUGIN, "backend_passwdmod_extop",
>+							  "olddn = %s (unknown expected)\n", olddn ? olddn : "<unknown>" );
>+			slapi_sdn_free(&sdn);
>+		}
>+
>+		/* replace it with the one in the extop req*/
>+		sdn = slapi_sdn_new_dn_byref(extopdn);
>+		slapi_pblock_set(pb, SLAPI_TARGET_SDN, sdn);
>+	} else {
>+		/* we can not retrieve the USERID */
>+		goto free_and_return;
>+	}
>+	
>+	wrap_inc_call_level();
>+	if (map_rdlock() != 0) {
>+		slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id,
>+				"backend_passwdmod_extop unable to acquire read lock\n");
>+		wrap_dec_call_level();
>+		goto free_and_return;
>+	}
>+	backend_locate(pb, &data, &entry_group, &entry_set);
>+	if (data != NULL) {
>+		/* If there is a mapping to a real entry
>+		 * ndn will contains its DN
>+		 */
>+		if (slapi_sdn_get_ndn(data->original_entry_dn)) {
>+			ndn = slapi_ch_strdup(slapi_sdn_get_ndn(data->original_entry_dn));
>+		} else {
>+			ndn = NULL;
>+		}
>+		slapi_log_error(SLAPI_LOG_PLUGIN, "backend_passwdmod_extop",
>+				"reverse mapped dn = %s\n", ndn ? ndn : "<unknown>" );
>+
>+		username = slapi_entry_attr_get_charptr(data->e, "uid");
>+		group = slapi_ch_strdup(entry_group);
>+		set = slapi_ch_strdup(entry_set);
You don't use username/group/set anywhere, just remove them.

>+		
>+		/* the rest does not require to hold the map lock */
>+		map_unlock();
>+		wrap_dec_call_level();
>+
>+		if (ndn) {
>+			/* replace the TARGET_SDN by the one found in the map
>+			 * This is the responsibility of the extop to free it
>+			 */
>+			slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
>+			if (sdn != NULL) {
>+				slapi_sdn_free(&sdn);
>+			}
>+			sdn = slapi_sdn_new_dn_byref(ndn);
>+			slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void*) sdn);
>+		}
>+
>+		/* We are not really interested in those info, just free them */
>+		slapi_ch_free_string(&set);
>+		slapi_ch_free_string(&group);
>+		slapi_ch_free_string(&username);
and here.

>+	} else {
>+		/* no mapping entry to real entry, this is fine */
>+		map_unlock();
>+		wrap_dec_call_level();
>+	}
>+	
>+free_and_return:
>+	
>+	if ( ber != NULL ){
>+		ber_free(ber, 1);
>+		ber = NULL;
>+	}
>+	return 0;
>+}
>+static int
>+backend_extop_cb(Slapi_PBlock *pb)
>+{
>+	struct plugin_state *state;
>+	int ret;
>+	int i;
>+	char *oid = NULL;
>+	IFP fct = NULL;
>+
>+	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
>+	if (state->ready_to_serve == 0) {
>+		/* No data to serve yet */
>+		return 0;
>+	}
>+	
>+	/* First check this is a supported OID (for slapi-nis) */
>+	if ( slapi_pblock_get( pb, SLAPI_EXT_OP_REQ_OID, &oid ) != 0 )
>+   	{
>+		slapi_log_error( SLAPI_LOG_FATAL, state->plugin_desc->spd_id, "Could not get OID from request\n" );
>+		return 0;
>+	}
>+	
>+	for (i = 0; extop_handlers[i].oid != NULL; i++) {
>+		if (strcmp( oid, extop_handlers[i].oid) == 0 ) {
>+			fct = extop_handlers[i].extop_fct;
>+			break;
>+		}
>+	}
>+	
>+	if (fct) {
>+		ret = fct(pb);
>+		if (ret) {
>+			slapi_log_error( SLAPI_LOG_FATAL, "backend_extop_cb", 
>+				 "pre-extop for %s failed %d\n", oid, ret );
>+		}
>+	}
>+	return (ret);
>+}
>+
> static int
> backend_compare_cb(Slapi_PBlock *pb)
> {
>@@ -2286,6 +2485,24 @@ backend_shutdown(struct plugin_state *state)
>     backend_shr_shutdown(state);
> }
> 
>+#ifndef SLAPI_PLUGIN_PRE_EXTOP_FN
>+#define SLAPI_PLUGIN_PRE_EXTOP_FN  413
>+#endif
>+int
>+backend_init_extop(Slapi_PBlock *pb, struct plugin_state *state)
>+{
>+	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
>+			"hooking up extop callbacks\n");
>+	/* Intercept extended operation requests */
>+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_EXTOP_FN,
>+			     backend_extop_cb) != 0) {
>+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
>+				"error hooking up pre extop callback\n");
>+		return -1;
>+	}
>+	return 0;
>+}
>+
> int
> backend_init_preop(Slapi_PBlock *pb, struct plugin_state *state)
> {
>diff --git a/src/back-sch.h b/src/back-sch.h
>index e8ec400..72ba641 100644
>--- a/src/back-sch.h
>+++ b/src/back-sch.h
>@@ -127,6 +127,22 @@ struct backend_search_filter_config {
> 	void *callback_data;
> };
> 
>+/* OIDs of the supported extended operation */
>+#define EXTOP_PASSWD_OID	"1.3.6.1.4.1.4203.1.11.1"
>+
>+/* ber tags for the PasswdModifyRequestValue sequence */
>+#define LDAP_EXTOP_PASSMOD_TAG_USERID	0x80U
>+#define LDAP_EXTOP_PASSMOD_TAG_OLDPWD	0x81U
>+#define LDAP_EXTOP_PASSMOD_TAG_NEWPWD	0x82U
>+
>+typedef int (*IFP)();
>+static int backend_passwdmod_extop(Slapi_PBlock *pb);
>+typedef struct backend_extop_handlers {
>+    char *oid;
>+    IFP extop_fct;
>+} backend_extop_handlers_t;
>+
>+
> /* Analyzes the filter to decide what kind of NSS search is it
>  * Returns 0 on success, 1 on failure
>  * struct backend_search_filter_config is populated with information about the filter
>diff --git a/src/plug-sch.c b/src/plug-sch.c
>index 7af8480..00e7041 100644
>--- a/src/plug-sch.c
>+++ b/src/plug-sch.c
>@@ -65,6 +65,7 @@
> #define PLUGIN_BETXN_POSTOP_ID PLUGIN_ID "-betxn_postop"
> #define PLUGIN_POSTOP_ID PLUGIN_ID "-postop"
> #define PLUGIN_INTERNAL_POSTOP_ID PLUGIN_ID "-internal-postop"
>+#define PLUGIN_PRE_EXTOP_ID PLUGIN_ID "-extop-preop"
> 
> /* the module initialization function */
> static Slapi_PluginDesc
>@@ -185,6 +186,20 @@ plugin_shutdown(Slapi_PBlock *pb)
> 			"plugin shutdown completed\n");
> 	return 0;
> }
>+static int
>+schema_compat_plugin_init_extop(Slapi_PBlock *pb)
>+{
>+	slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
>+	slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description);
>+	slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state);
>+	if (backend_init_extop(pb, global_plugin_state) == -1) {
>+		slapi_log_error(SLAPI_LOG_PLUGIN,
>+				global_plugin_state->plugin_desc->spd_id,
>+				"error registering extop hooks\n");
>+		return -1;
>+	}
>+	return 0;
>+}
> 
> static int
> schema_compat_plugin_init_preop(Slapi_PBlock *pb)
>@@ -343,6 +358,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
> 		return -1;
> 	}
> #endif
>+	if (slapi_register_plugin("preextendedop", TRUE,
>+				  "schema_compat_plugin_init_extop",
>+				  schema_compat_plugin_init_extop,
>+				  PLUGIN_PRE_EXTOP_ID, NULL,
>+				  state->plugin_identity) != 0) {
>+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
>+				"error registering extop plugin\n");
>+		return -1;
>+	}
> 	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
> 			"registered plugin hooks\n");
> 	global_plugin_state = NULL;
>-- 
>2.5.0
>


-- 
/ Alexander Bokovoy




More information about the Freeipa-devel mailing list