]> git.sur5r.net Git - openldap/commitdiff
implement "realdn" by clause in ACLs (ITS#3627; accounting for Howard's remarks)
authorPierangelo Masarati <ando@openldap.org>
Sun, 3 Apr 2005 01:59:03 +0000 (01:59 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 3 Apr 2005 01:59:03 +0000 (01:59 +0000)
servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/controls.c
servers/slapd/operation.c
servers/slapd/slap.h

index 29e348494fe009c9439d06a61d0695c3ab44dae9..dfae7d5c5ae65309b0f30a4b0e5b6c38d55c3ea6 100644 (file)
@@ -618,6 +618,281 @@ acl_get(
        return( NULL );
 }
 
+static int
+acl_mask_dn(
+       Operation               *op,
+       Entry                   *e,
+       AccessControl           *a,
+       int                     nmatch,
+       regmatch_t              *matches,
+       slap_dn_access          *b,
+       struct berval           *opndn )
+{
+       /*
+        * if access applies to the entry itself, and the
+        * user is bound as somebody in the same namespace as
+        * the entry, OR the given dn matches the dn pattern
+        */
+       /*
+        * NOTE: styles "anonymous", "users" and "self" 
+        * have been moved to enum slap_style_t, whose 
+        * value is set in a_dn_style; however, the string
+        * is maintaned in a_dn_pat.
+        */
+       if ( b->a_style == ACL_STYLE_ANONYMOUS ) {
+               if ( !BER_BVISEMPTY( opndn ) ) {
+                       return 1;
+               }
+
+       } else if ( b->a_style == ACL_STYLE_USERS ) {
+               if ( BER_BVISEMPTY( opndn ) ) {
+                       return 1;
+               }
+
+       } else if ( b->a_style == ACL_STYLE_SELF ) {
+               struct berval   ndn, selfndn;
+               int             level;
+
+               if ( BER_BVISEMPTY( opndn ) || BER_BVISNULL( &e->e_nname ) ) {
+                       return 1;
+               }
+
+               level = b->a_self_level;
+               if ( level < 0 ) {
+                       selfndn = *opndn;
+                       ndn = e->e_nname;
+                       level = -level;
+
+               } else {
+                       ndn = *opndn;
+                       selfndn = e->e_nname;
+               }
+
+               for ( ; level > 0; level-- ) {
+                       if ( BER_BVISEMPTY( &ndn ) ) {
+                               break;
+                       }
+                       dnParent( &ndn, &ndn );
+               }
+                       
+               if ( BER_BVISEMPTY( &ndn ) || !dn_match( &ndn, &selfndn ) )
+               {
+                       return 1;
+               }
+
+       } else if ( b->a_style == ACL_STYLE_REGEX ) {
+               if ( !ber_bvccmp( &b->a_pat, '*' ) ) {
+                       int             tmp_nmatch;
+                       regmatch_t      tmp_matches[2],
+                                       *tmp_matchesp = tmp_matches;
+
+                       int             rc = 0;
+
+                       switch ( a->acl_dn_style ) {
+                       case ACL_STYLE_REGEX:
+                               if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
+                                       tmp_matchesp = matches;
+                                       tmp_nmatch = nmatch;
+                                       break;
+                               }
+                       /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
+
+                       case ACL_STYLE_BASE:
+                               tmp_matches[0].rm_so = 0;
+                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
+                               tmp_nmatch = 1;
+                               break;
+
+                       case ACL_STYLE_ONE:
+                       case ACL_STYLE_SUBTREE:
+                       case ACL_STYLE_CHILDREN:
+                               tmp_matches[0].rm_so = 0;
+                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
+                               tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
+                               tmp_matches[1].rm_eo = e->e_nname.bv_len;
+                               tmp_nmatch = 2;
+                               break;
+
+                       default:
+                               /* error */
+                               rc = 1;
+                               break;
+                       }
+
+                       if ( rc ) {
+                               return 1;
+                       }
+
+                       if ( !regex_matches( &b->a_pat, opndn->bv_val,
+                               e->e_ndn, tmp_nmatch, tmp_matchesp ) )
+                       {
+                               return 1;
+                       }
+               }
+
+       } else {
+               struct berval   pat;
+               ber_len_t       patlen, odnlen;
+               int             got_match = 0;
+
+               if ( e->e_dn == NULL )
+                       return 1;
+
+               if ( b->a_expand ) {
+                       struct berval   bv;
+                       char            buf[ACL_BUF_SIZE];
+                       
+                       int             tmp_nmatch;
+                       regmatch_t      tmp_matches[2],
+                                       *tmp_matchesp = tmp_matches;
+
+                       int             rc = 0;
+
+                       bv.bv_len = sizeof( buf ) - 1;
+                       bv.bv_val = buf;
+
+                       switch ( a->acl_dn_style ) {
+                       case ACL_STYLE_REGEX:
+                               if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
+                                       tmp_matchesp = matches;
+                                       tmp_nmatch = nmatch;
+                                       break;
+                               }
+                       /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
+
+                       case ACL_STYLE_BASE:
+                               tmp_matches[0].rm_so = 0;
+                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
+                               tmp_nmatch = 1;
+                               break;
+
+                       case ACL_STYLE_ONE:
+                       case ACL_STYLE_SUBTREE:
+                       case ACL_STYLE_CHILDREN:
+                               tmp_matches[0].rm_so = 0;
+                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
+                               tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
+                               tmp_matches[1].rm_eo = e->e_nname.bv_len;
+                               tmp_nmatch = 2;
+                               break;
+
+                       default:
+                               /* error */
+                               rc = 1;
+                               break;
+                       }
+
+                       if ( rc ) {
+                               return 1;
+                       }
+
+                       if ( string_expand( &bv, &b->a_pat, 
+                                       e->e_nname.bv_val,
+                                       tmp_nmatch, tmp_matchesp ) )
+                       {
+                               return 1;
+                       }
+                       
+                       if ( dnNormalize(0, NULL, NULL, &bv,
+                                       &pat, op->o_tmpmemctx )
+                                       != LDAP_SUCCESS )
+                       {
+                               /* did not expand to a valid dn */
+                               return 1;
+                       }
+
+               } else {
+                       pat = b->a_pat;
+               }
+
+               patlen = pat.bv_len;
+               odnlen = opndn->bv_len;
+               if ( odnlen < patlen ) {
+                       goto dn_match_cleanup;
+
+               }
+
+               if ( b->a_style == ACL_STYLE_BASE ) {
+                       /* base dn -- entire object DN must match */
+                       if ( odnlen != patlen ) {
+                               goto dn_match_cleanup;
+                       }
+
+               } else if ( b->a_style == ACL_STYLE_ONE ) {
+                       int rdnlen = -1;
+
+                       if ( odnlen <= patlen ) {
+                               goto dn_match_cleanup;
+                       }
+
+                       if ( !DN_SEPARATOR( opndn->bv_val[odnlen - patlen - 1] ) ) {
+                               goto dn_match_cleanup;
+                       }
+
+                       rdnlen = dn_rdnlen( NULL, opndn );
+                       if ( rdnlen != odnlen - patlen - 1 ) {
+                               goto dn_match_cleanup;
+                       }
+
+               } else if ( b->a_style == ACL_STYLE_SUBTREE ) {
+                       if ( odnlen > patlen && !DN_SEPARATOR( opndn->bv_val[odnlen - patlen - 1] ) ) {
+                               goto dn_match_cleanup;
+                       }
+
+               } else if ( b->a_style == ACL_STYLE_CHILDREN ) {
+                       if ( odnlen <= patlen ) {
+                               goto dn_match_cleanup;
+                       }
+
+                       if ( !DN_SEPARATOR( opndn->bv_val[odnlen - patlen - 1] ) ) {
+                               goto dn_match_cleanup;
+                       }
+
+               } else if ( b->a_style == ACL_STYLE_LEVEL ) {
+                       int level;
+                       struct berval ndn;
+
+                       if ( odnlen <= patlen ) {
+                               goto dn_match_cleanup;
+                       }
+
+                       if ( level > 0 && !DN_SEPARATOR( opndn->bv_val[odnlen - patlen - 1] ) )
+                       {
+                               goto dn_match_cleanup;
+                       }
+                       
+                       level = b->a_level;
+                       ndn = *opndn;
+                       for ( ; level > 0; level-- ) {
+                               if ( BER_BVISEMPTY( &ndn ) ) {
+                                       goto dn_match_cleanup;
+                               }
+                               dnParent( &ndn, &ndn );
+                               if ( ndn.bv_len < patlen ) {
+                                       goto dn_match_cleanup;
+                               }
+                       }
+                       
+                       if ( ndn.bv_len != patlen ) {
+                               goto dn_match_cleanup;
+                       }
+               }
+
+               got_match = !strcmp( pat.bv_val, &opndn->bv_val[ odnlen - patlen ] );
+
+dn_match_cleanup:;
+               if ( pat.bv_val != b->a_pat.bv_val ) {
+                       slap_sl_free( pat.bv_val, op->o_tmpmemctx );
+               }
+
+               if ( !got_match ) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Record value-dependent access control state
  */
@@ -633,6 +908,100 @@ acl_get(
                } \
        } while( 0 )
 
+static int
+acl_mask_dnattr(
+       Operation               *op,
+       Entry                   *e,
+       struct berval           *val,
+       AccessControl           *a,
+       Access                  *b,
+       int                     i,
+       regmatch_t              *matches,
+       int                     count,
+       AccessControlState      *state,
+       slap_dn_access          *bdn,
+       struct berval           *opndn )
+{
+       Attribute       *at;
+       struct berval   bv;
+       int             rc, match = 0;
+       const char      *text;
+       const char      *attr = bdn->a_at->ad_cname.bv_val;
+
+       assert( attr != NULL );
+
+       if ( BER_BVISEMPTY( opndn ) ) {
+               return 1;
+       }
+
+       Debug( LDAP_DEBUG_ACL, "<= check a_dn_at: %s\n", attr, 0, 0 );
+       bv = *opndn;
+
+       /* see if asker is listed in dnattr */
+       for ( at = attrs_find( e->e_attrs, bdn->a_at );
+               at != NULL;
+               at = attrs_find( at->a_next, bdn->a_at ) )
+       {
+               if ( value_find_ex( bdn->a_at,
+                       SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+                               SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+                       at->a_nvals,
+                       &bv, op->o_tmpmemctx ) == 0 )
+               {
+                       /* found it */
+                       match = 1;
+                       break;
+               }
+       }
+
+       if ( match ) {
+               /* have a dnattr match. if this is a self clause then
+                * the target must also match the op dn.
+                */
+               if ( bdn->a_self ) {
+                       /* check if the target is an attribute. */
+                       if ( val == NULL ) return 1;
+
+                       /* target is attribute, check if the attribute value
+                        * is the op dn.
+                        */
+                       rc = value_match( &match, bdn->a_at,
+                               bdn->a_at->ad_type->sat_equality, 0,
+                               val, &bv, &text );
+                       /* on match error or no match, fail the ACL clause */
+                       if ( rc != LDAP_SUCCESS || match != 0 )
+                               return 1;
+               }
+
+       } else {
+               /* no dnattr match, check if this is a self clause */
+               if ( ! bdn->a_self )
+                       return 1;
+
+               ACL_RECORD_VALUE_STATE;
+               
+               /* this is a self clause, check if the target is an
+                * attribute.
+                */
+               if ( val == NULL )
+                       return 1;
+
+               /* target is attribute, check if the attribute value
+                * is the op dn.
+                */
+               rc = value_match( &match, bdn->a_at,
+                       bdn->a_at->ad_type->sat_equality, 0,
+                       val, &bv, &text );
+
+               /* on match error or no match, fail the ACL clause */
+               if ( rc != LDAP_SUCCESS || match != 0 )
+                       return 1;
+       }
+
+       return 0;
+}
+
+
 /*
  * acl_mask - modifies mask based upon the given acl and the
  * requested access to entry e, attribute attr, value val.  if val
@@ -655,7 +1024,7 @@ acl_mask(
        int                     count,
        AccessControlState      *state )
 {
-       int             i, odnlen, patlen;
+       int             i;
        Access  *b;
 #ifdef LDAP_DEBUG
        char accessmaskbuf[ACCESSMASK_MAXLEN];
@@ -715,255 +1084,41 @@ acl_mask(
                         * value is set in a_dn_style; however, the string
                         * is maintaned in a_dn_pat.
                         */
-                       if ( b->a_dn_style == ACL_STYLE_ANONYMOUS ) {
-                               if ( !BER_BVISEMPTY( &op->o_ndn ) ) {
-                                       continue;
-                               }
-
-                       } else if ( b->a_dn_style == ACL_STYLE_USERS ) {
-                               if ( BER_BVISEMPTY( &op->o_ndn ) ) {
-                                       continue;
-                               }
-
-                       } else if ( b->a_dn_style == ACL_STYLE_SELF ) {
-                               struct berval   ndn, selfndn;
-                               int             level;
-
-                               if ( BER_BVISEMPTY( &op->o_ndn ) || BER_BVISNULL( &e->e_nname ) ) {
-                                       continue;
-                               }
 
-                               level = b->a_dn_self_level;
-                               if ( level < 0 ) {
-                                       selfndn = op->o_ndn;
-                                       ndn = e->e_nname;
-                                       level = -level;
-
-                               } else {
-                                       ndn = op->o_ndn;
-                                       selfndn = e->e_nname;
-                               }
-
-                               for ( ; level > 0; level-- ) {
-                                       if ( BER_BVISEMPTY( &ndn ) ) {
-                                               break;
-                                       }
-                                       dnParent( &ndn, &ndn );
-                               }
-                               
-                               if ( BER_BVISEMPTY( &ndn ) || !dn_match( &ndn, &selfndn ) )
-                               {
-                                       continue;
-                               }
-
-                       } else if ( b->a_dn_style == ACL_STYLE_REGEX ) {
-                               if ( !ber_bvccmp( &b->a_dn_pat, '*' ) ) {
-                                       int             tmp_nmatch;
-                                       regmatch_t      tmp_matches[2],
-                                                       *tmp_matchesp = tmp_matches;
-
-                                       int             rc = 0;
-
-                                       switch ( a->acl_dn_style ) {
-                                       case ACL_STYLE_REGEX:
-                                               if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
-                                                       tmp_matchesp = matches;
-                                                       tmp_nmatch = nmatch;
-                                                       break;
-                                               }
-                                       /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
-
-                                       case ACL_STYLE_BASE:
-                                               tmp_matches[0].rm_so = 0;
-                                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
-                                               tmp_nmatch = 1;
-                                               break;
-
-                                       case ACL_STYLE_ONE:
-                                       case ACL_STYLE_SUBTREE:
-                                       case ACL_STYLE_CHILDREN:
-                                               tmp_matches[0].rm_so = 0;
-                                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
-                                               tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
-                                               tmp_matches[1].rm_eo = e->e_nname.bv_len;
-                                               tmp_nmatch = 2;
-                                               break;
-
-                                       default:
-                                               /* error */
-                                               rc = 1;
-                                               break;
-                                       }
+                       if ( acl_mask_dn( op, e, a, nmatch, matches,
+                               &b->a_dn, &op->o_ndn ) )
+                       {
+                               continue;
+                       }
+               }
 
-                                       if ( rc ) {
-                                               continue;
-                                       }
+               if ( !BER_BVISEMPTY( &b->a_realdn_pat ) ) {
+                       struct berval   ndn;
 
-                                       if ( !regex_matches( &b->a_dn_pat,
-                                               op->o_ndn.bv_val, e->e_ndn,
-                                               tmp_nmatch, tmp_matchesp ) )
-                                       {
-                                               continue;
-                                       }
-                               }
+                       Debug( LDAP_DEBUG_ACL, "<= check a_realdn_pat: %s\n",
+                               b->a_realdn_pat.bv_val, 0, 0);
+                       /*
+                        * if access applies to the entry itself, and the
+                        * user is bound as somebody in the same namespace as
+                        * the entry, OR the given dn matches the dn pattern
+                        */
+                       /*
+                        * NOTE: styles "anonymous", "users" and "self" 
+                        * have been moved to enum slap_style_t, whose 
+                        * value is set in a_dn_style; however, the string
+                        * is maintaned in a_dn_pat.
+                        */
 
+                       if ( op->o_conn && !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+                               ndn = op->o_conn->c_ndn;
                        } else {
-                               struct berval pat;
-                               int got_match = 0;
-
-                               if ( e->e_dn == NULL )
-                                       continue;
-
-                               if ( b->a_dn_expand ) {
-                                       struct berval   bv;
-                                       char            buf[ACL_BUF_SIZE];
-                                       
-                                       int             tmp_nmatch;
-                                       regmatch_t      tmp_matches[2],
-                                                       *tmp_matchesp = tmp_matches;
-
-                                       int             rc = 0;
-
-                                       bv.bv_len = sizeof( buf ) - 1;
-                                       bv.bv_val = buf;
-
-                                       switch ( a->acl_dn_style ) {
-                                       case ACL_STYLE_REGEX:
-                                               if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
-                                                       tmp_matchesp = matches;
-                                                       tmp_nmatch = nmatch;
-                                                       break;
-                                               }
-                                       /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
-
-                                       case ACL_STYLE_BASE:
-                                               tmp_matches[0].rm_so = 0;
-                                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
-                                               tmp_nmatch = 1;
-                                               break;
-
-                                       case ACL_STYLE_ONE:
-                                       case ACL_STYLE_SUBTREE:
-                                       case ACL_STYLE_CHILDREN:
-                                               tmp_matches[0].rm_so = 0;
-                                               tmp_matches[0].rm_eo = e->e_nname.bv_len;
-                                               tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
-                                               tmp_matches[1].rm_eo = e->e_nname.bv_len;
-                                               tmp_nmatch = 2;
-                                               break;
-
-                                       default:
-                                               /* error */
-                                               rc = 1;
-                                               break;
-                                       }
-
-                                       if ( rc ) {
-                                               continue;
-                                       }
-
-                                       if ( string_expand( &bv, &b->a_dn_pat, 
-                                                       e->e_nname.bv_val,
-                                                       tmp_nmatch, tmp_matchesp ) )
-                                       {
-                                               continue;
-                                       }
-                                       
-                                       if ( dnNormalize(0, NULL, NULL, &bv,
-                                                       &pat, op->o_tmpmemctx )
-                                                       != LDAP_SUCCESS )
-                                       {
-                                               /* did not expand to a valid dn */
-                                               continue;
-                                       }
-
-                               } else {
-                                       pat = b->a_dn_pat;
-                               }
-
-                               patlen = pat.bv_len;
-                               odnlen = op->o_ndn.bv_len;
-                               if ( odnlen < patlen ) {
-                                       goto dn_match_cleanup;
-
-                               }
-
-                               if ( b->a_dn_style == ACL_STYLE_BASE ) {
-                                       /* base dn -- entire object DN must match */
-                                       if ( odnlen != patlen ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                               } else if ( b->a_dn_style == ACL_STYLE_ONE ) {
-                                       int rdnlen = -1;
-
-                                       if ( odnlen <= patlen ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                                       if ( !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                                       rdnlen = dn_rdnlen( NULL, &op->o_ndn );
-                                       if ( rdnlen != odnlen - patlen - 1 ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                               } else if ( b->a_dn_style == ACL_STYLE_SUBTREE ) {
-                                       if ( odnlen > patlen && !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                               } else if ( b->a_dn_style == ACL_STYLE_CHILDREN ) {
-                                       if ( odnlen <= patlen ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                                       if ( !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                               } else if ( b->a_dn_style == ACL_STYLE_LEVEL ) {
-                                       int level;
-                                       struct berval ndn;
-
-                                       if ( odnlen <= patlen ) {
-                                               goto dn_match_cleanup;
-                                       }
-
-                                       if ( level > 0 && !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) )
-                                       {
-                                               goto dn_match_cleanup;
-                                       }
-                                       
-                                       level = b->a_dn_level;
-                                       ndn = op->o_ndn;
-                                       for ( ; level > 0; level-- ) {
-                                               if ( BER_BVISEMPTY( &ndn ) ) {
-                                                       goto dn_match_cleanup;
-                                               }
-                                               dnParent( &ndn, &ndn );
-                                               if ( ndn.bv_len < patlen ) {
-                                                       goto dn_match_cleanup;
-                                               }
-                                       }
-                                       
-                                       if ( ndn.bv_len != patlen ) {
-                                               goto dn_match_cleanup;
-                                       }
-                               }
-
-                               got_match = !strcmp( pat.bv_val, &op->o_ndn.bv_val[ odnlen - patlen ] );
-
-dn_match_cleanup:;
-                               if ( pat.bv_val != b->a_dn_pat.bv_val ) {
-                                       slap_sl_free( pat.bv_val, op->o_tmpmemctx );
-                               }
+                               ndn = op->o_ndn;
+                       }
 
-                               if ( !got_match ) {
-                                       continue;
-                               }
+                       if ( acl_mask_dn( op, e, a, nmatch, matches,
+                               &b->a_realdn, &ndn ) )
+                       {
+                               continue;
                        }
                }
 
@@ -1209,6 +1364,33 @@ dn_match_cleanup:;
                        }
                }
 
+               if ( b->a_dn_at != NULL ) {
+                       if ( acl_mask_dnattr( op, e, val, a, b, i,
+                                       matches, count, state,
+                                       &b->a_dn, &op->o_ndn ) )
+                       {
+                               continue;
+                       }
+               }
+
+               if ( b->a_realdn_at != NULL ) {
+                       struct berval   ndn;
+
+                       if ( op->o_conn && !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
+                               ndn = op->o_conn->c_ndn;
+                       } else {
+                               ndn = op->o_ndn;
+                       }
+
+                       if ( acl_mask_dnattr( op, e, val, a, b, i,
+                                       matches, count, state,
+                                       &b->a_realdn, &ndn ) )
+                       {
+                               continue;
+                       }
+               }
+
+#if 0
                if ( b->a_dn_at != NULL ) {
                        Attribute       *at;
                        struct berval   bv;
@@ -1243,7 +1425,7 @@ dn_match_cleanup:;
                                }
                        }
 
-                       if( match ) {
+                       if ( match ) {
                                /* have a dnattr match. if this is a self clause then
                                 * the target must also match the op dn.
                                 */
@@ -1261,6 +1443,7 @@ dn_match_cleanup:;
                                        if (rc != LDAP_SUCCESS || match != 0 )
                                                continue;
                                }
+
                        } else {
                                /* no dnattr match, check if this is a self clause */
                                if ( ! b->a_dn_self )
@@ -1286,6 +1469,7 @@ dn_match_cleanup:;
                                        continue;
                        }
                }
+#endif
 
                if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
                        struct berval bv;
index b72ad12d4a84d3f940b6e30d3ac9c98d60db3325..f82a577c3d1969846fa8bdb457ecf60dbd37aadc 100644 (file)
@@ -589,11 +589,13 @@ parse_acl(
 
                        /* get <who> */
                        for ( ; i < argc; i++ ) {
-                               slap_style_t sty = ACL_STYLE_REGEX;
-                               char *style_modifier = NULL;
-                               char *style_level = NULL;
-                               int level = 0;
-                               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 );
@@ -721,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=* */
@@ -760,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
@@ -772,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
@@ -808,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 );
@@ -822,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",
@@ -832,12 +844,12 @@ parse_acl(
                                                free( bv.bv_val );
 
                                        } else {
-                                               b->a_dn_pat = bv;
+                                               bdn->a_pat = bv;
                                        }
-                                       b->a_dn_style = sty;
-                                       b->a_dn_expand = expand;
+                                       bdn->a_style = sty;
+                                       bdn->a_expand = expand;
                                        if ( sty == ACL_STYLE_SELF ) {
-                                               b->a_dn_self_level = level;
+                                               bdn->a_self_level = level;
 
                                        } else {
                                                if ( level < 0 ) {
@@ -858,7 +870,7 @@ parse_acl(
                                                                fname, lineno, 0 );
                                                }
 
-                                               b->a_dn_level = level;
+                                               bdn->a_level = level;
                                        }
                                        continue;
                                }
@@ -872,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,
@@ -889,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",
@@ -1650,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 ) );
@@ -2080,6 +2096,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 );
        }
@@ -2211,6 +2230,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 )
 {
@@ -2219,42 +2294,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 );
-                       if ( b->a_dn_style == ACL_STYLE_SELF && b->a_dn_self_level != 0 ) {
-                               int n = sprintf( ptr, ".level{%d}", b->a_dn_self_level );
-                               if ( n > 0 ) {
-                                       ptr += n;
-                               } /* else ? */
-                       }
-
-               } else {
-                       ptr = lutil_strcopy( ptr, "dn." );
-                       ptr = lutil_strcopy( ptr, style_strings[b->a_dn_style] );
-                       if ( b->a_dn_style == ACL_STYLE_LEVEL ) {
-                               int n = sprintf( ptr, "{%d}", b->a_dn_level );
-                               if ( n > 0 ) {
-                                       ptr += n;
-                               } /* else ? */
-                       }
-                       if ( b->a_dn_expand ) {
-                               ptr = lutil_strcopy( ptr, ",expand" );
-                       }
-                       *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 ) ) {
@@ -2342,7 +2386,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--;
 
index 78199b1d2e5e5425d2940fd92e02abb3957fedb4..27fe43f1c6161453fbaa8d452283f29f7b05a917 100644 (file)
@@ -755,19 +755,17 @@ static int parseProxyAuthz (
                ctrl->ldctl_value.bv_len ?  ctrl->ldctl_value.bv_val : "anonymous",
                0 );
 
-       if( ctrl->ldctl_value.bv_len == 0 ) {
+       if ( ctrl->ldctl_value.bv_len == 0 ) {
                Debug( LDAP_DEBUG_TRACE,
                        "parseProxyAuthz: conn=%lu anonymous\n", 
                        op->o_connid, 0, 0 );
 
                /* anonymous */
-               free( op->o_dn.bv_val );
-               op->o_dn.bv_len = 0;
-               op->o_dn.bv_val = ch_strdup( "" );
-
-               free( op->o_ndn.bv_val );
+               op->o_ndn.bv_val[ 0 ] = '\0';
                op->o_ndn.bv_len = 0;
-               op->o_ndn.bv_val = ch_strdup( "" );
+
+               op->o_dn.bv_val[ 0 ] = '\0';
+               op->o_dn.bv_len = 0;
 
                return LDAP_SUCCESS;
        }
@@ -791,27 +789,26 @@ static int parseProxyAuthz (
 
        rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
 
-       if( rc ) {
+       if ( rc ) {
                ch_free( dn.bv_val );
                rs->sr_text = "not authorized to assume identity";
                return LDAP_PROXY_AUTHZ_FAILURE;
        }
 
-       ch_free( op->o_dn.bv_val );
        ch_free( op->o_ndn.bv_val );
-
-       op->o_dn.bv_val = NULL;
-       op->o_ndn = dn;
-
-       Statslog( LDAP_DEBUG_STATS, "%s PROXYAUTHZ dn=\"%s\"\n",
-           op->o_log_prefix, dn.bv_val, 0, 0, 0 );
+       ch_free( op->o_dn.bv_val );
 
        /*
         * NOTE: since slap_sasl_getdn() returns a normalized dn,
         * from now on op->o_dn is normalized
         */
+       op->o_ndn = dn;
        ber_dupbv( &op->o_dn, &dn );
 
+
+       Statslog( LDAP_DEBUG_STATS, "%s PROXYAUTHZ dn=\"%s\"\n",
+           op->o_log_prefix, dn.bv_val, 0, 0, 0 );
+
        return LDAP_SUCCESS;
 }
 
index e65fd4d7ad9c5e3dd3411d26128e7ce6cdf23077..4946c772fd2986676a0aa633b99c883ff2995100 100644 (file)
@@ -68,13 +68,13 @@ slap_op_free( Operation *op )
        if ( op->o_ber != NULL ) {
                ber_free( op->o_ber, 1 );
        }
-       if ( op->o_dn.bv_val != NULL ) {
+       if ( !BER_BVISNULL( &op->o_dn ) ) {
                free( op->o_dn.bv_val );
        }
-       if ( op->o_ndn.bv_val != NULL ) {
+       if ( !BER_BVISNULL( &op->o_ndn ) ) {
                free( op->o_ndn.bv_val );
        }
-       if ( op->o_authmech.bv_val != NULL ) {
+       if ( !BER_BVISNULL( &op->o_authmech ) ) {
                free( op->o_authmech.bv_val );
        }
        if ( op->o_ctrls != NULL ) {
@@ -89,9 +89,9 @@ slap_op_free( Operation *op )
 
        {
                GroupAssertion *g, *n;
-               for (g = op->o_groups; g; g=n) {
+               for ( g = op->o_groups; g; g = n ) {
                        n = g->ga_next;
-                       slap_sl_free(g, op->o_tmpmemctx);
+                       slap_sl_free( g, op->o_tmpmemctx );
                }
                op->o_groups = NULL;
        }
index c6bc4007391b11e6082f8b849940593a4cd320a0..fb4403a500863da1ad7346b3e2c1c6ba6d894226 100644 (file)
@@ -1228,6 +1228,19 @@ typedef struct slap_dynacl_t {
 } slap_dynacl_t;
 #endif /* SLAP_DYNACL */
 
+/* the DN portion of the "by" part */
+typedef struct slap_dn_access {
+       /* DN pattern */
+       AuthorizationInformation        a_dnauthz;
+
+       slap_style_t            a_style;
+       int                     a_level;
+       int                     a_self_level;
+       AttributeDescription    *a_at;
+       int                     a_self;
+       int                     a_expand;
+} slap_dn_access;
+
 /* the "by" part */
 typedef struct slap_access {
        slap_control_t a_type;
@@ -1299,16 +1312,30 @@ typedef struct slap_access {
 
        slap_mask_t     a_access_mask;
 
-       AuthorizationInformation        a_authz;
-#define a_dn_pat       a_authz.sai_dn
-
-       slap_style_t a_dn_style;
-       int                     a_dn_level;
-       int                     a_dn_self_level;
-       AttributeDescription    *a_dn_at;
-       int                     a_dn_self;
-       int                     a_dn_expand;
-
+       /* DN pattern */
+       slap_dn_access          a_dn;
+#define a_dn_pat               a_dn.a_dnauthz.sai_dn
+#define        a_dn_style              a_dn.a_style
+#define        a_dn_level              a_dn.a_level
+#define        a_dn_self_level         a_dn.a_self_level
+#define        a_dn_at                 a_dn.a_at
+#define        a_dn_self               a_dn.a_self
+#define        a_dn_expand             a_dn.a_expand
+
+       /* real DN pattern */
+       slap_dn_access          a_realdn;
+#define a_realdn_pat           a_realdn.a_dnauthz.sai_dn
+#define        a_realdn_style          a_realdn.a_style
+#define        a_realdn_level          a_realdn.a_level
+#define        a_realdn_self_level     a_realdn.a_self_level
+#define        a_realdn_at             a_realdn.a_at
+#define        a_realdn_self           a_realdn.a_self
+#define        a_realdn_expand         a_realdn.a_expand
+
+#define        a_authz                 a_dn.a_dnauthz
+#define        a_pat                   a_dnauthz.sai_dn
+
+       /* connection related stuff */
        slap_style_t a_peername_style;
        struct berval   a_peername_pat;
        unsigned long   a_peername_addr,