+ 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;