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

thierry bordaz tbordaz at redhat.com
Wed Jun 15 16:42:39 UTC 2016


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 <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
>>
>
>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-slapi-nis-should-allow-password-update-on-a-virtual-.patch
Type: text/x-patch
Size: 10044 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20160615/3300c40a/attachment.bin>


More information about the Freeipa-devel mailing list