Skip to content
Snippets Groups Projects
Commit 362766b3 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

move compare to frontend (disabled by default, only invoked if backend doesn't...

move compare to frontend (disabled by default, only invoked if backend doesn't provide hook); honor ITS#3472 (disclose access check); fix ITS#3521 as well (check access to hasSubordinates); fix a problem in backend_attribute() with operational attrs; add backend_access() helper
parent 1b268479
No related branches found
No related tags found
No related merge requests found
......@@ -555,11 +555,11 @@ backend_db_init(
/* assign a default depth limit for alias deref */
be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
if(bi->bi_db_init) {
if ( bi->bi_db_init ) {
rc = bi->bi_db_init( be );
}
if(rc != 0) {
if ( rc != 0 ) {
fprintf( stderr, "database init failed (%s)\n", type );
nbackends--;
return NULL;
......@@ -583,6 +583,7 @@ be_db_close( void )
if ( frontendDB->bd_info->bi_db_close ) {
(*frontendDB->bd_info->bi_db_close)( frontendDB );
}
}
Backend *
......@@ -1479,13 +1480,21 @@ backend_attribute(
BER_BVZERO( &anlist[ 1 ].an_name );
rs.sr_attrs = anlist;
rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
rc = backend_operational( op, &rs );
/* NOTE: backend_operational() is also called
* when returning results, so it's supposed
* to do no harm to entries */
rs.sr_entry = e;
rc = backend_operational( op, &rs );
rs.sr_entry = NULL;
if ( rc == LDAP_SUCCESS ) {
if ( rs.sr_operational_attrs ) {
freeattr = 1;
a = rs.sr_operational_attrs;
if ( rc == LDAP_SUCCESS && rs.sr_operational_attrs ) {
freeattr = 1;
a = rs.sr_operational_attrs;
} else {
rc = LDAP_NO_SUCH_ATTRIBUTE;
}
}
}
......@@ -1567,6 +1576,144 @@ freeit: if ( e != target ) {
return rc;
}
#ifdef LDAP_SLAPI
static int backend_compute_output_attr_access(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e)
{
struct berval *nval = (struct berval *)c->cac_private;
Operation *op = NULL;
slapi_pblock_get( c->cac_pb, SLAPI_OPERATION, &op );
if ( op == NULL ) {
return 1;
}
return access_allowed( op, e, a->a_desc, nval, ACL_AUTH, NULL ) == 0;
}
#endif /* LDAP_SLAPI */
int
backend_access(
Operation *op,
Entry *target,
struct berval *edn,
AttributeDescription *entry_at,
struct berval *nval,
slap_access_t access,
slap_mask_t *mask )
{
Entry *e = NULL;
int rc = LDAP_INSUFFICIENT_ACCESS;
Backend *be = op->o_bd;
/* pedantic */
assert( op );
assert( op->o_conn );
assert( edn );
assert( access > ACL_NONE );
op->o_bd = select_backend( edn, 0, 0 );
if ( target && dn_match( &target->e_nname, edn ) ) {
e = target;
} else {
rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
}
if ( e ) {
Attribute *a = NULL;
int freeattr = 0;
if ( entry_at == NULL ) {
entry_at = slap_schema.si_ad_entry;
}
if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children )
{
if ( access_allowed_mask( op, e, entry_at,
NULL, access, NULL, mask ) == 0 )
{
rc = LDAP_INSUFFICIENT_ACCESS;
} else {
rc = LDAP_SUCCESS;
}
} else {
a = attr_find( e->e_attrs, entry_at );
if ( a == NULL ) {
SlapReply rs = { 0 };
AttributeName anlist[ 2 ];
anlist[ 0 ].an_name = entry_at->ad_cname;
anlist[ 0 ].an_desc = entry_at;
BER_BVZERO( &anlist[ 1 ].an_name );
rs.sr_attrs = anlist;
rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
/* NOTE: backend_operational() is also called
* when returning results, so it's supposed
* to do no harm to entries */
rs.sr_entry = e;
rc = backend_operational( op, &rs );
rs.sr_entry = NULL;
if ( rc == LDAP_SUCCESS ) {
if ( rs.sr_operational_attrs ) {
freeattr = 1;
a = rs.sr_operational_attrs;
} else {
rc = LDAP_NO_SUCH_OBJECT;
}
}
}
if ( a ) {
if ( access_allowed_mask( op, e, entry_at,
nval, access, NULL, mask ) == 0 )
{
rc = LDAP_INSUFFICIENT_ACCESS;
goto freeit;
}
rc = LDAP_SUCCESS;
}
#ifdef LDAP_SLAPI
else if ( op->o_pb ) {
/* try any computed attributes */
computed_attr_context ctx;
slapi_int_pblock_set_operation( op->o_pb, op );
ctx.cac_pb = op->o_pb;
ctx.cac_attrs = NULL;
ctx.cac_userattrs = 0;
ctx.cac_opattrs = 0;
ctx.cac_private = (void *)nval;
rc = compute_evaluator( &ctx, entry_at->ad_cname.bv_val, e, backend_compute_output_attr_access );
if ( rc == 1 ) {
rc = LDAP_INSUFFICIENT_ACCESS;
} else {
rc = LDAP_SUCCESS;
}
}
#endif /* LDAP_SLAPI */
}
freeit: if ( e != target ) {
be_entry_release_r( op, e );
}
if ( freeattr ) {
attr_free( a );
}
}
op->o_bd = be;
return rc;
}
int backend_operational(
Operation *op,
SlapReply *rs )
......@@ -1583,15 +1730,15 @@ int backend_operational(
* and the backend supports specific operational attributes,
* add them to the attribute list
*/
if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
ad_inlist( slap_schema.si_ad_entryDN, op->ors_attrs )))
if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
ad_inlist( slap_schema.si_ad_entryDN, rs->sr_attrs )))
{
*ap = slap_operational_entryDN( rs->sr_entry );
ap = &(*ap)->a_next;
}
if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
ad_inlist( slap_schema.si_ad_subschemaSubentry, op->ors_attrs )))
if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
ad_inlist( slap_schema.si_ad_subschemaSubentry, rs->sr_attrs )))
{
*ap = slap_operational_subschemaSubentry( op->o_bd );
ap = &(*ap)->a_next;
......@@ -1602,7 +1749,7 @@ int backend_operational(
if ( SLAP_ISOVERLAY( be_orig ))
op->o_bd = select_backend( be_orig->be_nsuffix, 0, 0 );
if (( SLAP_OPATTRS( rs->sr_attr_flags ) || op->ors_attrs ) &&
if (( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
op->o_bd && op->o_bd->be_operational != NULL )
{
Attribute *a;
......
......@@ -274,6 +274,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"subschemaSubentry compare not supported" );
#ifndef SLAP_COMPARE_IN_FRONTEND
} else if ( ava.aa_desc == slap_schema.si_ad_hasSubordinates
&& op->o_bd->be_has_subordinates )
{
......@@ -281,9 +282,16 @@ fe_op_compare( Operation *op, SlapReply *rs )
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
if ( rc == 0 && entry ) {
rc = op->o_bd->be_has_subordinates( op, entry,
&hasSubordinates );
be_entry_release_r( op, entry );
if ( ! access_allowed( op, entry,
ava.aa_desc, &ava.aa_value, ACL_COMPARE, NULL ) )
{
rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
} else {
rc = rs->sr_err = op->o_bd->be_has_subordinates( op,
entry, &hasSubordinates );
be_entry_release_r( op, entry );
}
}
if ( rc == 0 ) {
......@@ -293,20 +301,90 @@ fe_op_compare( Operation *op, SlapReply *rs )
? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
if ( hasSubordinates == asserted ) {
rs->sr_err = LDAP_COMPARE_TRUE;
} else {
rs->sr_err = LDAP_COMPARE_FALSE;
}
} else {
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* return error only if "disclose"
* is granted on the object */
if ( backend_access( op, NULL, &op->o_req_ndn,
slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
#endif /* SLAP_ACL_HONOR_DISCLOSE */
}
send_ldap_result( op, rs );
if( rc == 0 ) rs->sr_err = LDAP_SUCCESS;
if ( rc == 0 ) {
rs->sr_err = LDAP_SUCCESS;
}
} else if ( op->o_bd->be_compare ) {
op->o_bd->be_compare( op, rs );
#endif /* ! SLAP_COMPARE_IN_FRONTEND */
} else {
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"operation not supported within namingContext" );
/* do our best to compare that AVA
*
* NOTE: this code is used only
* if SLAP_COMPARE_IN_FRONTEND
* is #define'd (it's not by default)
* or if op->o_bd->be_compare is NULL.
*
* FIXME: one potential issue is that
* if SLAP_COMPARE_IN_FRONTEND overlays
* are not executed for compare. */
BerVarray vals = NULL;
int rc = LDAP_OTHER;
rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
ava.aa_desc, &vals, ACL_COMPARE );
switch ( rs->sr_err ) {
default:
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* return error only if "disclose"
* is granted on the object */
if ( backend_access( op, NULL, &op->o_req_ndn,
slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL )
== LDAP_INSUFFICIENT_ACCESS )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
}
#endif /* SLAP_ACL_HONOR_DISCLOSE */
break;
case LDAP_SUCCESS:
if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
vals, &ava.aa_value, op->o_tmpmemctx ) == 0 )
{
rs->sr_err = LDAP_COMPARE_TRUE;
break;
} else {
rs->sr_err = LDAP_COMPARE_FALSE;
}
rc = LDAP_SUCCESS;
break;
}
send_ldap_result( op, rs );
if ( rc == 0 ) {
rs->sr_err = LDAP_SUCCESS;
}
if ( vals ) {
ber_bvarray_free_x( vals, op->o_tmpmemctx );
}
}
#if defined( LDAP_SLAPI )
......
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