Skip to content
Snippets Groups Projects
Commit a143720b authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#4730

parent bb38cb8e
No related branches found
No related tags found
No related merge requests found
......@@ -23,13 +23,14 @@ OpenLDAP 2.4.18 Engineering
Fixed slapd-relay response/cleanup callback mismatch (ITS#6154)
Fixed slapd-sql with baseObject query (ITS#6172)
Fixed slapd-sql with empty attribute (ITS#6163)
Added slapo-pcache olcProxyCacheOffline (ITS#6152)
Fixed slapo-pcache multiple enhancements (ITS#6152)
Fixed slapo-translucent attribute return (ITS#6254)
Fixed slapo-translucent filter matching (ITS#6255)
Fixed slapo-translucent to honor sizelimit (ITS#6253)
Fixed slapo-unique filter matching (ITS#6077)
Fixed tools off by one error (ITS#6233)
Fixed tools resource leaks (ITS#6145)
Added contrib/allowed (ITS#4730)
Fixed contrib/autogroup with RE24 (ITS#6227)
Fixed contrib/nss symbols (ITS#6273)
Build Environment
......
This directory contains a slapd overlay, "allowed".
--- o --- o --- o ---
It adds to entries returned by search operations the value of attributes
"allowedAttributes"
<http://msdn.microsoft.com/en-us/library/ms675217(VS.85).aspx>
"allowedAttributesEffective"
<http://msdn.microsoft.com/en-us/library/ms675218(VS.85).aspx>
No other use is made of those attributes: they cannot be compared,
they cannot be used in search filters, they cannot be used in ACLs, ...
--- o --- o --- o ---
Other attributes like
"allowedChildClasses"
<http://msdn.microsoft.com/en-us/library/ms675219(VS.85).aspx>
"allowedChildClassesEffective"
<http://msdn.microsoft.com/en-us/library/ms675220(VS.85).aspx>
make little sense within OpenLDAP's slapd right now, since any AUXILIARY
objectClass can be added to an entry, while no STRUCTURAL objectClass can.
This may change when DIT structure rules are implemented, while ACLs may
restrict what AUXILIARY objectClasses can be added to an entry.
--- o --- o --- o ---
Usage: add to slapd.conf(5)
moduleload path/to/allowed.so
overlay allowed
or add
dn: olcOverlay={0}allowed,olcDatabase={1}bdb,cn=config
objectClass: olcOverlayConfig
olcOverlay: {0}allowed
as a child of the database that's intended to support this feature
(replace "olcDatabase={1}bdb,cn=config" with the appropriate parent);
or use
dn: olcOverlay={0}allowed,olcDatabase={-1}frontend,cn=config
objectClass: olcOverlayConfig
olcOverlay: {0}allowed
if it's supposed to be global.
--- o --- o --- o ---
No Makefile is provided. Use a command line similar to:
gcc -shared -I../../../include -I../../../servers/slapd -Wall -g \
-o allowed.so allowed.c
to compile this overlay, or even better use OpenLDAP's libtool as appropriate.
---
This work is part of OpenLDAP Software <http://www.openldap.org/>.
Copyright 2006-2009 The OpenLDAP Foundation. 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.
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 initially developed by Pierangelo Masarati for inclusion in
OpenLDAP Software.
/* allowed.c - add allowed attributes based on ACL */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2006-2009 The OpenLDAP Foundation.
* 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 initially developed by Pierangelo Masarati for inclusion in
* OpenLDAP Software.
*/
/*
* Rationale: return in allowedAttributes the attributes required/allowed
* by the objectClasses that are currently present in an object; return
* in allowedAttributesEffective the subset of the above that can be written
* by the identity that performs the search.
*
* Caveats:
* - right now, the overlay assumes that all values of the objectClass
* attribute will be returned in rs->sr_entry; this may not be true
* in general, but it usually is for back-bdb/back-hdb. To generalize,
* the search request should be analyzed, and if allowedAttributes or
* allowedAttributesEffective are requested, add objectClass to the
* requested attributes
* - it assumes that there is no difference between write-add and
* write-delete
* - it assumes that access rules do not depend on the values of the
* attributes or on the contents of the entry (attr/val, filter, ...)
* allowedAttributes and allowedAttributesEffective cannot be used
* in filters or in compare
*/
#include "portable.h"
/* define SLAPD_OVER_ALLOWED=2 to build as run-time loadable module */
#ifdef SLAPD_OVER_ALLOWED
#include "slap.h"
/*
* Schema from
*
* <http://www.redhat.com/archives/fedora-directory-devel/2006-August/msg00007.html>
*
* posted by Andrew Bartlett
*/
#define AA_SCHEMA_AT "1.2.840.113556.1.4"
static AttributeDescription
*ad_allowedChildClasses,
*ad_allowedChildClassesEffective,
*ad_allowedAttributes,
*ad_allowedAttributesEffective;
static struct {
char *at;
AttributeDescription **ad;
} aa_attrs[] = {
{ "( " AA_SCHEMA_AT ".911 "
"NAME 'allowedChildClasses' "
"EQUALITY objectIdentifierMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
/* added by me :) */
"DESC 'Child classes allowed for a given object' "
"NO-USER-MODIFICATION "
"USAGE directoryOperation )", &ad_allowedChildClasses },
{ "( " AA_SCHEMA_AT ".912 "
"NAME 'allowedChildClassesEffective' "
"EQUALITY objectIdentifierMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
/* added by me :) */
"DESC 'Child classes allowed for a given object according to ACLs' "
"NO-USER-MODIFICATION "
"USAGE directoryOperation )", &ad_allowedChildClassesEffective },
{ "( " AA_SCHEMA_AT ".913 "
"NAME 'allowedAttributes' "
"EQUALITY objectIdentifierMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
/* added by me :) */
"DESC 'Attributes allowed for a given object' "
"NO-USER-MODIFICATION "
"USAGE directoryOperation )", &ad_allowedAttributes },
{ "( " AA_SCHEMA_AT ".914 "
"NAME 'allowedAttributesEffective' "
"EQUALITY objectIdentifierMatch "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
/* added by me :) */
"DESC 'Attributes allowed for a given object according to ACLs' "
"NO-USER-MODIFICATION "
"USAGE directoryOperation )", &ad_allowedAttributesEffective },
/* TODO: add objectClass stuff? */
{ NULL, NULL }
};
static int
aa_add_at( AttributeType *at, AttributeType ***atpp )
{
int i = 0;
if ( *atpp ) {
for ( i = 0; (*atpp)[ i ] != NULL; i++ ) {
if ( (*atpp)[ i ] == at ) {
break;
}
}
if ( (*atpp)[ i ] != NULL ) {
return 0;
}
}
*atpp = ch_realloc( *atpp, sizeof( AttributeType * ) * ( i + 2 ) );
(*atpp)[ i ] = at;
(*atpp)[ i + 1 ] = NULL;
return 0;
}
static int
aa_add_oc( ObjectClass *oc, ObjectClass ***ocpp, AttributeType ***atpp )
{
int i = 0;
if ( *ocpp ) {
for ( ; (*ocpp)[ i ] != NULL; i++ ) {
if ( (*ocpp)[ i ] == oc ) {
break;
}
}
if ( (*ocpp)[ i ] != NULL ) {
return 0;
}
}
*ocpp = ch_realloc( *ocpp, sizeof( ObjectClass * ) * ( i + 2 ) );
(*ocpp)[ i ] = oc;
(*ocpp)[ i + 1 ] = NULL;
if ( oc->soc_required ) {
int i;
for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) {
aa_add_at( oc->soc_required[ i ], atpp );
}
}
if ( oc->soc_allowed ) {
int i;
for ( i = 0; oc->soc_allowed[ i ] != NULL; i++ ) {
aa_add_at( oc->soc_allowed[ i ], atpp );
}
}
return 0;
}
static int
aa_operational( Operation *op, SlapReply *rs )
{
Attribute *a, **ap;
AccessControlState acl_state = ACL_STATE_INIT;
struct berval *v;
AttributeType **atp = NULL;
ObjectClass **ocp = NULL;
BerVarray bv_allowed = NULL,
bv_effective = NULL;
int i, ja = 0, je = 0;
#define GOT_NONE (0x0U)
#define GOT_C (0x1U)
#define GOT_CE (0x2U)
#define GOT_A (0x4U)
#define GOT_AE (0x8U)
#define GOT_ALL (GOT_C|GOT_CE|GOT_A|GOT_AE)
int got = GOT_NONE;
/* only add if requested */
if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) {
got = GOT_ALL;
} else {
if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) {
got |= GOT_C;
}
if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) {
got |= GOT_CE;
}
if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) {
got |= GOT_A;
}
if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) {
got |= GOT_AE;
}
}
if ( got == GOT_NONE ) {
return SLAP_CB_CONTINUE;
}
/* shouldn't be called without an entry; please check */
assert( rs->sr_entry != NULL );
/* see caveats; this is not guaranteed for all backends */
a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
if ( a == NULL ) {
return SLAP_CB_CONTINUE;
}
/* if client has no access to objectClass attribute; don't compute */
if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass,
NULL, ACL_READ, &acl_state ) )
{
return SLAP_CB_CONTINUE;
}
for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) {
ObjectClass *oc = oc_bvfind( v );
assert( oc != NULL );
/* if client has no access to specific value, don't compute */
if ( !access_allowed( op, rs->sr_entry,
slap_schema.si_ad_objectClass,
&oc->soc_cname, ACL_READ, &acl_state ) )
{
continue;
}
aa_add_oc( oc, &ocp, &atp );
if ( oc->soc_sups ) {
for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) {
aa_add_oc( oc->soc_sups[ i ], &ocp, &atp );
}
}
}
if ( atp != NULL ) {
for ( i = 0; atp[ i ] != NULL; i++ )
/* just count */ ;
if ( got & GOT_A ) {
bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
}
if ( got & GOT_AE ) {
bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) );
}
for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) {
if ( got & GOT_A ) {
ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname );
ja++;
}
if ( got & GOT_AE ) {
AttributeDescription *ad = NULL;
const char *text = NULL;
if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) {
/* log? */
continue;
}
if ( access_allowed( op, rs->sr_entry,
ad, NULL, ACL_WRITE, NULL ) )
{
ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname );
je++;
}
}
}
for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next )
/* go to last */ ;
if ( ( got & GOT_A ) && ja > 0 ) {
BER_BVZERO( &bv_allowed[ ja ] );
*ap = attr_alloc( ad_allowedAttributes );
(*ap)->a_vals = bv_allowed;
(*ap)->a_nvals = bv_allowed;
(*ap)->a_numvals = ja;
ap = &(*ap)->a_next;
}
if ( ( got & GOT_AE ) && je > 0 ) {
BER_BVZERO( &bv_effective[ je ] );
*ap = attr_alloc( ad_allowedAttributesEffective );
(*ap)->a_vals = bv_effective;
(*ap)->a_nvals = bv_effective;
(*ap)->a_numvals = je;
ap = &(*ap)->a_next;
}
*ap = NULL;
}
ch_free( atp );
ch_free( ocp );
return SLAP_CB_CONTINUE;
}
static slap_overinst aa;
#if LDAP_VENDOR_VERSION_MINOR != X && LDAP_VENDOR_VERSION_MINOR <= 3
/* backport register_at() from HEAD, to allow building with OL <= 2.3 */
static int
register_at( char *def, AttributeDescription **rad, int dupok )
{
LDAPAttributeType *at;
int code, freeit = 0;
const char *err;
AttributeDescription *ad = NULL;
at = ldap_str2attributetype( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
if ( !at ) {
Debug( LDAP_DEBUG_ANY,
"register_at: AttributeType \"%s\": %s, %s\n",
def, ldap_scherr2str(code), err );
return code;
}
code = at_add( at, 0, NULL, &err );
if ( code ) {
if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) {
freeit = 1;
} else {
ldap_attributetype_free( at );
Debug( LDAP_DEBUG_ANY,
"register_at: AttributeType \"%s\": %s, %s\n",
def, scherr2str(code), err );
return code;
}
}
code = slap_str2ad( at->at_names[0], &ad, &err );
if ( freeit || code ) {
ldap_attributetype_free( at );
} else {
ldap_memfree( at );
}
if ( code ) {
Debug( LDAP_DEBUG_ANY, "register_at: AttributeType \"%s\": %s\n",
def, err, 0 );
}
if ( rad ) *rad = ad;
return code;
}
#endif
#if SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC
static
#endif /* SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC */
int
aa_initialize( void )
{
int i;
aa.on_bi.bi_type = "allowed";
aa.on_bi.bi_operational = aa_operational;
/* aa schema integration */
for ( i = 0; aa_attrs[i].at; i++ ) {
int code;
code = register_at( aa_attrs[i].at, aa_attrs[i].ad, 0 );
if ( code ) {
Debug( LDAP_DEBUG_ANY,
"aa_initialize: register_at failed\n", 0, 0, 0 );
return -1;
}
}
return overlay_register( &aa );
}
#if SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC
int
init_module( int argc, char *argv[] )
{
return aa_initialize();
}
#endif /* SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC */
#endif /* SLAPD_OVER_ALLOWED */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment