+ if ( style == NULL || *style == '\0' ||
+ strcasecmp( style, "exact" ) == 0 ||
+ strcasecmp( style, "baseObject" ) == 0 ||
+ strcasecmp( style, "base" ) == 0 )
+ {
+ sty = ACL_STYLE_BASE;
+
+ } else if ( strcasecmp( style, "onelevel" ) == 0 ||
+ strcasecmp( style, "one" ) == 0 )
+ {
+ sty = ACL_STYLE_ONE;
+
+ } else if ( strcasecmp( style, "subtree" ) == 0 ||
+ strcasecmp( style, "sub" ) == 0 )
+ {
+ sty = ACL_STYLE_SUBTREE;
+
+ } else if ( strcasecmp( style, "children" ) == 0 ) {
+ sty = ACL_STYLE_CHILDREN;
+
+ } else if ( strcasecmp( style, "level" ) == 0 )
+ {
+ if ( lutil_atoi( &level, style_level ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: unable to parse level "
+ "in \"level{n}\"\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ sty = ACL_STYLE_LEVEL;
+
+ } else if ( strcasecmp( style, "regex" ) == 0 ) {
+ sty = ACL_STYLE_REGEX;
+
+ } else if ( strcasecmp( style, "expand" ) == 0 ) {
+ sty = ACL_STYLE_EXPAND;
+
+ } else if ( strcasecmp( style, "ip" ) == 0 ) {
+ sty = ACL_STYLE_IP;
+
+ } else if ( strcasecmp( style, "ipv6" ) == 0 ) {
+#ifndef LDAP_PF_INET6
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: IPv6 not supported\n",
+ fname, lineno, 0 );
+#endif /* ! LDAP_PF_INET6 */
+ sty = ACL_STYLE_IPV6;
+
+ } else if ( strcasecmp( style, "path" ) == 0 ) {
+ sty = ACL_STYLE_PATH;
+#ifndef LDAP_PF_LOCAL
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: "
+ "\"path\" style modifier is useless without local.\n",
+ fname, lineno, 0 );
+ goto fail;
+#endif /* LDAP_PF_LOCAL */
+
+ } else {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: unknown style \"%s\" in by clause\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( style_modifier &&
+ strcasecmp( style_modifier, "expand" ) == 0 )
+ {
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "\"regex\" style implies \"expand\" modifier.\n",
+ fname, lineno, 0 );
+ goto fail;
+ break;
+
+ case ACL_STYLE_EXPAND:
+ break;
+
+ default:
+ /* we'll see later if it's pertinent */
+ expand = 1;
+ break;
+ }
+ }
+
+ /* expand in <who> needs regex in <what> */
+ if ( ( sty == ACL_STYLE_EXPAND || expand )
+ && a->acl_dn_style != ACL_STYLE_REGEX )
+ {
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: line %d: \"expand\" style "
+ "or modifier used in conjunction with a non-regex <what> clause.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ if ( strncasecmp( left, "real", STRLENOF( "real" ) ) == 0 ) {
+ is_realdn = 1;
+ bdn = &b->a_realdn;
+ left += STRLENOF( "real" );
+ }
+
+ if ( strcasecmp( left, "*" ) == 0 ) {
+ if ( is_realdn ) {
+ goto fail;
+ }
+
+ ber_str2bv( "*", STRLENOF( "*" ), 1, &bv );
+ sty = ACL_STYLE_REGEX;
+
+ } else if ( strcasecmp( left, "anonymous" ) == 0 ) {
+ ber_str2bv("anonymous", STRLENOF( "anonymous" ), 1, &bv);
+ sty = ACL_STYLE_ANONYMOUS;
+
+ } else if ( strcasecmp( left, "users" ) == 0 ) {
+ ber_str2bv("users", STRLENOF( "users" ), 1, &bv);
+ sty = ACL_STYLE_USERS;
+
+ } 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 ) {
+ bdn->a_style = ACL_STYLE_REGEX;
+ if ( right == NULL ) {
+ /* no '=' */
+ ber_str2bv("users",
+ STRLENOF( "users" ),
+ 1, &bv);
+ bdn->a_style = ACL_STYLE_USERS;
+
+ } else if (*right == '\0' ) {
+ /* dn="" */
+ ber_str2bv("anonymous",
+ STRLENOF( "anonymous" ),
+ 1, &bv);
+ bdn->a_style = ACL_STYLE_ANONYMOUS;
+
+ } else if ( strcmp( right, "*" ) == 0 ) {
+ /* dn=* */
+ /* any or users? users for now */
+ ber_str2bv("users",
+ STRLENOF( "users" ),
+ 1, &bv);
+ bdn->a_style = ACL_STYLE_USERS;
+
+ } else if ( strcmp( right, ".+" ) == 0
+ || strcmp( right, "^.+" ) == 0
+ || strcmp( right, ".+$" ) == 0
+ || strcmp( right, "^.+$" ) == 0
+ || strcmp( right, ".+$$" ) == 0
+ || strcmp( right, "^.+$$" ) == 0 )
+ {
+ ber_str2bv("users",
+ STRLENOF( "users" ),
+ 1, &bv);
+ bdn->a_style = ACL_STYLE_USERS;
+
+ } else if ( strcmp( right, ".*" ) == 0
+ || strcmp( right, "^.*" ) == 0
+ || strcmp( right, ".*$" ) == 0
+ || strcmp( right, "^.*$" ) == 0
+ || strcmp( right, ".*$$" ) == 0
+ || strcmp( right, "^.*$$" ) == 0 )
+ {
+ ber_str2bv("*",
+ STRLENOF( "*" ),
+ 1, &bv);
+
+ } else {
+ acl_regex_normalized_dn( right, &bv );
+ if ( !ber_bvccmp( &bv, '*' ) ) {
+ regtest( fname, lineno, bv.bv_val );
+ }
+ }
+
+ } else if ( right == NULL || *right == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause\n",
+ fname, lineno, left );
+ goto fail;
+
+ } else {
+ ber_str2bv( right, 0, 1, &bv );
+ }
+
+ } else {
+ BER_BVZERO( &bv );
+ }
+
+ if ( !BER_BVISNULL( &bv ) ) {
+ if ( !BER_BVISEMPTY( &bdn->a_pat ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: dn pattern already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ if ( sty != ACL_STYLE_REGEX &&
+ sty != ACL_STYLE_ANONYMOUS &&
+ sty != ACL_STYLE_USERS &&
+ sty != ACL_STYLE_SELF &&
+ expand == 0 )
+ {
+ rc = dnNormalize(0, NULL, NULL,
+ &bv, &bdn->a_pat, NULL);
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: bad DN \"%s\" in by DN clause\n",
+ fname, lineno, bv.bv_val );
+ goto fail;
+ }
+ free( bv.bv_val );
+ if ( sty == ACL_STYLE_BASE
+ && be != NULL
+ && !BER_BVISNULL( &be->be_rootndn )
+ && dn_match( &bdn->a_pat, &be->be_rootndn ) )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: rootdn is always granted "
+ "unlimited privileges.\n",
+ fname, lineno, 0 );
+ }
+
+ } else {
+ bdn->a_pat = bv;
+ }
+ bdn->a_style = sty;
+ if ( expand ) {
+ char *exp;
+ int gotit = 0;
+
+ for ( exp = strchr( bdn->a_pat.bv_val, '$' );
+ exp && (ber_len_t)(exp - bdn->a_pat.bv_val)
+ < bdn->a_pat.bv_len;
+ exp = strchr( exp, '$' ) )
+ {
+ if ( isdigit( (unsigned char) exp[ 1 ] ) ) {
+ gotit = 1;
+ break;
+ }
+ }
+
+ if ( gotit == 1 ) {
+ bdn->a_expand = expand;
+
+ } else {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "\"expand\" used with no expansions in \"pattern\".\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+ }
+ if ( sty == ACL_STYLE_SELF ) {
+ bdn->a_self_level = level;
+
+ } else {
+ if ( level < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: bad negative level \"%d\" "
+ "in by DN clause\n",
+ fname, lineno, level );
+ goto fail;
+ } else if ( level == 1 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%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 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: \"base\" should be used "
+ "instead of \"level{0}\" in by DN clause\n",
+ fname, lineno, 0 );
+ }
+
+ bdn->a_level = level;
+ }
+ continue;
+ }
+
+ if ( strcasecmp( left, "dnattr" ) == 0 ) {
+ if ( right == NULL || right[0] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause\n",
+ fname, lineno, left );
+ goto fail;
+ }
+
+ if( bdn->a_at != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: dnattr already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ rc = slap_str2ad( right, &bdn->a_at, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "dnattr \"%s\": %s",
+ right, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+ goto fail;
+ }
+
+
+ if( !is_at_syntax( bdn->a_at->ad_type,
+ SLAPD_DN_SYNTAX ) &&
+ !is_at_syntax( bdn->a_at->ad_type,
+ SLAPD_NAMEUID_SYNTAX ))
+ {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "dnattr \"%s\": "
+ "inappropriate syntax: %s\n",
+ right,
+ bdn->a_at->ad_type->sat_syntax_oid );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+ goto fail;
+ }
+
+ if( bdn->a_at->ad_type->sat_equality == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: dnattr \"%s\": "
+ "inappropriate matching (no EQUALITY)\n",
+ fname, lineno, right );
+ goto fail;
+ }
+
+ continue;
+ }
+
+ if ( strncasecmp( left, "group", STRLENOF( "group" ) ) == 0 ) {
+ char *name = NULL;
+ char *value = NULL;
+
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ /* legacy, tolerated */
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: "
+ "deprecated group style \"regex\"; "
+ "use \"expand\" instead.\n",
+ fname, lineno, 0 );
+ sty = ACL_STYLE_EXPAND;
+ break;
+
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* legal, substring expansion; supersedes regex */
+ break;
+
+ default:
+ /* unknown */
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( right == NULL || right[0] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause.\n",
+ fname, lineno, left );
+ goto fail;
+ }
+
+ if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: group pattern already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ /* format of string is
+ "group/objectClassValue/groupAttrName" */
+ if ( ( value = strchr(left, '/') ) != NULL ) {
+ *value++ = '\0';
+ if ( *value && ( name = strchr( value, '/' ) ) != NULL ) {
+ *name++ = '\0';
+ }
+ }
+
+ b->a_group_style = sty;
+ if ( sty == ACL_STYLE_EXPAND ) {
+ acl_regex_normalized_dn( right, &bv );
+ if ( !ber_bvccmp( &bv, '*' ) ) {
+ regtest( fname, lineno, bv.bv_val );
+ }
+ b->a_group_pat = bv;
+
+ } else {
+ ber_str2bv( right, 0, 0, &bv );
+ rc = dnNormalize( 0, NULL, NULL, &bv,
+ &b->a_group_pat, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: bad DN \"%s\".\n",
+ fname, lineno, right );
+ goto fail;
+ }
+ }
+
+ if ( value && *value ) {
+ b->a_group_oc = oc_find( value );
+ *--value = '/';
+
+ if ( b->a_group_oc == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: group objectclass "
+ "\"%s\" unknown.\n",
+ fname, lineno, value );
+ goto fail;
+ }
+
+ } else {
+ b->a_group_oc = oc_find( SLAPD_GROUP_CLASS );
+
+ if( b->a_group_oc == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: group default objectclass "
+ "\"%s\" unknown.\n",
+ fname, lineno, SLAPD_GROUP_CLASS );
+ goto fail;
+ }
+ }
+
+ if ( is_object_subclass( slap_schema.si_oc_referral,
+ b->a_group_oc ) )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: group objectclass \"%s\" "
+ "is subclass of referral.\n",
+ fname, lineno, value );
+ goto fail;
+ }
+
+ if ( is_object_subclass( slap_schema.si_oc_alias,
+ b->a_group_oc ) )
+ {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: group objectclass \"%s\" "
+ "is subclass of alias.\n",
+ fname, lineno, value );
+ goto fail;
+ }
+
+ if ( name && *name ) {
+ rc = slap_str2ad( name, &b->a_group_at, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group \"%s\": %s.",
+ right, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+ goto fail;
+ }
+ *--name = '/';
+
+ } else {
+ rc = slap_str2ad( SLAPD_GROUP_ATTR, &b->a_group_at, &text );
+
+ if ( rc != LDAP_SUCCESS ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group \"%s\": %s.",
+ SLAPD_GROUP_ATTR, text );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+ goto fail;
+ }
+ }
+
+ if ( !is_at_syntax( b->a_group_at->ad_type,
+ SLAPD_DN_SYNTAX ) &&
+ !is_at_syntax( b->a_group_at->ad_type,
+ SLAPD_NAMEUID_SYNTAX ) &&
+ !is_at_subtype( b->a_group_at->ad_type, slap_schema.si_ad_labeledURI->ad_type ) )
+ {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group \"%s\": inappropriate syntax: %s.",
+ right,
+ b->a_group_at->ad_type->sat_syntax_oid );
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: %s\n",
+ fname, lineno, buf );
+ goto fail;
+ }
+
+
+ {
+ int rc;
+ ObjectClass *ocs[2];
+
+ ocs[0] = b->a_group_oc;
+ ocs[1] = NULL;
+
+ rc = oc_check_allowed( b->a_group_at->ad_type,
+ ocs, NULL );
+
+ if( rc != 0 ) {
+ char buf[ SLAP_TEXT_BUFLEN ];
+
+ snprintf( buf, sizeof( buf ),
+ "group: \"%s\" not allowed by \"%s\".",
+ b->a_group_at->ad_cname.bv_val,
+ b->a_group_oc->soc_oid );
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: %s\n",
+ fname, lineno, buf );
+ goto fail;
+ }
+ }
+ continue;
+ }
+
+ if ( strcasecmp( left, "peername" ) == 0 ) {
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* cheap replacement to regex for simple expansion */
+ case ACL_STYLE_IP:
+ case ACL_STYLE_IPV6:
+ case ACL_STYLE_PATH:
+ /* legal, peername specific */
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( right == NULL || right[0] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause.\n",
+ fname, lineno, left );
+ goto fail;
+ }
+
+ if ( !BER_BVISEMPTY( &b->a_peername_pat ) ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "peername pattern already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ b->a_peername_style = sty;
+ if ( sty == ACL_STYLE_REGEX ) {
+ acl_regex_normalized_dn( right, &bv );
+ if ( !ber_bvccmp( &bv, '*' ) ) {
+ regtest( fname, lineno, bv.bv_val );
+ }
+ b->a_peername_pat = bv;
+
+ } else {
+ ber_str2bv( right, 0, 1, &b->a_peername_pat );
+
+ if ( sty == ACL_STYLE_IP ) {
+ char *addr = NULL,
+ *mask = NULL,
+ *port = NULL;
+
+ split( right, '{', &addr, &port );
+ split( addr, '%', &addr, &mask );
+
+ b->a_peername_addr = inet_addr( addr );
+ if ( b->a_peername_addr == (unsigned long)(-1) ) {
+ /* illegal address */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "illegal peername address \"%s\".\n",
+ fname, lineno, addr );
+ goto fail;
+ }
+
+ b->a_peername_mask = (unsigned long)(-1);
+ if ( mask != NULL ) {
+ b->a_peername_mask = inet_addr( mask );
+ if ( b->a_peername_mask ==
+ (unsigned long)(-1) )
+ {
+ /* illegal mask */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "illegal peername address mask "
+ "\"%s\".\n",
+ fname, lineno, mask );
+ goto fail;
+ }
+ }
+
+ b->a_peername_port = -1;
+ if ( port ) {
+ char *end = NULL;
+
+ b->a_peername_port = strtol( port, &end, 10 );
+ if ( end == port || end[0] != '}' ) {
+ /* illegal port */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "illegal peername port specification "
+ "\"{%s}\".\n",
+ fname, lineno, port );
+ goto fail;
+ }
+ }
+
+#ifdef LDAP_PF_INET6
+ } else if ( sty == ACL_STYLE_IPV6 ) {
+ char *addr = NULL,
+ *mask = NULL,
+ *port = NULL;
+
+ split( right, '{', &addr, &port );
+ split( addr, '%', &addr, &mask );
+
+ if ( inet_pton( AF_INET6, addr, &b->a_peername_addr6 ) != 1 ) {
+ /* illegal address */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "illegal peername address \"%s\".\n",
+ fname, lineno, addr );
+ goto fail;
+ }
+
+ if ( mask == NULL ) {
+ mask = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF";
+ }
+
+ if ( inet_pton( AF_INET6, mask, &b->a_peername_mask6 ) != 1 ) {
+ /* illegal mask */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "illegal peername address mask "
+ "\"%s\".\n",
+ fname, lineno, mask );
+ goto fail;
+ }
+
+ b->a_peername_port = -1;
+ if ( port ) {
+ char *end = NULL;
+
+ b->a_peername_port = strtol( port, &end, 10 );
+ if ( end == port || end[0] != '}' ) {
+ /* illegal port */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "illegal peername port specification "
+ "\"{%s}\".\n",
+ fname, lineno, port );
+ goto fail;
+ }
+ }
+#endif /* LDAP_PF_INET6 */
+ }
+ }
+ continue;
+ }
+
+ if ( strcasecmp( left, "sockname" ) == 0 ) {
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* cheap replacement to regex for simple expansion */
+ break;
+
+ default:
+ /* unknown */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( right == NULL || right[0] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause\n",
+ fname, lineno, left );
+ goto fail;
+ }
+
+ if ( !BER_BVISNULL( &b->a_sockname_pat ) ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "sockname pattern already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ b->a_sockname_style = sty;
+ if ( sty == ACL_STYLE_REGEX ) {
+ acl_regex_normalized_dn( right, &bv );
+ if ( !ber_bvccmp( &bv, '*' ) ) {
+ regtest( fname, lineno, bv.bv_val );
+ }
+ b->a_sockname_pat = bv;
+
+ } else {
+ ber_str2bv( right, 0, 1, &b->a_sockname_pat );
+ }
+ continue;
+ }
+
+ if ( strcasecmp( left, "domain" ) == 0 ) {
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ case ACL_STYLE_SUBTREE:
+ /* legal, traditional */
+ break;
+
+ case ACL_STYLE_EXPAND:
+ /* tolerated: means exact,expand */
+ if ( expand ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: "
+ "\"expand\" modifier "
+ "with \"expand\" style.\n",
+ fname, lineno, 0 );
+ }
+ sty = ACL_STYLE_BASE;
+ expand = 1;
+ break;
+
+ default:
+ /* unknown */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( right == NULL || right[0] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause.\n",
+ fname, lineno, left );
+ goto fail;
+ }
+
+ if ( !BER_BVISEMPTY( &b->a_domain_pat ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: domain pattern already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ b->a_domain_style = sty;
+ b->a_domain_expand = expand;
+ if ( sty == ACL_STYLE_REGEX ) {
+ acl_regex_normalized_dn( right, &bv );
+ if ( !ber_bvccmp( &bv, '*' ) ) {
+ regtest( fname, lineno, bv.bv_val );
+ }
+ b->a_domain_pat = bv;
+
+ } else {
+ ber_str2bv( right, 0, 1, &b->a_domain_pat );
+ }
+ continue;
+ }
+
+ if ( strcasecmp( left, "sockurl" ) == 0 ) {
+ switch ( sty ) {
+ case ACL_STYLE_REGEX:
+ case ACL_STYLE_BASE:
+ /* legal, traditional */
+ case ACL_STYLE_EXPAND:
+ /* cheap replacement to regex for simple expansion */
+ break;
+
+ default:
+ /* unknown */
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( right == NULL || right[0] == '\0' ) {
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "missing \"=\" in (or value after) \"%s\" "
+ "in by clause.\n",
+ fname, lineno, left );
+ goto fail;
+ }
+
+ if ( !BER_BVISEMPTY( &b->a_sockurl_pat ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: sockurl pattern already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ b->a_sockurl_style = sty;
+ if ( sty == ACL_STYLE_REGEX ) {
+ acl_regex_normalized_dn( right, &bv );
+ if ( !ber_bvccmp( &bv, '*' ) ) {
+ regtest( fname, lineno, bv.bv_val );
+ }
+ b->a_sockurl_pat = bv;
+
+ } else {
+ ber_str2bv( right, 0, 1, &b->a_sockurl_pat );
+ }
+ continue;
+ }
+
+ if ( strcasecmp( left, "set" ) == 0 ) {
+ switch ( sty ) {
+ /* deprecated */
+ case ACL_STYLE_REGEX:
+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
+ "%s: line %d: "
+ "deprecated set style "
+ "\"regex\" in <by> clause; "
+ "use \"expand\" instead.\n",
+ fname, lineno, 0 );
+ sty = ACL_STYLE_EXPAND;
+ /* FALLTHRU */
+
+ case ACL_STYLE_BASE:
+ case ACL_STYLE_EXPAND:
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+ "inappropriate style \"%s\" in by clause.\n",
+ fname, lineno, style );
+ goto fail;
+ }
+
+ if ( !BER_BVISEMPTY( &b->a_set_pat ) ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: set attribute already specified.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }
+
+ if ( right == NULL || *right == '\0' ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: no set is defined.\n",
+ fname, lineno, 0 );
+ goto fail;
+ }