openldap/contrib/slapd-modules/cloak/cloak.c
Kurt Zeilenga a5abeb92ec Update contrib notices to reflect that they are distributed as part of
OpenLDAP Software (though they may not necessarily be supported by the
OpenLDAP Project).  Assistance in updating ACKNOWLEDGEMENTS welcomed.
2009-08-16 22:55:23 +00:00

336 lines
7.0 KiB
C

/* cloak.c - Overlay to hide some attribute except if explicitely requested */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2008-2009 The OpenLDAP Foundation.
* Portions Copyright 2008 Emmanuel Dreyfus
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was originally developed by the Emmanuel Dreyfus for
* inclusion in OpenLDAP Software.
*/
#include "portable.h"
#ifdef SLAPD_OVER_CLOAK
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "lutil.h"
#include "slap.h"
#include "config.h"
enum { CLOAK_ATTR = 1 };
typedef struct cloak_info_t {
ObjectClass *ci_oc;
AttributeDescription *ci_ad;
struct cloak_info_t *ci_next;
} cloak_info_t;
#define CLOAK_USAGE "\"cloak-attr <attr> [<class>]\": "
static int
cloak_cfgen( ConfigArgs *c )
{
slap_overinst *on = (slap_overinst *)c->bi;
cloak_info_t *ci = (cloak_info_t *)on->on_bi.bi_private;
int rc = 0, i;
if ( c->op == SLAP_CONFIG_EMIT ) {
switch( c->type ) {
case CLOAK_ATTR:
for ( i = 0; ci; i++, ci = ci->ci_next ) {
struct berval bv;
int len;
assert( ci->ci_ad != NULL );
if ( ci->ci_oc != NULL )
len = snprintf( c->cr_msg,
sizeof( c->cr_msg ),
SLAP_X_ORDERED_FMT "%s %s", i,
ci->ci_ad->ad_cname.bv_val,
ci->ci_oc->soc_cname.bv_val );
else
len = snprintf( c->cr_msg,
sizeof( c->cr_msg ),
SLAP_X_ORDERED_FMT "%s", i,
ci->ci_ad->ad_cname.bv_val );
bv.bv_val = c->cr_msg;
bv.bv_len = len;
value_add_one( &c->rvalue_vals, &bv );
}
break;
default:
rc = 1;
break;
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) {
cloak_info_t *ci_next;
switch( c->type ) {
case CLOAK_ATTR:
for ( ci_next = ci, i = 0;
ci_next, c->valx < 0 || i < c->valx;
ci = ci_next, i++ ){
ci_next = ci->ci_next;
ch_free ( ci->ci_ad );
if ( ci->ci_oc != NULL )
ch_free ( ci->ci_oc );
ch_free( ci );
}
ci = (cloak_info_t *)on->on_bi.bi_private;
break;
default:
rc = 1;
break;
}
return rc;
}
switch( c->type ) {
case CLOAK_ATTR: {
ObjectClass *oc = NULL;
AttributeDescription *ad = NULL;
const char *text;
cloak_info_t **cip = NULL;
cloak_info_t *ci_next = NULL;
if ( c->argc == 3 ) {
oc = oc_find( c->argv[ 2 ] );
if ( oc == NULL ) {
snprintf( c->cr_msg,
sizeof( c->cr_msg ),
CLOAK_USAGE
"unable to find ObjectClass \"%s\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
}
rc = slap_str2ad( c->argv[ 1 ], &ad, &text );
if ( rc != LDAP_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ), CLOAK_USAGE
"unable to find AttributeDescription \"%s\"",
c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
for ( i = 0, cip = (cloak_info_t **)&on->on_bi.bi_private;
c->valx < 0 || i < c->valx, *cip;
i++, cip = &(*cip)->ci_next ) {
if ( c->valx >= 0 && *cip == NULL ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
CLOAK_USAGE
"invalid index {%d}\n",
c->valx );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
ci_next = *cip;
}
*cip = (cloak_info_t *)ch_calloc( 1, sizeof( cloak_info_t ) );
(*cip)->ci_oc = oc;
(*cip)->ci_ad = ad;
(*cip)->ci_next = ci_next;
rc = 0;
break;
}
default:
rc = 1;
break;
}
return rc;
}
static int
cloak_search_cb( Operation *op, SlapReply *rs )
{
slap_callback *sc;
cloak_info_t *ci;
Entry *e = NULL;
Entry *me = NULL;
assert( op && op->o_callback && rs );
if ( rs->sr_type != REP_SEARCH || !rs->sr_entry ) {
slap_freeself_cb( op, rs );
return ( SLAP_CB_CONTINUE );
}
sc = op->o_callback;
e = rs->sr_entry;
/*
* First perform a quick scan for an attribute to cloak
*/
for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) {
Attribute *a;
if ( ci->ci_oc != NULL &&
!is_entry_objectclass_or_sub( e, ci->ci_oc ) )
continue;
for ( a = e->e_attrs; a; a = a->a_next )
if ( a->a_desc == ci->ci_ad )
break;
if ( a != NULL )
break;
}
/*
* Nothing found to cloak
*/
if ( ci == NULL )
return ( SLAP_CB_CONTINUE );
/*
* We are now committed to cloak an attribute.
*/
if ( rs->sr_flags & REP_ENTRY_MODIFIABLE )
me = e;
else
me = entry_dup( e );
for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) {
Attribute *a;
Attribute *pa;
for ( pa = NULL, a = me->e_attrs;
a;
pa = a, a = a->a_next ) {
if ( a->a_desc != ci->ci_ad )
continue;
Debug( LDAP_DEBUG_TRACE, "cloak_search_cb: cloak %s\n",
a->a_desc->ad_cname.bv_val,
0, 0 );
if ( pa != NULL )
pa->a_next = a->a_next;
else
me->e_attrs = a->a_next;
attr_clean( a );
}
}
if ( me != e ) {
if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED )
entry_free( e );
rs->sr_entry = me;
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
}
return ( SLAP_CB_CONTINUE );
}
static int
cloak_search( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
cloak_info_t *ci = (cloak_info_t *)on->on_bi.bi_private;
slap_callback *sc;
if ( op->ors_attrsonly ||
op->ors_attrs ||
get_manageDSAit( op ) )
return SLAP_CB_CONTINUE;
sc = op->o_tmpcalloc( 1, sizeof( *sc ), op->o_tmpmemctx );
sc->sc_response = cloak_search_cb;
sc->sc_cleanup = slap_freeself_cb;
sc->sc_next = op->o_callback;
sc->sc_private = ci;
op->o_callback = sc;
return SLAP_CB_CONTINUE;
}
static slap_overinst cloak_ovl;
static ConfigTable cloakcfg[] = {
{ "cloak-attr", "attribute [class]",
2, 3, 0, ARG_MAGIC|CLOAK_ATTR, cloak_cfgen,
"( OLcfgCtAt:4.1 NAME 'olcCloakAttribute' "
"DESC 'Cloaked attribute: attribute [class]' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString "
"X-ORDERED 'VALUES' )",
NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
static ConfigOCs cloakocs[] = {
{ "( OLcfgCtOc:4.1 "
"NAME 'olcCloakConfig' "
"DESC 'Attribute cloak configuration' "
"SUP olcOverlayConfig "
"MAY ( olcCloakAttribute ) )",
Cft_Overlay, cloakcfg },
{ NULL, 0, NULL }
};
#if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC
static
#endif
int
cloak_initialize( void ) {
int rc;
cloak_ovl.on_bi.bi_type = "cloak";
cloak_ovl.on_bi.bi_op_search = cloak_search;
cloak_ovl.on_bi.bi_cf_ocs = cloakocs;
rc = config_register_schema ( cloakcfg, cloakocs );
if ( rc )
return rc;
return overlay_register( &cloak_ovl );
}
#if SLAPD_OVER_CLOAK == SLAPD_MOD_DYNAMIC
int init_module(int argc, char *argv[]) {
return cloak_initialize();
}
#endif
#endif /* defined(SLAPD_OVER_CLOAK) */