diff --git a/CHANGES b/CHANGES index 0b266a2df548defb1ea6ed2c0c8e62340269c370..4bb5f22edbf0fdf1958843d96c38b68d87dd4b1c 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ OpenLDAP 2.4.13 Engineering Fixed libldap interaction with GnuTLS CN IP-based matches (ITS#5789) Fixed libldap Ipv6 detection (ITS#5739) Fixed slapd acl checks on ADD (ITS#4556,ITS#5723) + Fixed slapd acl application to newly created backends (ITS#5572) Added slapd keyword add_content_acl for add checks (ITS#4556,ITS#5723) Fixed slapd config backend olcLogFile support (ITS#5765) Fixed slapd contextCSN pending list (ITS#5709) diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index a9c2a791550d483972226bd8fa82edb8df7d7b3e..c04f3044b09442184d522d6c73b4777e8dfa6c37 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -138,6 +138,7 @@ slap_access_allowed( slap_access_t access_level; const char *attr; regmatch_t matches[MAXREMATCHES]; + AccessControlState acl_state = ACL_STATE_INIT; assert( op != NULL ); assert( e != NULL ); @@ -179,7 +180,7 @@ slap_access_allowed( } /* use backend default access if no backend acls */ - if ( op->o_bd->be_acl == NULL ) { + if ( op->o_bd->be_acl == NULL && frontendDB->be_acl == NULL ) { int i; Debug( LDAP_DEBUG_ACL, @@ -201,15 +202,22 @@ slap_access_allowed( ret = 0; control = ACL_BREAK; - if ( state && state->as_vd_ad == desc ) { + if ( state == NULL ) + state = &acl_state; + if ( state->as_vd_ad == desc ) { a = state->as_vd_acl; count = state->as_vd_acl_count; - + if ( state->as_fe_done ) + state->as_fe_done--; } else { - if ( state ) state->as_vi_acl = NULL; + state->as_vi_acl = NULL; + a = NULL; count = 0; } + if ( a == NULL ) + state->as_fe_done = 0; + ACL_PRIV_ASSIGN( mask, *maskp ); memset( matches, '\0', sizeof( matches ) ); @@ -476,13 +484,14 @@ slap_acl_get( assert( e != NULL ); assert( count != NULL ); assert( desc != NULL ); + assert( state != NULL ); attr = desc->ad_cname.bv_val; assert( attr != NULL ); if( a == NULL ) { - if( op->o_bd == NULL ) { + if( op->o_bd == NULL || op->o_bd->be_acl == NULL ) { a = frontendDB->be_acl; } else { a = op->o_bd->be_acl; @@ -490,7 +499,8 @@ slap_acl_get( prev = NULL; assert( a != NULL ); - + if ( a == frontendDB->be_acl ) + state->as_fe_done = 1; } else { prev = a; a = a->acl_next; @@ -498,9 +508,13 @@ slap_acl_get( dnlen = e->e_nname.bv_len; + retry: for ( ; a != NULL; prev = a, a = a->acl_next ) { (*count) ++; + if ( a != frontendDB->be_acl && state->as_fe_done ) + state->as_fe_done++; + if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) { if ( a->acl_dn_style == ACL_STYLE_REGEX ) { Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n", @@ -567,7 +581,7 @@ slap_acl_get( continue; } - if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { + if( !( state->as_recorded & ACL_STATE_RECORDED_VD )) { state->as_recorded |= ACL_STATE_RECORDED_VD; state->as_vd_acl = prev; state->as_vd_acl_count = *count - 1; @@ -649,6 +663,12 @@ slap_acl_get( return a; } + if ( !state->as_fe_done ) { + state->as_fe_done = 1; + a = frontendDB->be_acl; + goto retry; + } + Debug( LDAP_DEBUG_ACL, "<= acl_get: done.\n", 0, 0, 0 ); return( NULL ); } @@ -1856,7 +1876,7 @@ acl_check_modlist( } /* use backend default access if no backend acls */ - if( op->o_bd != NULL && op->o_bd->be_acl == NULL ) { + if( op->o_bd != NULL && op->o_bd->be_acl == NULL && frontendDB->be_acl == NULL ) { Debug( LDAP_DEBUG_ACL, "=> access_allowed: backend default %s access %s to \"%s\"\n", access2str( ACL_WRITE ), diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 29910379d373121ecf287762f5b65f8e2ba78692..1679f2b0e8f16fbe0deb3ad9077ab602a28908ba 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -2449,19 +2449,12 @@ acl_free( AccessControl *a ) free( a ); } -/* Because backend_startup uses acl_append to tack on the global_acl to - * the end of each backend's acl, we cannot just take one argument and - * merrily free our way to the end of the list. backend_destroy calls us - * with the be_acl in arg1, and global_acl in arg2 to give us a stopping - * point. config_destroy calls us with global_acl in arg1 and NULL in - * arg2, so we then proceed to polish off the global_acl. - */ void -acl_destroy( AccessControl *a, AccessControl *end ) +acl_destroy( AccessControl *a ) { AccessControl *n; - for ( ; a && a != end; a = n ) { + for ( ; a; a = n ) { n = a->acl_next; acl_free( a ); } diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 3754a258f20af6203dbce3bc5d295c85632fd207..0a573ca1a19cebddcf63c22da17410c5a7f933e8 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -261,8 +261,6 @@ int backend_startup(Backend *be) return rc; } } - /* append global access controls */ - acl_append( &be->be_acl, frontendDB->be_acl, -1 ); return backend_startup_one( be, &cr ); } @@ -310,8 +308,6 @@ int backend_startup(Backend *be) "has no suffix\n", i, be->bd_info->bi_type, 0 ); } - /* append global access controls */ - acl_append( &be->be_acl, frontendDB->be_acl, -1 ); rc = backend_startup_one( be, &cr ); @@ -453,7 +449,7 @@ void backend_destroy_one( BackendDB *bd, int dynamic ) if ( !BER_BVISNULL( &bd->be_rootpw ) ) { free( bd->be_rootpw.bv_val ); } - acl_destroy( bd->be_acl, frontendDB->be_acl ); + acl_destroy( bd->be_acl ); limits_destroy( bd->be_limits ); if ( !BER_BVISNULL( &bd->be_update_ndn ) ) { ch_free( bd->be_update_ndn.bv_val ); @@ -504,7 +500,8 @@ int backend_destroy(void) if ( !BER_BVISNULL( &bd->be_rootpw ) ) { free( bd->be_rootpw.bv_val ); } - acl_destroy( bd->be_acl, frontendDB->be_acl ); + acl_destroy( bd->be_acl ); + frontendDB = NULL; } return 0; diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 0d1431923b1127e26f1cb7c8152ba167a12d9592..8c1a9b91db18443bd076f062f036ae959d716c43 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -979,12 +979,7 @@ config_generic(ConfigArgs *c) { AccessControl *a; char *src, *dst, ibuf[11]; struct berval bv, abv; - AccessControl *end; - if ( c->be == frontendDB ) - end = NULL; - else - end = frontendDB->be_acl; - for (i=0, a=c->be->be_acl; a && a != end; i++,a=a->acl_next) { + for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) { abv.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i ); if ( abv.bv_len >= sizeof( ibuf ) ) { ber_bvarray_free_x( c->rvalue_vals, NULL ); @@ -1220,13 +1215,8 @@ config_generic(ConfigArgs *c) { case CFG_ACL: if ( c->valx < 0 ) { - AccessControl *end; - if ( c->be == frontendDB ) - end = NULL; - else - end = frontendDB->be_acl; - acl_destroy( c->be->be_acl, end ); - c->be->be_acl = end; + acl_destroy( c->be->be_acl ); + c->be->be_acl = NULL; } else { AccessControl **prev, *a; @@ -1691,11 +1681,10 @@ sortval_reject: case CFG_ACL: /* Don't append to the global ACL if we're on a specific DB */ i = c->valx; - if ( c->be != frontendDB && frontendDB->be_acl && c->valx == -1 ) { + if ( c->valx == -1 ) { AccessControl *a; i = 0; - for ( a=c->be->be_acl; a && a != frontendDB->be_acl; - a = a->acl_next ) + for ( a=c->be->be_acl; a; a = a->acl_next ) i++; } if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) { @@ -5920,7 +5909,7 @@ config_back_db_open( BackendDB *be, ConfigReply *cr ) /* If we have no explicitly configured ACLs, don't just use * the global ACLs. Explicitly deny access to everything. */ - if ( frontendDB->be_acl && be->be_acl == frontendDB->be_acl ) { + if ( !be->be_acl ) { parse_acl(be, "config_back_db_open", 0, 6, (char **)defacl, 0 ); } diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 368fb9cef62c883dc787c326587b274d98285cb2..a81ab852c9588e332dfc6463f5804af459c419c8 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -1984,7 +1984,7 @@ config_destroy( ) if ( frontendDB->be_schemadn.bv_val ) free( frontendDB->be_schemadn.bv_val ); if ( frontendDB->be_acl ) - acl_destroy( frontendDB->be_acl, NULL ); + acl_destroy( frontendDB->be_acl ); } free( line ); if ( slapd_args_file ) diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 1d08b5488ab10147ab7b1e5e25f91ac630d87df3..560ffc3f2d1d785fd71ce9b2b454d731f55c4caf 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -111,7 +111,7 @@ LDAP_SLAPD_F (slap_access_t) str2access LDAP_P(( const char *str )); LDAP_SLAPD_F (char *) accessmask2str LDAP_P(( slap_mask_t mask, char*, int debug )); LDAP_SLAPD_F (slap_mask_t) str2accessmask LDAP_P(( const char *str )); LDAP_SLAPD_F (void) acl_unparse LDAP_P(( AccessControl*, struct berval* )); -LDAP_SLAPD_F (void) acl_destroy LDAP_P(( AccessControl*, AccessControl* )); +LDAP_SLAPD_F (void) acl_destroy LDAP_P(( AccessControl* )); LDAP_SLAPD_F (void) acl_free LDAP_P(( AccessControl *a )); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index ae7d51b8d61d5370423ae6127350d81b18aec4a5..9a699456d3eced23274a6c3d7753e2f0c3ad896e 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1542,9 +1542,10 @@ typedef struct AccessControlState { slap_acl_state_t as_recorded; int as_vd_acl_count; int as_result; + int as_fe_done; } AccessControlState; #define ACL_STATE_INIT { NULL, NULL, NULL, \ - ACL_STATE_NOT_RECORDED, 0, 0 } + ACL_STATE_NOT_RECORDED, 0, 0, 0 } /* * Backend-info