[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