[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