1 /* $NetBSD: cloak.c,v 1.1.1.2 2010/12/12 15:18:56 adam Exp $ */ 2 3 /* cloak.c - Overlay to hide some attribute except if explicitely requested */ 4 /* OpenLDAP: pkg/ldap/contrib/slapd-modules/cloak/cloak.c,v 1.2.2.4 2010/04/13 20:22:26 kurt Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2008-2010 The OpenLDAP Foundation. 8 * Portions Copyright 2008 Emmanuel Dreyfus 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 originally developed by the Emmanuel Dreyfus for 21 * inclusion in OpenLDAP Software. 22 */ 23 24 #include "portable.h" 25 26 #ifdef SLAPD_OVER_CLOAK 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 enum { CLOAK_ATTR = 1 }; 38 39 typedef struct cloak_info_t { 40 ObjectClass *ci_oc; 41 AttributeDescription *ci_ad; 42 struct cloak_info_t *ci_next; 43 } cloak_info_t; 44 45 #define CLOAK_USAGE "\"cloak-attr <attr> [<class>]\": " 46 47 static int 48 cloak_cfgen( ConfigArgs *c ) 49 { 50 slap_overinst *on = (slap_overinst *)c->bi; 51 cloak_info_t *ci = (cloak_info_t *)on->on_bi.bi_private; 52 53 int rc = 0, i; 54 55 if ( c->op == SLAP_CONFIG_EMIT ) { 56 switch( c->type ) { 57 case CLOAK_ATTR: 58 for ( i = 0; ci; i++, ci = ci->ci_next ) { 59 struct berval bv; 60 int len; 61 62 assert( ci->ci_ad != NULL ); 63 64 if ( ci->ci_oc != NULL ) 65 len = snprintf( c->cr_msg, 66 sizeof( c->cr_msg ), 67 SLAP_X_ORDERED_FMT "%s %s", i, 68 ci->ci_ad->ad_cname.bv_val, 69 ci->ci_oc->soc_cname.bv_val ); 70 else 71 len = snprintf( c->cr_msg, 72 sizeof( c->cr_msg ), 73 SLAP_X_ORDERED_FMT "%s", i, 74 ci->ci_ad->ad_cname.bv_val ); 75 76 bv.bv_val = c->cr_msg; 77 bv.bv_len = len; 78 value_add_one( &c->rvalue_vals, &bv ); 79 } 80 break; 81 82 default: 83 rc = 1; 84 break; 85 } 86 87 return rc; 88 89 } else if ( c->op == LDAP_MOD_DELETE ) { 90 cloak_info_t *ci_next; 91 92 switch( c->type ) { 93 case CLOAK_ATTR: 94 for ( ci_next = ci, i = 0; 95 ci_next, c->valx < 0 || i < c->valx; 96 ci = ci_next, i++ ){ 97 98 ci_next = ci->ci_next; 99 100 ch_free ( ci->ci_ad ); 101 if ( ci->ci_oc != NULL ) 102 ch_free ( ci->ci_oc ); 103 104 ch_free( ci ); 105 } 106 ci = (cloak_info_t *)on->on_bi.bi_private; 107 break; 108 109 default: 110 rc = 1; 111 break; 112 } 113 114 return rc; 115 } 116 117 switch( c->type ) { 118 case CLOAK_ATTR: { 119 ObjectClass *oc = NULL; 120 AttributeDescription *ad = NULL; 121 const char *text; 122 cloak_info_t **cip = NULL; 123 cloak_info_t *ci_next = NULL; 124 125 if ( c->argc == 3 ) { 126 oc = oc_find( c->argv[ 2 ] ); 127 if ( oc == NULL ) { 128 snprintf( c->cr_msg, 129 sizeof( c->cr_msg ), 130 CLOAK_USAGE 131 "unable to find ObjectClass \"%s\"", 132 c->argv[ 2 ] ); 133 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", 134 c->log, c->cr_msg, 0 ); 135 return 1; 136 } 137 } 138 139 rc = slap_str2ad( c->argv[ 1 ], &ad, &text ); 140 if ( rc != LDAP_SUCCESS ) { 141 snprintf( c->cr_msg, sizeof( c->cr_msg ), CLOAK_USAGE 142 "unable to find AttributeDescription \"%s\"", 143 c->argv[ 1 ] ); 144 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", 145 c->log, c->cr_msg, 0 ); 146 return 1; 147 } 148 149 for ( i = 0, cip = (cloak_info_t **)&on->on_bi.bi_private; 150 c->valx < 0 || i < c->valx, *cip; 151 i++, cip = &(*cip)->ci_next ) { 152 if ( c->valx >= 0 && *cip == NULL ) { 153 snprintf( c->cr_msg, sizeof( c->cr_msg ), 154 CLOAK_USAGE 155 "invalid index {%d}\n", 156 c->valx ); 157 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", 158 c->log, c->cr_msg, 0 ); 159 return 1; 160 } 161 ci_next = *cip; 162 } 163 164 *cip = (cloak_info_t *)ch_calloc( 1, sizeof( cloak_info_t ) ); 165 (*cip)->ci_oc = oc; 166 (*cip)->ci_ad = ad; 167 (*cip)->ci_next = ci_next; 168 169 rc = 0; 170 break; 171 } 172 173 default: 174 rc = 1; 175 break; 176 } 177 178 return rc; 179 } 180 181 static int 182 cloak_search_cb( Operation *op, SlapReply *rs ) 183 { 184 slap_callback *sc; 185 cloak_info_t *ci; 186 Entry *e = NULL; 187 Entry *me = NULL; 188 189 assert( op && op->o_callback && rs ); 190 191 if ( rs->sr_type != REP_SEARCH || !rs->sr_entry ) { 192 slap_freeself_cb( op, rs ); 193 return ( SLAP_CB_CONTINUE ); 194 } 195 196 sc = op->o_callback; 197 e = rs->sr_entry; 198 199 /* 200 * First perform a quick scan for an attribute to cloak 201 */ 202 for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { 203 Attribute *a; 204 205 if ( ci->ci_oc != NULL && 206 !is_entry_objectclass_or_sub( e, ci->ci_oc ) ) 207 continue; 208 209 for ( a = e->e_attrs; a; a = a->a_next ) 210 if ( a->a_desc == ci->ci_ad ) 211 break; 212 213 if ( a != NULL ) 214 break; 215 } 216 217 /* 218 * Nothing found to cloak 219 */ 220 if ( ci == NULL ) 221 return ( SLAP_CB_CONTINUE ); 222 223 /* 224 * We are now committed to cloak an attribute. 225 */ 226 if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) 227 me = e; 228 else 229 me = entry_dup( e ); 230 231 for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { 232 Attribute *a; 233 Attribute *pa; 234 235 for ( pa = NULL, a = me->e_attrs; 236 a; 237 pa = a, a = a->a_next ) { 238 239 if ( a->a_desc != ci->ci_ad ) 240 continue; 241 242 Debug( LDAP_DEBUG_TRACE, "cloak_search_cb: cloak %s\n", 243 a->a_desc->ad_cname.bv_val, 244 0, 0 ); 245 246 if ( pa != NULL ) 247 pa->a_next = a->a_next; 248 else 249 me->e_attrs = a->a_next; 250 251 attr_clean( a ); 252 } 253 254 } 255 256 if ( me != e ) { 257 if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) 258 entry_free( e ); 259 260 rs->sr_entry = me; 261 rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; 262 } 263 264 return ( SLAP_CB_CONTINUE ); 265 } 266 267 static int 268 cloak_search( Operation *op, SlapReply *rs ) 269 { 270 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 271 cloak_info_t *ci = (cloak_info_t *)on->on_bi.bi_private; 272 slap_callback *sc; 273 274 if ( op->ors_attrsonly || 275 op->ors_attrs || 276 get_manageDSAit( op ) ) 277 return SLAP_CB_CONTINUE; 278 279 sc = op->o_tmpcalloc( 1, sizeof( *sc ), op->o_tmpmemctx ); 280 sc->sc_response = cloak_search_cb; 281 sc->sc_cleanup = slap_freeself_cb; 282 sc->sc_next = op->o_callback; 283 sc->sc_private = ci; 284 op->o_callback = sc; 285 286 return SLAP_CB_CONTINUE; 287 } 288 289 static slap_overinst cloak_ovl; 290 291 static ConfigTable cloakcfg[] = { 292 { "cloak-attr", "attribute [class]", 293 2, 3, 0, ARG_MAGIC|CLOAK_ATTR, cloak_cfgen, 294 "( OLcfgCtAt:4.1 NAME 'olcCloakAttribute' " 295 "DESC 'Cloaked attribute: attribute [class]' " 296 "EQUALITY caseIgnoreMatch " 297 "SYNTAX OMsDirectoryString " 298 "X-ORDERED 'VALUES' )", 299 NULL, NULL }, 300 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 301 }; 302 303 static ConfigOCs cloakocs[] = { 304 { "( OLcfgCtOc:4.1 " 305 "NAME 'olcCloakConfig' " 306 "DESC 'Attribute cloak configuration' " 307 "SUP olcOverlayConfig " 308 "MAY ( olcCloakAttribute ) )", 309 Cft_Overlay, cloakcfg }, 310 { NULL, 0, NULL } 311 }; 312 313 #if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC 314 static 315 #endif 316 int 317 cloak_initialize( void ) { 318 int rc; 319 cloak_ovl.on_bi.bi_type = "cloak"; 320 cloak_ovl.on_bi.bi_op_search = cloak_search; 321 cloak_ovl.on_bi.bi_cf_ocs = cloakocs; 322 323 rc = config_register_schema ( cloakcfg, cloakocs ); 324 if ( rc ) 325 return rc; 326 327 return overlay_register( &cloak_ovl ); 328 } 329 330 #if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC 331 int init_module(int argc, char *argv[]) { 332 return cloak_initialize(); 333 } 334 #endif 335 336 #endif /* defined(SLAPD_OVER_CLOAK) */ 337 338