Thanks Alexander for the review.
You are right I forgot to remove those lines during the cleanup.

thanks
thierry

On 06/15/2016 05:54 PM, Alexander Bokovoy wrote:
On Wed, 15 Jun 2016, thierry bordaz wrote:
From 6cd06b9004f8ab72e13c26742d11ee31d30bbc79 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbor...@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




>From c90a4c06de19e9c9d69cfa08ed7e25301e1135a2 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbor...@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.

https://fedorahosted.org/freeipa/ticket/5955
---
 configure.ac   |   1 +
 src/back-sch.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/back-sch.h |  16 +++++
 src/plug-sch.c |  24 +++++++
 4 files changed, 246 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..b45d0b7 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,191 @@ 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;
+	const char *entry_group = 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>" );
+
+		/* 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);
+		}
+	} 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 +2473,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

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to