Back to index

openldap  2.4.31
noopsrch.c
Go to the documentation of this file.
00001 /* noopsrch.c - LDAP Control that counts entries a search would return */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2010-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* ACKNOWLEDGEMENTS:
00017  * This work was initially developed by Pierangelo Masarati for inclusion
00018  * in OpenLDAP Software.
00019  */
00020 
00021 #include "portable.h"
00022 
00023 /* define SLAPD_OVER_NOOPSRCH=2 to build as run-time loadable module */
00024 #ifdef SLAPD_OVER_NOOPSRCH
00025 
00026 /*
00027  * Control OID
00028  */
00029 #define       LDAP_CONTROL_X_NOOPSRCH            "1.3.6.1.4.1.4203.666.5.18"
00030 
00031 #include "slap.h"
00032 #include "ac/string.h"
00033 
00034 #define o_noopsrch                 o_ctrlflag[noopsrch_cid]
00035 #define o_ctrlnoopsrch             o_controls[noopsrch_cid]
00036 
00037 static int noopsrch_cid;
00038 static slap_overinst noopsrch;
00039 
00040 static int
00041 noopsrch_parseCtrl (
00042        Operation *op,
00043        SlapReply *rs,
00044        LDAPControl *ctrl )
00045 {
00046        if ( op->o_noopsrch != SLAP_CONTROL_NONE ) {
00047               rs->sr_text = "No-op Search control specified multiple times";
00048               return LDAP_PROTOCOL_ERROR;
00049        }
00050 
00051        if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
00052               rs->sr_text = "No-op Search control value is present";
00053               return LDAP_PROTOCOL_ERROR;
00054        }
00055 
00056        op->o_ctrlnoopsrch = (void *)NULL;
00057 
00058        op->o_noopsrch = ctrl->ldctl_iscritical
00059               ? SLAP_CONTROL_CRITICAL
00060               : SLAP_CONTROL_NONCRITICAL;
00061 
00062        rs->sr_err = LDAP_SUCCESS;
00063 
00064        return rs->sr_err;
00065 }
00066 
00067 int dummy;
00068 
00069 typedef struct noopsrch_cb_t {
00070        slap_overinst *nc_on;
00071        ber_int_t            nc_nentries;
00072        ber_int_t            nc_nsearchref;
00073        AttributeName *nc_save_attrs;
00074        int                         *nc_pdummy;
00075        int                         nc_save_slimit;
00076 } noopsrch_cb_t;
00077 
00078 static int
00079 noopsrch_response( Operation *op, SlapReply *rs )
00080 {
00081        noopsrch_cb_t        *nc = (noopsrch_cb_t *)op->o_callback->sc_private;
00082 
00083        /* if the control is global, limits are not computed yet  */
00084        if ( nc->nc_pdummy == &dummy ) {   
00085               nc->nc_save_slimit = op->ors_slimit;
00086               op->ors_slimit = SLAP_NO_LIMIT;
00087               nc->nc_pdummy = NULL;
00088        }
00089 
00090        if ( rs->sr_type == REP_SEARCH ) {
00091               nc->nc_nentries++;
00092 #ifdef NOOPSRCH_DEBUG
00093               Debug( LDAP_DEBUG_TRACE, "noopsrch_response(REP_SEARCH): nentries=%d\n", nc->nc_nentries, 0, 0 );
00094 #endif
00095               return 0;
00096 
00097        } else if ( rs->sr_type == REP_SEARCHREF ) {
00098               nc->nc_nsearchref++;
00099               return 0;
00100 
00101        } else if ( rs->sr_type == REP_RESULT ) {
00102               BerElementBuffer     berbuf;
00103               BerElement                  *ber = (BerElement *) &berbuf;
00104               struct berval        ctrlval;
00105               LDAPControl                 *ctrl, *ctrlsp[2];
00106               int                                rc = rs->sr_err;
00107 
00108               if ( nc->nc_save_slimit >= 0 && nc->nc_nentries >= nc->nc_save_slimit ) {
00109                      rc = LDAP_SIZELIMIT_EXCEEDED;
00110               }
00111 
00112 #ifdef NOOPSRCH_DEBUG
00113               Debug( LDAP_DEBUG_TRACE, "noopsrch_response(REP_RESULT): err=%d nentries=%d nref=%d\n", rc, nc->nc_nentries, nc->nc_nsearchref );
00114 #endif
00115 
00116               ber_init2( ber, NULL, LBER_USE_DER );
00117 
00118               ber_printf( ber, "{iii}", rc, nc->nc_nentries, nc->nc_nsearchref );
00119               if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
00120                      ber_free_buf( ber );
00121                      if ( op->o_noopsrch == SLAP_CONTROL_CRITICAL ) {
00122                             return LDAP_CONSTRAINT_VIOLATION;
00123                      }
00124                      return SLAP_CB_CONTINUE;
00125               }
00126 
00127               ctrl = op->o_tmpcalloc( 1,
00128                      sizeof( LDAPControl ) + ctrlval.bv_len + 1,
00129                      op->o_tmpmemctx );
00130               ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
00131               ctrl->ldctl_oid = LDAP_CONTROL_X_NOOPSRCH;
00132               ctrl->ldctl_iscritical = 0;
00133               ctrl->ldctl_value.bv_len = ctrlval.bv_len;
00134               AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
00135               ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';
00136 
00137               ber_free_buf( ber );
00138 
00139               ctrlsp[0] = ctrl;
00140               ctrlsp[1] = NULL;
00141               slap_add_ctrls( op, rs, ctrlsp );
00142 
00143               return SLAP_CB_CONTINUE;
00144        }
00145 }
00146 
00147 static int
00148 noopsrch_cleanup( Operation *op, SlapReply *rs )
00149 {
00150        if ( rs->sr_type == REP_RESULT || rs->sr_err == SLAPD_ABANDON ) {
00151               noopsrch_cb_t        *nc = (noopsrch_cb_t *)op->o_callback->sc_private;
00152               op->ors_attrs = nc->nc_save_attrs;
00153               if ( nc->nc_pdummy == NULL ) {
00154                      op->ors_slimit = nc->nc_save_slimit;
00155               }
00156 
00157               op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
00158               op->o_callback = NULL;
00159        }
00160 
00161        return SLAP_CB_CONTINUE;
00162 }
00163 
00164 static int
00165 noopsrch_op_search( Operation *op, SlapReply *rs )
00166 {
00167        if ( op->o_noopsrch != SLAP_CONTROL_NONE ) {
00168               slap_callback *sc;
00169               noopsrch_cb_t *nc;
00170 
00171               sc = op->o_tmpcalloc( 1, sizeof( slap_callback ) + sizeof( noopsrch_cb_t ), op->o_tmpmemctx );
00172 
00173               nc = (noopsrch_cb_t *)&sc[ 1 ];
00174               nc->nc_on = (slap_overinst *)op->o_bd->bd_info;
00175               nc->nc_nentries = 0;
00176               nc->nc_nsearchref = 0;
00177               nc->nc_save_attrs = op->ors_attrs;
00178               nc->nc_pdummy = &dummy;
00179 
00180               sc->sc_response = noopsrch_response;
00181               sc->sc_cleanup = noopsrch_cleanup;
00182               sc->sc_private = (void *)nc;
00183 
00184               op->ors_attrs = slap_anlist_no_attrs;
00185 
00186               sc->sc_next = op->o_callback->sc_next;
00187                 op->o_callback->sc_next = sc;
00188        }
00189        
00190        return SLAP_CB_CONTINUE;
00191 }
00192 
00193 static int noopsrch_cnt;
00194 
00195 static int
00196 noopsrch_db_init( BackendDB *be, ConfigReply *cr)
00197 {
00198        if ( noopsrch_cnt++ == 0 ) {
00199               int rc;
00200 
00201               rc = register_supported_control( LDAP_CONTROL_X_NOOPSRCH,
00202                      SLAP_CTRL_SEARCH | SLAP_CTRL_GLOBAL_SEARCH, NULL,
00203                      noopsrch_parseCtrl, &noopsrch_cid );
00204               if ( rc != LDAP_SUCCESS ) {
00205                      Debug( LDAP_DEBUG_ANY,
00206                             "noopsrch_initialize: Failed to register control '%s' (%d)\n",
00207                             LDAP_CONTROL_X_NOOPSRCH, rc, 0 );
00208                      return rc;
00209               }
00210        }
00211 
00212        return LDAP_SUCCESS;
00213 }
00214 
00215 static int
00216 noopsrch_db_destroy( BackendDB *be, ConfigReply *cr )
00217 {
00218        assert( noopsrch_cnt > 0 );
00219 
00220 #ifdef SLAP_CONFIG_DELETE
00221        overlay_unregister_control( be, LDAP_CONTROL_X_NOOPSRCH );
00222        if ( --noopsrch_cnt == 0 ) {
00223               unregister_supported_control( LDAP_CONTROL_X_NOOPSRCH );
00224        }
00225 
00226 #endif /* SLAP_CONFIG_DELETE */
00227 
00228        return 0;
00229 }
00230 
00231 #if SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC
00232 static
00233 #endif /* SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC */
00234 int
00235 noopsrch_initialize( void )
00236 {
00237 
00238        noopsrch.on_bi.bi_type = "noopsrch";
00239 
00240        noopsrch.on_bi.bi_db_init = noopsrch_db_init;
00241        noopsrch.on_bi.bi_db_destroy = noopsrch_db_destroy;
00242        noopsrch.on_bi.bi_op_search = noopsrch_op_search;
00243 
00244        return overlay_register( &noopsrch );
00245 }
00246 
00247 #if SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC
00248 int
00249 init_module( int argc, char *argv[] )
00250 {
00251        return noopsrch_initialize();
00252 }
00253 #endif /* SLAPD_OVER_NOOPSRCH == SLAPD_MOD_DYNAMIC */
00254 
00255 #endif /* SLAPD_OVER_NOOPSRCH */