1 /* $NetBSD: cloak.c,v 1.1.1.3 2014/05/28 09:58:27 tron Exp $ */ 2 3 /* cloak.c - Overlay to hide some attribute except if explicitely requested */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2008-2014 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 *)SLAP_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_response_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 return ( SLAP_CB_CONTINUE ); 193 } 194 195 sc = op->o_callback; 196 e = rs->sr_entry; 197 198 /* 199 * First perform a quick scan for an attribute to cloak 200 */ 201 for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { 202 Attribute *a; 203 204 if ( ci->ci_oc != NULL && 205 !is_entry_objectclass_or_sub( e, ci->ci_oc ) ) 206 continue; 207 208 for ( a = e->e_attrs; a; a = a->a_next ) 209 if ( a->a_desc == ci->ci_ad ) 210 break; 211 212 if ( a != NULL ) 213 break; 214 } 215 216 /* 217 * Nothing found to cloak 218 */ 219 if ( ci == NULL ) 220 return ( SLAP_CB_CONTINUE ); 221 222 /* 223 * We are now committed to cloak an attribute. 224 */ 225 rs_entry2modifiable( op, rs, (slap_overinst *) op->o_bd->bd_info ); 226 me = rs->sr_entry; 227 228 for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { 229 Attribute *a; 230 Attribute *pa; 231 232 for ( pa = NULL, a = me->e_attrs; 233 a; 234 pa = a, a = a->a_next ) { 235 236 if ( a->a_desc != ci->ci_ad ) 237 continue; 238 239 Debug( LDAP_DEBUG_TRACE, "cloak_search_response_cb: cloak %s\n", 240 a->a_desc->ad_cname.bv_val, 241 0, 0 ); 242 243 if ( pa != NULL ) 244 pa->a_next = a->a_next; 245 else 246 me->e_attrs = a->a_next; 247 248 attr_clean( a ); 249 } 250 251 } 252 253 return ( SLAP_CB_CONTINUE ); 254 } 255 256 static int 257 cloak_search_cleanup_cb( Operation *op, SlapReply *rs ) 258 { 259 if ( rs->sr_type == REP_RESULT || rs->sr_err != LDAP_SUCCESS ) { 260 slap_freeself_cb( op, rs ); 261 } 262 263 return SLAP_CB_CONTINUE; 264 } 265 266 static int 267 cloak_search( Operation *op, SlapReply *rs ) 268 { 269 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; 270 cloak_info_t *ci = (cloak_info_t *)on->on_bi.bi_private; 271 slap_callback *sc; 272 273 if ( op->ors_attrsonly || 274 op->ors_attrs || 275 get_manageDSAit( op ) ) 276 return SLAP_CB_CONTINUE; 277 278 sc = op->o_tmpcalloc( 1, sizeof( *sc ), op->o_tmpmemctx ); 279 sc->sc_response = cloak_search_response_cb; 280 sc->sc_cleanup = cloak_search_cleanup_cb; 281 sc->sc_next = op->o_callback; 282 sc->sc_private = ci; 283 op->o_callback = sc; 284 285 return SLAP_CB_CONTINUE; 286 } 287 288 static slap_overinst cloak_ovl; 289 290 static ConfigTable cloakcfg[] = { 291 { "cloak-attr", "attribute [class]", 292 2, 3, 0, ARG_MAGIC|CLOAK_ATTR, cloak_cfgen, 293 "( OLcfgCtAt:4.1 NAME 'olcCloakAttribute' " 294 "DESC 'Cloaked attribute: attribute [class]' " 295 "EQUALITY caseIgnoreMatch " 296 "SYNTAX OMsDirectoryString " 297 "X-ORDERED 'VALUES' )", 298 NULL, NULL }, 299 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 300 }; 301 302 static int 303 cloak_db_destroy( 304 BackendDB *be, 305 ConfigReply *cr ) 306 { 307 slap_overinst *on = (slap_overinst *)be->bd_info; 308 cloak_info_t *ci = (cloak_info_t *)on->on_bi.bi_private; 309 310 for ( ; ci; ) { 311 cloak_info_t *tmp = ci; 312 ci = ci->ci_next; 313 SLAP_FREE( tmp ); 314 } 315 316 on->on_bi.bi_private = NULL; 317 318 return 0; 319 } 320 321 static ConfigOCs cloakocs[] = { 322 { "( OLcfgCtOc:4.1 " 323 "NAME 'olcCloakConfig' " 324 "DESC 'Attribute cloak configuration' " 325 "SUP olcOverlayConfig " 326 "MAY ( olcCloakAttribute ) )", 327 Cft_Overlay, cloakcfg }, 328 { NULL, 0, NULL } 329 }; 330 331 #if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC 332 static 333 #endif 334 int 335 cloak_initialize( void ) { 336 int rc; 337 cloak_ovl.on_bi.bi_type = "cloak"; 338 cloak_ovl.on_bi.bi_db_destroy = cloak_db_destroy; 339 cloak_ovl.on_bi.bi_op_search = cloak_search; 340 cloak_ovl.on_bi.bi_cf_ocs = cloakocs; 341 342 rc = config_register_schema ( cloakcfg, cloakocs ); 343 if ( rc ) 344 return rc; 345 346 return overlay_register( &cloak_ovl ); 347 } 348 349 #if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC 350 int init_module(int argc, char *argv[]) { 351 return cloak_initialize(); 352 } 353 #endif 354 355 #endif /* defined(SLAPD_OVER_CLOAK) */ 356 357