1 /* $NetBSD: dyngroup.c,v 1.1.1.3 2010/12/12 15:23:34 adam Exp $ */ 2 3 /* dyngroup.c - Demonstration of overlay code */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/overlays/dyngroup.c,v 1.10.2.5 2010/04/13 20:23:44 kurt Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2003-2010 The OpenLDAP Foundation. 8 * Copyright 2003 by Howard Chu. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work was initially developed by Howard Chu for inclusion in 21 * OpenLDAP Software. 22 */ 23 24 #include "portable.h" 25 26 #ifdef SLAPD_OVER_DYNGROUP 27 28 #include <stdio.h> 29 30 #include <ac/string.h> 31 #include <ac/socket.h> 32 33 #include "lutil.h" 34 #include "slap.h" 35 #include "config.h" 36 37 /* This overlay extends the Compare operation to detect members of a 38 * dynamic group. It has no effect on any other operations. It must 39 * be configured with a pair of attributes to trigger on, e.g. 40 * attrpair member memberURL 41 * will cause compares on "member" to trigger a compare on "memberURL". 42 */ 43 44 typedef struct adpair { 45 struct adpair *ap_next; 46 AttributeDescription *ap_mem; 47 AttributeDescription *ap_uri; 48 } adpair; 49 50 static int dgroup_cf( ConfigArgs *c ) 51 { 52 slap_overinst *on = (slap_overinst *)c->bi; 53 int rc = 1; 54 55 switch( c->op ) { 56 case SLAP_CONFIG_EMIT: 57 { 58 adpair *ap; 59 for ( ap = on->on_bi.bi_private; ap; ap = ap->ap_next ) { 60 struct berval bv; 61 char *ptr; 62 bv.bv_len = ap->ap_mem->ad_cname.bv_len + 1 + 63 ap->ap_uri->ad_cname.bv_len; 64 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 65 ptr = lutil_strcopy( bv.bv_val, ap->ap_mem->ad_cname.bv_val ); 66 *ptr++ = ' '; 67 strcpy( ptr, ap->ap_uri->ad_cname.bv_val ); 68 ber_bvarray_add( &c->rvalue_vals, &bv ); 69 rc = 0; 70 } 71 } 72 break; 73 case LDAP_MOD_DELETE: 74 if ( c->valx == -1 ) { 75 adpair *ap; 76 while (( ap = on->on_bi.bi_private )) { 77 on->on_bi.bi_private = ap->ap_next; 78 ch_free( ap ); 79 } 80 } else { 81 adpair **app, *ap; 82 int i; 83 app = (adpair **)&on->on_bi.bi_private; 84 for (i=0; i<=c->valx; i++, app = &ap->ap_next) { 85 ap = *app; 86 } 87 *app = ap->ap_next; 88 ch_free( ap ); 89 } 90 rc = 0; 91 break; 92 case SLAP_CONFIG_ADD: 93 case LDAP_MOD_ADD: 94 { 95 adpair ap = { NULL, NULL, NULL }, *a2; 96 const char *text; 97 if ( slap_str2ad( c->argv[1], &ap.ap_mem, &text ) ) { 98 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"", 99 c->argv[0], c->argv[1] ); 100 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 101 "%s: %s\n", c->log, c->cr_msg, 0 ); 102 return ARG_BAD_CONF; 103 } 104 if ( slap_str2ad( c->argv[2], &ap.ap_uri, &text ) ) { 105 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"", 106 c->argv[0], c->argv[2] ); 107 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 108 "%s: %s\n", c->log, c->cr_msg, 0 ); 109 return ARG_BAD_CONF; 110 } 111 /* The on->on_bi.bi_private pointer can be used for 112 * anything this instance of the overlay needs. 113 */ 114 a2 = ch_malloc( sizeof(adpair) ); 115 a2->ap_next = on->on_bi.bi_private; 116 a2->ap_mem = ap.ap_mem; 117 a2->ap_uri = ap.ap_uri; 118 on->on_bi.bi_private = a2; 119 rc = 0; 120 } 121 } 122 return rc; 123 } 124 125 static ConfigTable dgroupcfg[] = { 126 { "attrpair", "member-attribute> <URL-attribute", 3, 3, 0, 127 ARG_MAGIC, dgroup_cf, 128 "( OLcfgOvAt:17.1 NAME 'olcDGAttrPair' " 129 "DESC 'Member and MemberURL attribute pair' " 130 "SYNTAX OMsDirectoryString )", NULL, NULL }, 131 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 132 }; 133 134 static ConfigOCs dgroupocs[] = { 135 { "( OLcfgOvOc:17.1 " 136 "NAME 'olcDGConfig' " 137 "DESC 'Dynamic Group configuration' " 138 "SUP olcOverlayConfig " 139 "MAY olcDGAttrPair )", 140 Cft_Overlay, dgroupcfg }, 141 { NULL, 0, NULL } 142 }; 143 144 static int 145 dyngroup_response( Operation *op, SlapReply *rs ) 146 { 147 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 148 adpair *ap = on->on_bi.bi_private; 149 150 /* If we've been configured and the current response is 151 * what we're looking for... 152 */ 153 if ( ap && op->o_tag == LDAP_REQ_COMPARE && 154 rs->sr_err == LDAP_NO_SUCH_ATTRIBUTE ) { 155 156 for (;ap;ap=ap->ap_next) { 157 if ( op->oq_compare.rs_ava->aa_desc == ap->ap_mem ) { 158 /* This compare is for one of the attributes we're 159 * interested in. We'll use slapd's existing dyngroup 160 * evaluator to get the answer we want. 161 */ 162 int cache = op->o_do_not_cache; 163 164 op->o_do_not_cache = 1; 165 rs->sr_err = backend_group( op, NULL, &op->o_req_ndn, 166 &op->oq_compare.rs_ava->aa_value, NULL, ap->ap_uri ); 167 op->o_do_not_cache = cache; 168 switch ( rs->sr_err ) { 169 case LDAP_SUCCESS: 170 rs->sr_err = LDAP_COMPARE_TRUE; 171 break; 172 173 case LDAP_NO_SUCH_OBJECT: 174 rs->sr_err = LDAP_COMPARE_FALSE; 175 break; 176 } 177 break; 178 } 179 } 180 } 181 /* Default is to just fall through to the normal processing */ 182 return SLAP_CB_CONTINUE; 183 } 184 185 static int 186 dyngroup_close( 187 BackendDB *be, 188 ConfigReply *cr 189 ) 190 { 191 slap_overinst *on = (slap_overinst *) be->bd_info; 192 adpair *ap, *a2; 193 194 for ( ap = on->on_bi.bi_private; ap; ap = a2 ) { 195 a2 = ap->ap_next; 196 ch_free( ap ); 197 } 198 return 0; 199 } 200 201 static slap_overinst dyngroup; 202 203 /* This overlay is set up for dynamic loading via moduleload. For static 204 * configuration, you'll need to arrange for the slap_overinst to be 205 * initialized and registered by some other function inside slapd. 206 */ 207 208 int dyngroup_initialize() { 209 int code; 210 211 dyngroup.on_bi.bi_type = "dyngroup"; 212 dyngroup.on_bi.bi_db_close = dyngroup_close; 213 dyngroup.on_response = dyngroup_response; 214 215 dyngroup.on_bi.bi_cf_ocs = dgroupocs; 216 code = config_register_schema( dgroupcfg, dgroupocs ); 217 if ( code ) return code; 218 219 return overlay_register( &dyngroup ); 220 } 221 222 #if SLAPD_OVER_DYNGROUP == SLAPD_MOD_DYNAMIC 223 int 224 init_module( int argc, char *argv[] ) 225 { 226 return dyngroup_initialize(); 227 } 228 #endif 229 230 #endif /* defined(SLAPD_OVER_DYNGROUP) */ 231