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