Back to index

openldap  2.4.31
dyngroup.c
Go to the documentation of this file.
00001 /* dyngroup.c - Demonstration of overlay code */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2003-2012 The OpenLDAP Foundation.
00006  * Copyright 2003 by Howard Chu.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Howard Chu for inclusion in
00019  * OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #ifdef SLAPD_OVER_DYNGROUP
00025 
00026 #include <stdio.h>
00027 
00028 #include <ac/string.h>
00029 #include <ac/socket.h>
00030 
00031 #include "lutil.h"
00032 #include "slap.h"
00033 #include "config.h"
00034 
00035 /* This overlay extends the Compare operation to detect members of a
00036  * dynamic group. It has no effect on any other operations. It must
00037  * be configured with a pair of attributes to trigger on, e.g.
00038  *     attrpair member memberURL
00039  * will cause compares on "member" to trigger a compare on "memberURL".
00040  */
00041 
00042 typedef struct adpair {
00043        struct adpair *ap_next;
00044        AttributeDescription *ap_mem;
00045        AttributeDescription *ap_uri;
00046 } adpair;
00047 
00048 static int dgroup_cf( ConfigArgs *c )
00049 {
00050        slap_overinst *on = (slap_overinst *)c->bi;
00051        int rc = 1;
00052 
00053        switch( c->op ) {
00054        case SLAP_CONFIG_EMIT:
00055               {
00056               adpair *ap;
00057               for ( ap = on->on_bi.bi_private; ap; ap = ap->ap_next ) {
00058                      struct berval bv;
00059                      char *ptr;
00060                      bv.bv_len = ap->ap_mem->ad_cname.bv_len + 1 +
00061                             ap->ap_uri->ad_cname.bv_len;
00062                      bv.bv_val = ch_malloc( bv.bv_len + 1 );
00063                      ptr = lutil_strcopy( bv.bv_val, ap->ap_mem->ad_cname.bv_val );
00064                      *ptr++ = ' ';
00065                      strcpy( ptr, ap->ap_uri->ad_cname.bv_val );
00066                      ber_bvarray_add( &c->rvalue_vals, &bv );
00067                      rc = 0;
00068               }
00069               }
00070               break;
00071        case LDAP_MOD_DELETE:
00072               if ( c->valx == -1 ) {
00073                      adpair *ap;
00074                      while (( ap = on->on_bi.bi_private )) {
00075                             on->on_bi.bi_private = ap->ap_next;
00076                             ch_free( ap );
00077                      }
00078               } else {
00079                      adpair **app, *ap;
00080                      int i;
00081                      app = (adpair **)&on->on_bi.bi_private;
00082                      for (i=0; i<=c->valx; i++, app = &ap->ap_next) {
00083                             ap = *app;
00084                      }
00085                      *app = ap->ap_next;
00086                      ch_free( ap );
00087               }
00088               rc = 0;
00089               break;
00090        case SLAP_CONFIG_ADD:
00091        case LDAP_MOD_ADD:
00092               {
00093               adpair ap = { NULL, NULL, NULL }, *a2;
00094               const char *text;
00095               if ( slap_str2ad( c->argv[1], &ap.ap_mem, &text ) ) {
00096                      snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
00097                             c->argv[0], c->argv[1] );
00098                      Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
00099                             "%s: %s\n", c->log, c->cr_msg, 0 );
00100                      return ARG_BAD_CONF;
00101               }
00102               if ( slap_str2ad( c->argv[2], &ap.ap_uri, &text ) ) {
00103                      snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
00104                             c->argv[0], c->argv[2] );
00105                      Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
00106                             "%s: %s\n", c->log, c->cr_msg, 0 );
00107                      return ARG_BAD_CONF;
00108               }
00109               /* The on->on_bi.bi_private pointer can be used for
00110                * anything this instance of the overlay needs.
00111                */
00112               a2 = ch_malloc( sizeof(adpair) );
00113               a2->ap_next = on->on_bi.bi_private;
00114               a2->ap_mem = ap.ap_mem;
00115               a2->ap_uri = ap.ap_uri;
00116               on->on_bi.bi_private = a2;
00117               rc = 0;
00118               }
00119        }
00120        return rc;
00121 }
00122 
00123 static ConfigTable dgroupcfg[] = {
00124        { "attrpair", "member-attribute> <URL-attribute", 3, 3, 0,
00125          ARG_MAGIC, dgroup_cf,
00126          "( OLcfgOvAt:17.1 NAME 'olcDGAttrPair' "
00127          "DESC 'Member and MemberURL attribute pair' "
00128          "SYNTAX OMsDirectoryString )", NULL, NULL },
00129        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
00130 };
00131 
00132 static ConfigOCs dgroupocs[] = {
00133        { "( OLcfgOvOc:17.1 "
00134          "NAME 'olcDGConfig' "
00135          "DESC 'Dynamic Group configuration' "
00136          "SUP olcOverlayConfig "
00137          "MAY olcDGAttrPair )",
00138          Cft_Overlay, dgroupcfg },
00139        { NULL, 0, NULL }
00140 };
00141 
00142 static int
00143 dyngroup_response( Operation *op, SlapReply *rs )
00144 {
00145        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
00146        adpair *ap = on->on_bi.bi_private;
00147 
00148        /* If we've been configured and the current response is
00149         * what we're looking for...
00150         */
00151        if ( ap && op->o_tag == LDAP_REQ_COMPARE &&
00152               rs->sr_err == LDAP_NO_SUCH_ATTRIBUTE ) {
00153 
00154               for (;ap;ap=ap->ap_next) {
00155                      if ( op->oq_compare.rs_ava->aa_desc == ap->ap_mem ) {
00156                             /* This compare is for one of the attributes we're
00157                              * interested in. We'll use slapd's existing dyngroup
00158                              * evaluator to get the answer we want.
00159                              */
00160                             int cache = op->o_do_not_cache;
00161                             
00162                             op->o_do_not_cache = 1;
00163                             rs->sr_err = backend_group( op, NULL, &op->o_req_ndn,
00164                                    &op->oq_compare.rs_ava->aa_value, NULL, ap->ap_uri );
00165                             op->o_do_not_cache = cache;
00166                             switch ( rs->sr_err ) {
00167                             case LDAP_SUCCESS:
00168                                    rs->sr_err = LDAP_COMPARE_TRUE;
00169                                    break;
00170 
00171                             case LDAP_NO_SUCH_OBJECT:
00172                                    rs->sr_err = LDAP_COMPARE_FALSE;
00173                                    break;
00174                             }
00175                             break;
00176                      }
00177               }
00178        }
00179        /* Default is to just fall through to the normal processing */
00180        return SLAP_CB_CONTINUE;
00181 }
00182 
00183 static int
00184 dyngroup_close(
00185        BackendDB *be,
00186        ConfigReply *cr
00187 )
00188 {
00189        slap_overinst *on = (slap_overinst *) be->bd_info;
00190        adpair *ap, *a2;
00191 
00192        for ( ap = on->on_bi.bi_private; ap; ap = a2 ) {
00193               a2 = ap->ap_next;
00194               ch_free( ap );
00195        }
00196        return 0;
00197 }
00198 
00199 static slap_overinst dyngroup;
00200 
00201 /* This overlay is set up for dynamic loading via moduleload. For static
00202  * configuration, you'll need to arrange for the slap_overinst to be
00203  * initialized and registered by some other function inside slapd.
00204  */
00205 
00206 int dyngroup_initialize() {
00207        int code;
00208 
00209        dyngroup.on_bi.bi_type = "dyngroup";
00210        dyngroup.on_bi.bi_db_close = dyngroup_close;
00211        dyngroup.on_response = dyngroup_response;
00212 
00213        dyngroup.on_bi.bi_cf_ocs = dgroupocs;
00214        code = config_register_schema( dgroupcfg, dgroupocs );
00215        if ( code ) return code;
00216 
00217        return overlay_register( &dyngroup );
00218 }
00219 
00220 #if SLAPD_OVER_DYNGROUP == SLAPD_MOD_DYNAMIC
00221 int
00222 init_module( int argc, char *argv[] )
00223 {
00224        return dyngroup_initialize();
00225 }
00226 #endif
00227 
00228 #endif /* defined(SLAPD_OVER_DYNGROUP) */