]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/aclparse.c
Fix ITS#3424
[openldap] / servers / slapd / aclparse.c
index 69bf5db066ec8a9905be0f668744dad9bd8c7c86..17f0274d561b0e601bc19e9011d384038f0a3579 100644 (file)
@@ -67,6 +67,45 @@ static int
 check_scope( BackendDB *be, AccessControl *a );
 #endif /* LDAP_DEVEL */
 
+#ifdef SLAP_DYNACL
+static int
+slap_dynacl_config( const char *fname, int lineno, Access *b, const char *name, slap_style_t sty, const char *right )
+{
+       slap_dynacl_t   *da, *tmp;
+       int             rc = 0;
+
+       for ( da = b->a_dynacl; da; da = da->da_next ) {
+               if ( strcasecmp( da->da_name, name ) == 0 ) {
+                       fprintf( stderr,
+                               "%s: line %d: dynacl \"%s\" already specified.\n",
+                               fname, lineno, name );
+                       acl_usage();
+               }
+       }
+
+       da = slap_dynacl_get( name );
+       if ( da == NULL ) {
+               return -1;
+       }
+
+       tmp = ch_malloc( sizeof( slap_dynacl_t ) );
+       *tmp = *da;
+
+       if ( tmp->da_parse ) {
+               rc = ( *tmp->da_parse )( fname, lineno, sty, right, &tmp->da_private );
+               if ( rc ) {
+                       ch_free( tmp );
+                       return rc;
+               }
+       }
+
+       tmp->da_next = b->a_dynacl;
+       b->a_dynacl = tmp;
+
+       return 0;
+}
+#endif /* SLAP_DYNACL */
+
 static void
 regtest(const char *fname, int lineno, char *pat) {
        int e;
@@ -148,12 +187,14 @@ check_scope( BackendDB *be, AccessControl *a )
                slap_style_t    style = a->acl_dn_style;
 
                if ( style == ACL_STYLE_REGEX ) {
-                       char    dnbuf[SLAP_LDAPDN_MAXLEN + 2];
-                       char    rebuf[SLAP_LDAPDN_MAXLEN + 1];
-                       regex_t re;
-                       int     rc;
+                       char            dnbuf[SLAP_LDAPDN_MAXLEN + 2];
+                       char            rebuf[SLAP_LDAPDN_MAXLEN + 1];
+                       ber_len_t       rebuflen;
+                       regex_t         re;
+                       int             rc;
                        
-                       /* add trailing '$' */
+                       /* add trailing '$' to database suffix to form
+                        * a simple trial regex pattern "<suffix>$" */
                        AC_MEMCPY( dnbuf, be->be_nsuffix[0].bv_val,
                                be->be_nsuffix[0].bv_len );
                        dnbuf[be->be_nsuffix[0].bv_len] = '$';
@@ -163,17 +204,26 @@ check_scope( BackendDB *be, AccessControl *a )
                                return ACL_SCOPE_WARN;
                        }
 
-                       /* remove trailing '$' */
-                       AC_MEMCPY( rebuf, a->acl_dn_pat.bv_val,
-                               a->acl_dn_pat.bv_len + 1 );
-                       if ( a->acl_dn_pat.bv_val[a->acl_dn_pat.bv_len - 1] == '$' ) {
-                               rebuf[a->acl_dn_pat.bv_len - 1] = '\0';
+                       /* remove trailing ')$', if any, from original
+                        * regex pattern */
+                       rebuflen = a->acl_dn_pat.bv_len;
+                       AC_MEMCPY( rebuf, a->acl_dn_pat.bv_val, rebuflen + 1 );
+                       if ( rebuf[rebuflen - 1] == '$' ) {
+                               rebuf[--rebuflen] = '\0';
+                       }
+                       while ( rebuflen > be->be_nsuffix[0].bv_len && rebuf[rebuflen - 1] == ')' ) {
+                               rebuf[--rebuflen] = '\0';
+                       }
+                       if ( rebuflen == be->be_nsuffix[0].bv_len ) {
+                               rc = ACL_SCOPE_WARN;
+                               goto regex_done;
                        }
 
                        /* not a clear indication of scoping error, though */
                        rc = regexec( &re, rebuf, 0, NULL, 0 )
                                ? ACL_SCOPE_WARN : ACL_SCOPE_OK;
 
+regex_done:;
                        regfree( &re );
                        return rc;
                }
@@ -187,8 +237,8 @@ check_scope( BackendDB *be, AccessControl *a )
                        /* base is blatantly wrong */
                        if ( style == ACL_STYLE_BASE ) return ACL_SCOPE_ERR;
 
-                       /* one can be wrong if there is more
-                        * than one level between the suffix
+                       /* a style of one can be wrong if there is
+                        * more than one level between the suffix
                         * and the pattern */
                        if ( style == ACL_STYLE_ONE ) {
                                int     rdnlen = -1, sep = 0;
@@ -1000,7 +1050,7 @@ parse_acl(
                                                acl_usage();
                                        }
 
-                                       if ( BER_BVISEMPTY( &b->a_peername_pat ) ) {
+                                       if ( !BER_BVISEMPTY( &b->a_peername_pat ) ) {
                                                fprintf( stderr, "%s: line %d: "
                                                        "peername pattern already specified.\n",
                                                        fname, lineno );
@@ -1263,6 +1313,30 @@ parse_acl(
                                        continue;
                                }
 
+#ifdef SLAP_DYNACL
+                               {
+                                       char            *name = NULL;
+                                       
+                                       if ( strcasecmp( left, "aci" ) == 0 ) {
+                                               name = "aci";
+                                               
+                                       } else if ( strncasecmp( left, "dynacl/", STRLENOF( "dynacl/" ) ) == 0 ) {
+                                               name = &left[ STRLENOF( "dynacl/" ) ];
+                                       }
+
+                                       if ( name ) {
+                                               if ( slap_dynacl_config( fname, lineno, b, name, sty, right ) ) {
+                                                       fprintf( stderr, "%s: line %d: "
+                                                               "unable to configure dynacl \"%s\"\n",
+                                                               fname, lineno, name );
+                                                       acl_usage();
+                                               }
+
+                                               continue;
+                                       }
+                               }
+#else /* ! SLAP_DYNACL */
+
 #ifdef SLAPD_ACI_ENABLED
                                if ( strcasecmp( left, "aci" ) == 0 ) {
                                        if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
@@ -1306,6 +1380,7 @@ parse_acl(
                                        continue;
                                }
 #endif /* SLAPD_ACI_ENABLED */
+#endif /* ! SLAP_DYNACL */
 
                                if ( strcasecmp( left, "ssf" ) == 0 ) {
                                        if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
@@ -1579,6 +1654,14 @@ parse_acl(
 
                if ( be != NULL ) {
 #ifdef LDAP_DEVEL
+                       if ( !BER_BVISNULL( &be->be_nsuffix[ 1 ] ) ) {
+                               fprintf( stderr, "%s: line %d: warning: "
+                                       "scope checking only applies to single-valued "
+                                       "suffix databases\n",
+                                       fname, lineno );
+                               /* go ahead, since checking is not authoritative */
+                       }
+
                        switch ( check_scope( be, a ) ) {
                        case ACL_SCOPE_UNKNOWN:
                                fprintf( stderr, "%s: line %d: warning: "
@@ -2069,11 +2152,23 @@ print_access( Access *b )
                fprintf( stderr, " set=\"%s\"", b->a_set_pat.bv_val );
        }
 
+#ifdef SLAP_DYNACL
+       if ( b->a_dynacl ) {
+               slap_dynacl_t   *da;
+
+               for ( da = b->a_dynacl; da; da = da->da_next ) {
+                       if ( da->da_print ) {
+                               (void)( *da->da_print )( da->da_private );
+                       }
+               }
+       }
+#else /* ! SLAP_DYNACL */
 #ifdef SLAPD_ACI_ENABLED
        if ( b->a_aci_at != NULL ) {
                fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
        }
 #endif
+#endif /* SLAP_DYNACL */
 
        /* Security Strength Factors */
        if ( b->a_authz.sai_ssf ) {
@@ -2145,8 +2240,11 @@ print_acl( Backend *be, AccessControl *a )
                        if ( ! first ) fprintf( stderr, "," );
                        if (an->an_oc) {
                                fputc( an->an_oc_exclude ? '!' : '@', stderr);
+                               fputs( an->an_oc->soc_cname.bv_val, stderr );
+
+                       } else {
+                               fputs( an->an_name.bv_val, stderr );
                        }
-                       fputs( an->an_name.bv_val, stderr );
                        first = 0;
                }
                fprintf(  stderr, "\n" );