Commit 57e262e5 authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#5872

parent 95b8abe9
......@@ -22,6 +22,7 @@ OpenLDAP 2.4.14 Engineering
Fixed slapd-meta double response sending (ITS#5854)
Fixed slapo-ppolicy to not be global (ITS#5858)
Updated contrib/addpartial module (ITS#5764)
Added contrib/cloak module (ITS#5872)
Build Environment
Fixed test049,test050 to work on windows (ITS#5842)
Removed patch for BerkeleyDB 4.7.25 (Official patch available)
......
......@@ -3,3 +3,4 @@ List of OpenLDAP Configuration OIDs allocated to contrib modules
OLcfgCt{Oc|At}:1 smbk5pwd
OLcfgCt{Oc|At}:2 autogroup
OLcfgCt{Oc|At}:3 nssov
OLcfgCt{Oc|At}:4 cloak
......@@ -20,6 +20,9 @@ allop (overlay)
autogroup (overlay)
Automated updates of group memberships.
cloak (overlay)
Hide specific attributes unless explicitely requested
comp_match (plugin)
Component Matching rules (RFC 3687).
......
/* $OpenLDAP$ */
/* cloak.c - Overlay to hide some attribute except if explicitely requested */
/*
* 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>.
*/
#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 = NULL;
sc->sc_next = NULL;
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) */
.TH SLAPO-CLOAK 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" Copyright 1998-2008 The OpenLDAP Foundation, All Rights Reserved.
.\" Copying restrictions apply. See the COPYRIGHT file.
.\" $OpenLDAP$
.SH NAME
slapo-cloak \- Attribute cloak overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The
.B cloak
overlay to
.BR slapd (8)
allows the server to hide specific attributes, unless explicitely requested
by the client. This improve performance when a client requests all attributes
and get a huge binary attribute that is of no interest for it.
This behavior is disabled when the \fImanageDSAit\fP
control (RFC 3296) is used.
.SH CONFIGURATION
The config directives that are specific to the
.B cloak
overlay must be prefixed by
.BR cloak\- ,
to avoid potential conflicts with directives specific to the underlying
database or to other stacked overlays.
.TP
.B overlay cloak
This directive adds the cloak overlay to the current database,
or to the frontend, if used before any database instantiation; see
.BR slapd.conf (5)
for details.
.LP
This
.B slapd.conf
configuration option is defined for the cloak overlay. It may have multiple
occurrences, and it must appear after the
.B overlay
directive:
.TP
.B cloak-attr <attribute> [<class>]
The value
.B <attribute>
is the name of the attribute that will be cloaked.
The optional
.B <class>
restricts cloaking only to entries of the named
.B <class>.
.SH EXAMPLE
This example hide the
.B jpegPhoto
attribute. Add the following to slapd.conf:
.LP
.nf
database <database>
# ...
overlay cloak
cloak-attr jpegPhoto
.fi
.LP
and that slapd loads cloak.la, if compiled as a run-time module;
.SH FILES
.TP
ETCDIR/slapd.conf
default slapd configuration file
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8).
The
.BR slapo-cloak (5)
overlay supports dynamic configuration via
.BR back-config .
.SH ACKNOWLEDGEMENTS
.P
This module was written in 2008 by Emmanuel Dreyfus.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment