]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/aclparse.c
document option '-F'
[openldap] / servers / slapd / aclparse.c
index 1a77a9527f18438a79206745b29fafce957e216d..fddae6b13a5eec2f6a9fbe8fdb2e6db8a78150b0 100644 (file)
@@ -45,7 +45,11 @@ static char *style_strings[] = {
        "one",
        "subtree",
        "children",
+       "level",
        "attrof",
+       "anonymous",
+       "users",
+       "self",
        "ip",
        "path",
        NULL
@@ -585,14 +589,39 @@ parse_acl(
 
                        /* get <who> */
                        for ( ; i < argc; i++ ) {
-                               slap_style_t sty = ACL_STYLE_REGEX;
-                               char *style_modifier = NULL;
-                               int expand = 0;
+                               slap_style_t    sty = ACL_STYLE_REGEX;
+                               char            *style_modifier = NULL;
+                               char            *style_level = NULL;
+                               int             level = 0;
+                               int             expand = 0;
+                               slap_dn_access  *bdn = &b->a_dn;
+                               int             is_realdn = 0;
 
                                split( argv[i], '=', &left, &right );
                                split( left, '.', &left, &style );
                                if ( style ) {
-                                       split( style, ',', &style, &style_modifier);
+                                       split( style, ',', &style, &style_modifier );
+
+                                       if ( strncasecmp( style, "level", STRLENOF( "level" ) ) == 0 ) {
+                                               split( style, '{', &style, &style_level );
+                                               if ( style_level != NULL ) {
+                                                       char *p = strchr( style_level, '}' );
+                                                       if ( p == NULL ) {
+                                                               fprintf( stderr,
+                                                                       "%s: line %d: premature eol: "
+                                                                       "expecting closing '}' in \"level{n}\"\n",
+                                                                       fname, lineno );
+                                                               acl_usage();
+                                                       } else if ( p == style_level ) {
+                                                               fprintf( stderr,
+                                                                       "%s: line %d: empty level "
+                                                                       "in \"level{n}\"\n",
+                                                                       fname, lineno );
+                                                               acl_usage();
+                                                       }
+                                                       p[0] = '\0';
+                                               }
+                                       }
                                }
 
                                if ( style == NULL || *style == '\0' ||
@@ -615,6 +644,21 @@ parse_acl(
                                } else if ( strcasecmp( style, "children" ) == 0 ) {
                                        sty = ACL_STYLE_CHILDREN;
 
+                               } else if ( strcasecmp( style, "level" ) == 0 )
+                               {
+                                       char    *next;
+
+                                       level = strtol( style_level, &next, 10 );
+                                       if ( next[0] != '\0' ) {
+                                               fprintf( stderr,
+                                                       "%s: line %d: unable to parse level "
+                                                       "in \"level{n}\"\n",
+                                                       fname, lineno );
+                                               acl_usage();
+                                       }
+
+                                       sty = ACL_STYLE_LEVEL;
+
                                } else if ( strcasecmp( style, "regex" ) == 0 ) {
                                        sty = ACL_STYLE_REGEX;
 
@@ -679,38 +723,48 @@ parse_acl(
                                                fname, lineno );
                                }
 
-                               if ( strcasecmp( argv[i], "*" ) == 0 ) {
+                               if ( strncasecmp( left, "real", STRLENOF( "real" ) ) == 0 ) {
+                                       is_realdn = 1;
+                                       bdn = &b->a_realdn;
+                                       left += STRLENOF( "real" );
+                               }
+
+                               if ( strcasecmp( left, "*" ) == 0 ) {
+                                       if ( is_realdn ) {
+                                               acl_usage();
+                                       }
+
                                        ber_str2bv( "*", STRLENOF( "*" ), 1, &bv );
                                        sty = ACL_STYLE_REGEX;
 
-                               } else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
+                               } else if ( strcasecmp( left, "anonymous" ) == 0 ) {
                                        ber_str2bv("anonymous", STRLENOF( "anonymous" ), 1, &bv);
                                        sty = ACL_STYLE_ANONYMOUS;
 
-                               } else if ( strcasecmp( argv[i], "users" ) == 0 ) {
+                               } else if ( strcasecmp( left, "users" ) == 0 ) {
                                        ber_str2bv("users", STRLENOF( "users" ), 1, &bv);
                                        sty = ACL_STYLE_USERS;
 
-                               } else if ( strcasecmp( argv[i], "self" ) == 0 ) {
+                               } else if ( strcasecmp( left, "self" ) == 0 ) {
                                        ber_str2bv("self", STRLENOF( "self" ), 1, &bv);
                                        sty = ACL_STYLE_SELF;
 
                                } else if ( strcasecmp( left, "dn" ) == 0 ) {
                                        if ( sty == ACL_STYLE_REGEX ) {
-                                               b->a_dn_style = ACL_STYLE_REGEX;
+                                               bdn->a_style = ACL_STYLE_REGEX;
                                                if ( right == NULL ) {
                                                        /* no '=' */
                                                        ber_str2bv("users",
                                                                STRLENOF( "users" ),
                                                                1, &bv);
-                                                       b->a_dn_style = ACL_STYLE_USERS;
+                                                       bdn->a_style = ACL_STYLE_USERS;
 
                                                } else if (*right == '\0' ) {
                                                        /* dn="" */
                                                        ber_str2bv("anonymous",
                                                                STRLENOF( "anonymous" ),
                                                                1, &bv);
-                                                       b->a_dn_style = ACL_STYLE_ANONYMOUS;
+                                                       bdn->a_style = ACL_STYLE_ANONYMOUS;
 
                                                } else if ( strcmp( right, "*" ) == 0 ) {
                                                        /* dn=* */
@@ -718,7 +772,7 @@ parse_acl(
                                                        ber_str2bv("users",
                                                                STRLENOF( "users" ),
                                                                1, &bv);
-                                                       b->a_dn_style = ACL_STYLE_USERS;
+                                                       bdn->a_style = ACL_STYLE_USERS;
 
                                                } else if ( strcmp( right, ".+" ) == 0
                                                        || strcmp( right, "^.+" ) == 0
@@ -730,7 +784,7 @@ parse_acl(
                                                        ber_str2bv("users",
                                                                STRLENOF( "users" ),
                                                                1, &bv);
-                                                       b->a_dn_style = ACL_STYLE_USERS;
+                                                       bdn->a_style = ACL_STYLE_USERS;
 
                                                } else if ( strcmp( right, ".*" ) == 0
                                                        || strcmp( right, "^.*" ) == 0
@@ -766,7 +820,7 @@ parse_acl(
                                }
 
                                if ( !BER_BVISNULL( &bv ) ) {
-                                       if ( !BER_BVISEMPTY( &b->a_dn_pat ) ) {
+                                       if ( !BER_BVISEMPTY( &bdn->a_pat ) ) {
                                                fprintf( stderr,
                                                    "%s: line %d: dn pattern already specified.\n",
                                                    fname, lineno );
@@ -780,7 +834,7 @@ parse_acl(
                                                        expand == 0 )
                                        {
                                                rc = dnNormalize(0, NULL, NULL,
-                                                       &bv, &b->a_dn_pat, NULL);
+                                                       &bv, &bdn->a_pat, NULL);
                                                if ( rc != LDAP_SUCCESS ) {
                                                        fprintf( stderr,
                                                                "%s: line %d: bad DN \"%s\" in by DN clause\n",
@@ -790,10 +844,34 @@ parse_acl(
                                                free( bv.bv_val );
 
                                        } else {
-                                               b->a_dn_pat = bv;
+                                               bdn->a_pat = bv;
+                                       }
+                                       bdn->a_style = sty;
+                                       bdn->a_expand = expand;
+                                       if ( sty == ACL_STYLE_SELF ) {
+                                               bdn->a_self_level = level;
+
+                                       } else {
+                                               if ( level < 0 ) {
+                                                       fprintf( stderr,
+                                                               "%s: line %d: bad negative level \"%d\" "
+                                                               "in by DN clause\n",
+                                                               fname, lineno, level );
+                                                       acl_usage();
+                                               } else if ( level == 1 ) {
+                                                       fprintf( stderr,
+                                                               "%s: line %d: \"onelevel\" should be used "
+                                                               "instead of \"level{1}\" in by DN clause\n",
+                                                               fname, lineno, 0 );
+                                               } else if ( level == 0 && sty == ACL_STYLE_LEVEL ) {
+                                                       fprintf( stderr,
+                                                               "%s: line %d: \"base\" should be used "
+                                                               "instead of \"level{0}\" in by DN clause\n",
+                                                               fname, lineno, 0 );
+                                               }
+
+                                               bdn->a_level = level;
                                        }
-                                       b->a_dn_style = sty;
-                                       b->a_dn_expand = expand;
                                        continue;
                                }
 
@@ -806,14 +884,14 @@ parse_acl(
                                                acl_usage();
                                        }
 
-                                       if( b->a_dn_at != NULL ) {
+                                       if( bdn->a_at != NULL ) {
                                                fprintf( stderr,
                                                        "%s: line %d: dnattr already specified.\n",
                                                        fname, lineno );
                                                acl_usage();
                                        }
 
-                                       rc = slap_str2ad( right, &b->a_dn_at, &text );
+                                       rc = slap_str2ad( right, &bdn->a_at, &text );
 
                                        if( rc != LDAP_SUCCESS ) {
                                                fprintf( stderr,
@@ -823,20 +901,20 @@ parse_acl(
                                        }
 
 
-                                       if( !is_at_syntax( b->a_dn_at->ad_type,
+                                       if( !is_at_syntax( bdn->a_at->ad_type,
                                                SLAPD_DN_SYNTAX ) &&
-                                               !is_at_syntax( b->a_dn_at->ad_type,
+                                               !is_at_syntax( bdn->a_at->ad_type,
                                                SLAPD_NAMEUID_SYNTAX ))
                                        {
                                                fprintf( stderr,
                                                        "%s: line %d: dnattr \"%s\": "
                                                        "inappropriate syntax: %s\n",
                                                        fname, lineno, right,
-                                                       b->a_dn_at->ad_type->sat_syntax_oid );
+                                                       bdn->a_at->ad_type->sat_syntax_oid );
                                                acl_usage();
                                        }
 
-                                       if( b->a_dn_at->ad_type->sat_equality == NULL ) {
+                                       if( bdn->a_at->ad_type->sat_equality == NULL ) {
                                                fprintf( stderr,
                                                        "%s: line %d: dnattr \"%s\": "
                                                        "inappropriate matching (no EQUALITY)\n",
@@ -1584,9 +1662,13 @@ parse_acl(
                        }
 
                        /* get <access> */
-                       if ( strncasecmp( left, "self", 4 ) == 0 ) {
+                       if ( strncasecmp( left, "self", STRLENOF( "self" ) ) == 0 ) {
                                b->a_dn_self = 1;
-                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[4] ) );
+                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[ STRLENOF( "self" ) ] ) );
+
+                       } else if ( strncasecmp( left, "realself", STRLENOF( "realself" ) ) == 0 ) {
+                               b->a_realdn_self = 1;
+                               ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( &left[ STRLENOF( "realself" ) ] ) );
 
                        } else {
                                ACL_PRIV_ASSIGN( b->a_access_mask, str2accessmask( left ) );
@@ -1905,13 +1987,18 @@ acl_usage( void )
                "<attrlist> ::= <attr> [val[.<attrstyle>]=<value>] | <attr> , <attrlist>\n"
                "<attr> ::= <attrname> | entry | children\n",
                "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
+                       "\t[ realanonymous | realusers | realself | realdn[.<dnstyle>]=<DN> ]\n"
                        "\t[dnattr=<attrname>]\n"
+                       "\t[realdnattr=<attrname>]\n"
                        "\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
                        "\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n"
                        "\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
 #ifdef SLAPD_ACI_ENABLED
-                       "\t[aci=<attrname>]\n"
+                       "\t[aci=[<attrname>]]\n"
 #endif
+#ifdef SLAP_DYNACL
+                       "\t[dynacl/<name>[.<dynstyle>][=<pattern>]]\n"
+#endif /* SLAP_DYNACL */
                        "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n",
                "<style> ::= exact | regex | base(Object)\n"
                "<dnstyle> ::= base(Object) | one(level) | sub(tree) | children | "
@@ -1920,7 +2007,7 @@ acl_usage( void )
                        "sub(tree) | children\n"
                "<peernamestyle> ::= exact | regex | ip | path\n"
                "<domainstyle> ::= exact | regex | base(Object) | sub(tree)\n"
-               "<access> ::= [self]{<level>|<priv>}\n"
+               "<access> ::= [[real]self]{<level>|<priv>}\n"
                "<level> ::= none|disclose|auth|compare|search|read|write|manage\n"
                "<priv> ::= {=|+|-}{0|d|x|c|s|r|w|m}+\n"
                "<control> ::= [ stop | continue | break ]\n"
@@ -2014,6 +2101,9 @@ access_free( Access *a )
        if ( !BER_BVISNULL( &a->a_dn_pat ) ) {
                free( a->a_dn_pat.bv_val );
        }
+       if ( !BER_BVISNULL( &a->a_realdn_pat ) ) {
+               free( a->a_realdn_pat.bv_val );
+       }
        if ( !BER_BVISNULL( &a->a_peername_pat ) ) {
                free( a->a_peername_pat.bv_val );
        }
@@ -2145,6 +2235,62 @@ str2access( const char *str )
 
 static char aclbuf[ACLBUF_MAXLEN];
 
+static char *
+dnaccess2text( slap_dn_access *bdn, char *ptr, int is_realdn )
+{
+       *ptr++ = ' ';
+
+       if ( is_realdn ) {
+               ptr = lutil_strcopy( ptr, "real" );
+       }
+
+       if ( ber_bvccmp( &bdn->a_pat, '*' ) ||
+               bdn->a_style == ACL_STYLE_ANONYMOUS ||
+               bdn->a_style == ACL_STYLE_USERS ||
+               bdn->a_style == ACL_STYLE_SELF )
+       {
+               if ( is_realdn ) {
+                       assert( ! ber_bvccmp( &bdn->a_pat, '*' ) );
+               }
+                       
+               ptr = lutil_strcopy( ptr, bdn->a_pat.bv_val );
+               if ( bdn->a_style == ACL_STYLE_SELF && bdn->a_self_level != 0 ) {
+                       int n = sprintf( ptr, ".level{%d}", bdn->a_self_level );
+                       if ( n > 0 ) {
+                               ptr += n;
+                       } /* else ? */
+               }
+
+       } else {
+               ptr = lutil_strcopy( ptr, "dn." );
+               ptr = lutil_strcopy( ptr, style_strings[bdn->a_style] );
+               if ( bdn->a_style == ACL_STYLE_LEVEL ) {
+                       int n = sprintf( ptr, "{%d}", bdn->a_level );
+                       if ( n > 0 ) {
+                               ptr += n;
+                       } /* else ? */
+               }
+               if ( bdn->a_expand ) {
+                       ptr = lutil_strcopy( ptr, ",expand" );
+               }
+               *ptr++ = '=';
+               *ptr++ = '"';
+               ptr = lutil_strcopy( ptr, bdn->a_pat.bv_val );
+               *ptr++ = '"';
+       }
+
+       if ( bdn->a_at != NULL ) {
+               *ptr++ = ' ';
+               if ( is_realdn ) {
+                       ptr = lutil_strcopy( ptr, "real" );
+               }
+               ptr = lutil_strcopy( ptr, "dnattr=" );
+               ptr = lutil_strcopy( ptr, bdn->a_at->ad_cname.bv_val );
+       }
+
+       return ptr;
+}
+
 static char *
 access2text( Access *b, char *ptr )
 {
@@ -2153,27 +2299,11 @@ access2text( Access *b, char *ptr )
        ptr = lutil_strcopy( ptr, "\tby" );
 
        if ( !BER_BVISEMPTY( &b->a_dn_pat ) ) {
-               *ptr++ = ' ';
-               if ( ber_bvccmp( &b->a_dn_pat, '*' ) ||
-                       b->a_dn_style == ACL_STYLE_ANONYMOUS ||
-                       b->a_dn_style == ACL_STYLE_USERS ||
-                       b->a_dn_style == ACL_STYLE_SELF )
-               {
-                       ptr = lutil_strcopy( ptr, b->a_dn_pat.bv_val );
-
-               } else {
-                       ptr = lutil_strcopy( ptr, "dn." );
-                       ptr = lutil_strcopy( ptr, style_strings[b->a_dn_style] );
-                       *ptr++ = '=';
-                       *ptr++ = '"';
-                       ptr = lutil_strcopy( ptr, b->a_dn_pat.bv_val );
-                       *ptr++ = '"';
-               }
+               ptr = dnaccess2text( &b->a_dn, ptr, 0 );
        }
 
-       if ( b->a_dn_at != NULL ) {
-               ptr = lutil_strcopy( ptr, " dnattr=" );
-               ptr = lutil_strcopy( ptr, b->a_dn_at->ad_cname.bv_val );
+       if ( !BER_BVISEMPTY( &b->a_realdn_pat ) ) {
+               ptr = dnaccess2text( &b->a_realdn, ptr, 1 );
        }
 
        if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
@@ -2261,7 +2391,11 @@ access2text( Access *b, char *ptr )
        }
 
        *ptr++ = ' ';
-       if ( b->a_dn_self ) ptr = lutil_strcopy( ptr, "self" );
+       if ( b->a_dn_self ) {
+               ptr = lutil_strcopy( ptr, "self" );
+       } else if ( b->a_realdn_self ) {
+               ptr = lutil_strcopy( ptr, "realself" );
+       }
        ptr = lutil_strcopy( ptr, accessmask2str( b->a_access_mask, maskbuf, 0 ));
        if ( !maskbuf[0] ) ptr--;
 
@@ -2294,7 +2428,7 @@ acl_unparse( AccessControl *a, struct berval *bv )
 
        ptr = bv->bv_val;
 
-       ptr = lutil_strcopy( ptr, "access to" );
+       ptr = lutil_strcopy( ptr, "to" );
        if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
                to++;
                ptr = lutil_strcopy( ptr, " dn." );
@@ -2369,7 +2503,7 @@ print_acl( Backend *be, AccessControl *a )
        struct berval bv;
 
        acl_unparse( a, &bv );
-       fprintf( stderr, "%s ACL: %s\n",
+       fprintf( stderr, "%s ACL: access %s\n",
                be == NULL ? "Global" : "Backend", bv.bv_val );
 }
 #endif /* LDAP_DEBUG */