Back to index

openldap  2.4.31
cloak.c
Go to the documentation of this file.
00001 /* cloak.c - Overlay to hide some attribute except if explicitely requested */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2008-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2008 Emmanuel Dreyfus
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 originally developed by the Emmanuel Dreyfus for
00019  * inclusion in OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #ifdef SLAPD_OVER_CLOAK
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 enum { CLOAK_ATTR = 1 };
00036 
00037 typedef struct cloak_info_t {
00038        ObjectClass          *ci_oc;       
00039        AttributeDescription *ci_ad;
00040        struct cloak_info_t  *ci_next;
00041 } cloak_info_t;
00042 
00043 #define CLOAK_USAGE "\"cloak-attr <attr> [<class>]\": "
00044 
00045 static int
00046 cloak_cfgen( ConfigArgs *c )
00047 {
00048        slap_overinst *on = (slap_overinst *)c->bi;
00049        cloak_info_t  *ci = (cloak_info_t *)on->on_bi.bi_private;
00050 
00051        int           rc = 0, i;
00052 
00053        if ( c->op == SLAP_CONFIG_EMIT ) {
00054               switch( c->type ) {
00055               case CLOAK_ATTR:
00056                      for ( i = 0; ci; i++, ci = ci->ci_next ) {
00057                             struct berval bv;
00058                             int len;
00059 
00060                             assert( ci->ci_ad != NULL );
00061 
00062                             if ( ci->ci_oc != NULL )
00063                                    len = snprintf( c->cr_msg, 
00064                                    sizeof( c->cr_msg ),
00065                                    SLAP_X_ORDERED_FMT "%s %s", i,
00066                                    ci->ci_ad->ad_cname.bv_val,
00067                                    ci->ci_oc->soc_cname.bv_val );
00068                             else
00069                                    len = snprintf( c->cr_msg, 
00070                                    sizeof( c->cr_msg ),
00071                                    SLAP_X_ORDERED_FMT "%s", i,
00072                                    ci->ci_ad->ad_cname.bv_val );
00073 
00074                             bv.bv_val = c->cr_msg;
00075                             bv.bv_len = len;
00076                             value_add_one( &c->rvalue_vals, &bv );
00077                      }
00078                      break;
00079 
00080               default:
00081                      rc = 1;
00082                      break;
00083               }
00084 
00085               return rc;
00086 
00087        } else if ( c->op == LDAP_MOD_DELETE ) {
00088               cloak_info_t  *ci_next;
00089 
00090               switch( c->type ) {
00091               case CLOAK_ATTR:
00092                      for ( ci_next = ci, i = 0; 
00093                            ci_next, c->valx < 0 || i < c->valx; 
00094                            ci = ci_next, i++ ){
00095 
00096                             ci_next = ci->ci_next;
00097 
00098                             ch_free ( ci->ci_ad );
00099                             if ( ci->ci_oc != NULL )
00100                                    ch_free ( ci->ci_oc );
00101 
00102                             ch_free( ci );
00103                      }
00104                      ci = (cloak_info_t *)on->on_bi.bi_private;
00105                      break;
00106 
00107               default:
00108                      rc = 1;
00109                      break;
00110               }
00111 
00112               return rc;
00113        }
00114 
00115        switch( c->type ) {
00116        case CLOAK_ATTR: {
00117               ObjectClass          *oc = NULL;
00118               AttributeDescription *ad = NULL;
00119               const char           *text;
00120               cloak_info_t         **cip = NULL;
00121               cloak_info_t          *ci_next = NULL;
00122 
00123               if ( c->argc == 3 ) {
00124                      oc = oc_find( c->argv[ 2 ] );
00125                      if ( oc == NULL ) {
00126                             snprintf( c->cr_msg, 
00127                                      sizeof( c->cr_msg ), 
00128                                      CLOAK_USAGE
00129                                      "unable to find ObjectClass \"%s\"",
00130                                      c->argv[ 2 ] );
00131                             Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
00132                                    c->log, c->cr_msg, 0 );
00133                             return 1;
00134                      }
00135               }
00136 
00137               rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
00138               if ( rc != LDAP_SUCCESS ) {
00139                      snprintf( c->cr_msg, sizeof( c->cr_msg ), CLOAK_USAGE
00140                             "unable to find AttributeDescription \"%s\"",
00141                             c->argv[ 1 ] );
00142                      Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
00143                             c->log, c->cr_msg, 0 );
00144                      return 1;
00145               }
00146 
00147               for ( i = 0, cip = (cloak_info_t **)&on->on_bi.bi_private;
00148                     c->valx < 0 || i < c->valx, *cip;
00149                     i++, cip = &(*cip)->ci_next ) {
00150                      if ( c->valx >= 0 && *cip == NULL ) {
00151                             snprintf( c->cr_msg, sizeof( c->cr_msg ),
00152                                    CLOAK_USAGE
00153                                    "invalid index {%d}\n",
00154                                    c->valx );
00155                             Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
00156                                    c->log, c->cr_msg, 0 );
00157                             return 1;
00158                      }
00159                      ci_next = *cip;
00160               }
00161 
00162               *cip = (cloak_info_t *)SLAP_CALLOC( 1, sizeof( cloak_info_t ) );
00163               (*cip)->ci_oc = oc;
00164               (*cip)->ci_ad = ad;
00165               (*cip)->ci_next = ci_next;
00166 
00167               rc = 0;
00168               break;
00169        }
00170 
00171        default:
00172               rc = 1;
00173               break;
00174        }
00175 
00176        return rc;
00177 }
00178 
00179 static int
00180 cloak_search_response_cb( Operation *op, SlapReply *rs )
00181 {
00182        slap_callback   *sc;
00183        cloak_info_t  *ci;
00184        Entry         *e = NULL;
00185        Entry         *me = NULL;
00186 
00187        assert( op && op->o_callback && rs );
00188 
00189        if ( rs->sr_type != REP_SEARCH || !rs->sr_entry ) {
00190               return ( SLAP_CB_CONTINUE );
00191        }
00192 
00193        sc = op->o_callback;
00194        e = rs->sr_entry;
00195 
00196        /* 
00197         * First perform a quick scan for an attribute to cloak
00198         */
00199        for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) {
00200               Attribute *a;
00201 
00202               if ( ci->ci_oc != NULL &&
00203                    !is_entry_objectclass_or_sub( e, ci->ci_oc ) )
00204                      continue;
00205 
00206               for ( a = e->e_attrs; a; a = a->a_next )
00207                      if ( a->a_desc == ci->ci_ad )
00208                             break;
00209 
00210               if ( a != NULL )
00211                      break;
00212        }
00213 
00214        /*
00215         * Nothing found to cloak
00216         */
00217        if ( ci == NULL )
00218               return ( SLAP_CB_CONTINUE );
00219 
00220        /*
00221         * We are now committed to cloak an attribute.
00222         */
00223        rs_entry2modifiable( op, rs, (slap_overinst *) op->o_bd->bd_info );
00224        me = rs->sr_entry;
00225               
00226        for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) {
00227               Attribute *a;
00228               Attribute *pa;
00229 
00230               for ( pa = NULL, a = me->e_attrs;
00231                     a; 
00232                     pa = a, a = a->a_next ) {
00233 
00234                      if ( a->a_desc != ci->ci_ad )
00235                             continue;
00236 
00237                      Debug( LDAP_DEBUG_TRACE, "cloak_search_response_cb: cloak %s\n", 
00238                             a->a_desc->ad_cname.bv_val,
00239                             0, 0 );
00240 
00241                      if ( pa != NULL ) 
00242                             pa->a_next = a->a_next;
00243                      else
00244                             me->e_attrs = a->a_next;
00245 
00246                      attr_clean( a );
00247               }
00248 
00249        }
00250 
00251        return ( SLAP_CB_CONTINUE );
00252 }
00253 
00254 static int
00255 cloak_search_cleanup_cb( Operation *op, SlapReply *rs )
00256 {
00257        if ( rs->sr_type == REP_RESULT || rs->sr_err != LDAP_SUCCESS ) {
00258               slap_freeself_cb( op, rs );
00259        }
00260 
00261        return SLAP_CB_CONTINUE;
00262 }
00263 
00264 static int
00265 cloak_search( Operation *op, SlapReply *rs )
00266 {
00267        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
00268        cloak_info_t    *ci = (cloak_info_t *)on->on_bi.bi_private; 
00269        slap_callback *sc;
00270 
00271        if ( op->ors_attrsonly ||
00272             op->ors_attrs ||
00273             get_manageDSAit( op ) )
00274               return SLAP_CB_CONTINUE;
00275 
00276        sc = op->o_tmpcalloc( 1, sizeof( *sc ), op->o_tmpmemctx );
00277        sc->sc_response = cloak_search_response_cb;
00278        sc->sc_cleanup = cloak_search_cleanup_cb;
00279        sc->sc_next = op->o_callback;
00280        sc->sc_private = ci;
00281        op->o_callback = sc;
00282 
00283        return SLAP_CB_CONTINUE;
00284 }
00285 
00286 static slap_overinst cloak_ovl;
00287 
00288 static ConfigTable cloakcfg[] = {
00289        { "cloak-attr", "attribute [class]",
00290               2, 3, 0, ARG_MAGIC|CLOAK_ATTR, cloak_cfgen,
00291               "( OLcfgCtAt:4.1 NAME 'olcCloakAttribute' "
00292                      "DESC 'Cloaked attribute: attribute [class]' "
00293                      "EQUALITY caseIgnoreMatch "
00294                      "SYNTAX OMsDirectoryString "
00295                      "X-ORDERED 'VALUES' )",
00296                      NULL, NULL },
00297        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
00298 };
00299 
00300 static int
00301 cloak_db_destroy(
00302        BackendDB *be,
00303        ConfigReply *cr )
00304 {
00305        slap_overinst *on = (slap_overinst *)be->bd_info;
00306        cloak_info_t  *ci = (cloak_info_t *)on->on_bi.bi_private;
00307 
00308        for ( ; ci; ) {
00309               cloak_info_t *tmp = ci;
00310               ci = ci->ci_next;
00311               SLAP_FREE( tmp );
00312        }
00313 
00314        on->on_bi.bi_private = NULL;
00315 
00316        return 0;
00317 }
00318 
00319 static ConfigOCs cloakocs[] = {
00320        { "( OLcfgCtOc:4.1 "
00321          "NAME 'olcCloakConfig' "
00322          "DESC 'Attribute cloak configuration' "
00323          "SUP olcOverlayConfig "
00324          "MAY ( olcCloakAttribute ) )", 
00325          Cft_Overlay, cloakcfg },
00326        { NULL, 0, NULL }
00327 };
00328 
00329 #if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC
00330 static
00331 #endif
00332 int
00333 cloak_initialize( void ) {
00334        int rc;
00335        cloak_ovl.on_bi.bi_type = "cloak";
00336        cloak_ovl.on_bi.bi_db_destroy = cloak_db_destroy;
00337        cloak_ovl.on_bi.bi_op_search = cloak_search;
00338         cloak_ovl.on_bi.bi_cf_ocs = cloakocs;
00339 
00340        rc = config_register_schema ( cloakcfg, cloakocs );
00341        if ( rc ) 
00342               return rc;
00343 
00344        return overlay_register( &cloak_ovl );
00345 }
00346 
00347 #if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC
00348 int init_module(int argc, char *argv[]) {
00349        return cloak_initialize();
00350 }
00351 #endif
00352 
00353 #endif /* defined(SLAPD_OVER_CLOAK) */
00354