]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/acl.c
ITS#4458 re-encode passwd request
[openldap] / servers / slapd / acl.c
index 954714cf7778e649f808d42cacc1d8fed9bb92cb..d523a5aa0e0107783a847b72dbbd0e9d30d1b135 100644 (file)
@@ -40,6 +40,9 @@
 #define ACL_BUF_SIZE   1024    /* use most appropriate size */
 
 static const struct berval     acl_bv_ip_eq = BER_BVC( "IP=" );
+#ifdef LDAP_PF_INET6
+static const struct berval     acl_bv_ipv6_eq = BER_BVC( "IP=[" );
+#endif /* LDAP_PF_INET6 */
 #ifdef LDAP_PF_LOCAL
 static const struct berval     acl_bv_path_eq = BER_BVC("PATH=");
 #endif /* LDAP_PF_LOCAL */
@@ -242,7 +245,6 @@ slap_access_allowed(
                        }
                }
 
-vd_access:
                control = slap_acl_mask( a, &mask, op,
                        e, desc, val, MAXREMATCHES, matches, count, state );
 
@@ -354,7 +356,7 @@ access_allowed_mask(
                {
                        access = ACL_AUTH;
 
-               } else if ( get_manageDIT( op ) && access_level == ACL_WRITE &&
+               } else if ( get_relax( op ) && access_level == ACL_WRITE &&
                        desc == slap_schema.si_ad_entry )
                {
                        access = ACL_MANAGE;
@@ -387,14 +389,12 @@ access_allowed_mask(
                op->o_bd = LDAP_STAILQ_FIRST( &backendDB );
                be_null = 1;
 
-#ifdef LDAP_DEVEL
-               /*
-                * FIXME: experimental; use first backend rules
-                * iff there is no global_acl (ITS#3100) */
+               /* FIXME: experimental; use first backend rules
+                * iff there is no global_acl (ITS#3100)
+                */
                if ( frontendDB->be_acl != NULL ) {
                        op->o_bd = frontendDB;
                }
-#endif /* LDAP_DEVEL */
        }
        assert( op->o_bd != NULL );
 
@@ -649,6 +649,17 @@ slap_acl_get(
        return( NULL );
 }
 
+/*
+ * Record value-dependent access control state
+ */
+#define ACL_RECORD_VALUE_STATE do { \
+               if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \
+                       state->as_recorded |= ACL_STATE_RECORDED_VD; \
+                       state->as_vd_acl = a; \
+                       state->as_vd_acl_count = count; \
+               } \
+       } while( 0 )
+
 static int
 acl_mask_dn(
        Operation               *op,
@@ -670,7 +681,7 @@ acl_mask_dn(
         * 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.
+        * is maintained in a_dn_pat.
         */
 
        if ( bdn->a_style == ACL_STYLE_ANONYMOUS ) {
@@ -996,6 +1007,8 @@ acl_mask_dnattr(
                if ( ! bdn->a_self )
                        return 1;
 
+               ACL_RECORD_VALUE_STATE;
+
                /* this is a self clause, check if the target is an
                 * attribute.
                 */
@@ -1088,7 +1101,7 @@ slap_acl_mask(
                         * 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.
+                        * is maintained in a_dn_pat.
                         */
 
                        if ( acl_mask_dn( op, e, desc, val, a, nmatch, matches,
@@ -1112,7 +1125,7 @@ slap_acl_mask(
                         * 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.
+                        * is maintained in a_dn_pat.
                         */
 
                        if ( op->o_conn && !BER_BVISNULL( &op->o_conn->c_ndn ) )
@@ -1306,6 +1319,50 @@ slap_acl_mask(
                                                if ( (addr & b->a_peername_mask) != b->a_peername_addr )
                                                        continue;
 
+#ifdef LDAP_PF_INET6
+                                       /* extract IPv6 and try exact match */
+                                       } else if ( b->a_peername_style == ACL_STYLE_IPV6 ) {
+                                               char            *port;
+                                               char            buf[] = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF";
+                                               struct berval   ip;
+                                               struct in6_addr addr;
+                                               int             port_number = -1, i;
+                                               
+                                               if ( strncasecmp( op->o_conn->c_peer_name.bv_val, 
+                                                                       acl_bv_ipv6_eq.bv_val,
+                                                                       acl_bv_ipv6_eq.bv_len ) != 0 ) 
+                                                       continue;
+
+                                               ip.bv_val = op->o_conn->c_peer_name.bv_val + acl_bv_ipv6_eq.bv_len;
+                                               ip.bv_len = op->o_conn->c_peer_name.bv_len - acl_bv_ipv6_eq.bv_len;
+
+                                               port = strrchr( ip.bv_val, ']' );
+                                               if ( port ) {
+                                                       ip.bv_len = port - ip.bv_val;
+                                                       ++port;
+                                                       if ( port[0] == ':' && lutil_atoi( &port_number, ++port ) != 0 )
+                                                               continue;
+                                               }
+                                               
+                                               /* the port check can be anticipated here */
+                                               if ( b->a_peername_port != -1 && port_number != b->a_peername_port )
+                                                       continue;
+                                               
+                                               /* address longer than expected? */
+                                               if ( ip.bv_len >= sizeof(buf) )
+                                                       continue;
+
+                                               AC_MEMCPY( buf, ip.bv_val, ip.bv_len );
+                                               buf[ ip.bv_len ] = '\0';
+
+                                               if ( inet_pton( AF_INET6, buf, &addr ) != 1 )
+                                                       continue;
+
+                                               /* check mask */
+                                               if ( !slap_addr6_mask( &addr, &b->a_peername_mask6, &b->a_peername_addr6 ) )
+                                                       continue;
+#endif /* LDAP_PF_INET6 */
+
 #ifdef LDAP_PF_LOCAL
                                        /* extract path and try exact match */
                                        } else if ( b->a_peername_style == ACL_STYLE_PATH ) {
@@ -1603,6 +1660,8 @@ slap_acl_mask(
                        const char *dummy;
                        int rc, match = 0;
 
+                       ACL_RECORD_VALUE_STATE;
+
                        /* must have DN syntax */
                        if ( desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName &&
                                !is_at_syntax( desc->ad_type, SLAPD_NAMEUID_SYNTAX )) continue;
@@ -1659,7 +1718,8 @@ slap_acl_mask(
                                Debug( LDAP_DEBUG_ACL, "    <= check a_dynacl: %s\n",
                                        da->da_name, 0, 0 );
 
-                               (void)( *da->da_mask )( da->da_private, op, e, desc, val, nmatch, matches, &grant, &deny );
+                               (void)da->da_mask( da->da_private, op, e, desc,
+                                       val, nmatch, matches, &grant, &deny );
 
                                tgrant |= grant;
                                tdeny |= deny;