From 88efff5ae386040768925943ae8d0824e6e15f6e Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Thu, 21 Jan 2016 04:42:17 +0100 Subject: Rewrite the base dn if needed in pre_search If a service wants to get the user information by searching for the user DN explicitly (maybe with a BASE search scope), we need to drop the virtual prefix for the service (the virtual entry might not even exists or does not have the requested user infromation). The pre_search plugin method is executed before all searches and modifies the TARGET_DN if required. --- service_passwords.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/service_passwords.c b/service_passwords.c index a8e2700..56c6e58 100644 --- a/service_passwords.c +++ b/service_passwords.c @@ -617,6 +617,83 @@ fail1: return rc; } +/** \c PRE_SEARCH plugin to rewrite the search base if it is set to the virtual + * service entry. + * + * Most applications want to get the user information of a user. Some might get + * this information by searching with the user DN as base DN. This does not work + * for the virtual service DNs, because this entries might not exists. + * + * So for all searches that are executed in an authenticated connection + * (authenticated as service account or user) the virtual prefix is dropped, if + * the base DN is the virtual user entry. The \c PRE_ENTRY hook rewrites the + * found user entry to the requested virtual user entry. This does nocht work, + * if the client explicitly searches with a search filter for \c cn, but it is + * sufficient. + * + * @param[in,out] pb Parameter block of the operation. + * @return The return value do not have influence on the search operation by + * itself. It only stops further plugin processing (other plguins), if + * it is not equal 0. + */ +static int pre_search(Slapi_PBlock *pb) +{ + char *bind_dn; + char *base; + int is_replication; + int is_internal; + + char *parent_dn = NULL; + + int rc = 0; + char fn[] = "pre_search in service_passwords plug-in"; + + rc |= slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn); + rc |= slapi_pblock_get(pb, SLAPI_TARGET_DN, &base); + rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_replication); + rc |= slapi_pblock_get(pb, SLAPI_IS_INTERNAL_OPERATION, &is_internal); + + if (rc != 0) { + slapi_log_error( + SLAPI_LOG_PLUGIN, fn, + "Could not get parameters (error %d).\n", + rc); + + slapi_send_ldap_result( + pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL); + return LDAP_OPERATIONS_ERROR; + } + + if (is_replication || is_internal) { + return 0; + } + + if (bind_dn == NULL) { + /* only handle authenticated searches */ + return 0; + } + + if (is_service(bind_dn, NULL) != 0) { + parent_dn = slapi_dn_parent(bind_dn); + rc |= is_user(parent_dn); + slapi_ch_free_string(&parent_dn); + + if (rc != 0) { + return 0; + } + } + + parent_dn = slapi_dn_parent(base); + + if (is_user(parent_dn) == 0) { + rc |= slapi_pblock_set(pb, SLAPI_TARGET_DN, parent_dn); + } + + slapi_ch_free_string(&parent_dn); + + return rc; +} + Slapi_PluginDesc bindpdesc = { .spd_id = "service_passwords", .spd_vendor = "spline", @@ -633,6 +710,7 @@ int service_passwords_init(Slapi_PBlock *pb) rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &bindpdesc); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_BIND_FN, (void *) pre_bind); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ENTRY_FN, (void *) pre_entry); + rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *) pre_search); rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_id); return rc; } -- cgit v1.2.3-1-g7c22