]> git.sur5r.net Git - openldap/commitdiff
apply advanced peername ACL (ITS#2907)
authorPierangelo Masarati <ando@openldap.org>
Mon, 8 Mar 2004 18:49:12 +0000 (18:49 +0000)
committerPierangelo Masarati <ando@openldap.org>
Mon, 8 Mar 2004 18:49:12 +0000 (18:49 +0000)
servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/search.c
servers/slapd/slap.h

index 1ddd783cd2acd36447e3fd052b375976a2352bde..e73d5d2cfd76e27c19a560e34cdd251188d73da4 100644 (file)
@@ -62,6 +62,12 @@ static struct berval
        aci_bv_set_ref          = BER_BVC("set-ref"),
        aci_bv_grant            = BER_BVC("grant"),
        aci_bv_deny             = BER_BVC("deny"),
+
+       aci_bv_ip_eq            = BER_BVC("IP="),
+#ifdef LDAP_PF_LOCAL
+       aci_bv_path_eq          = BER_BVC("PATH="),
+       aci_bv_dirsep           = BER_BVC(LDAP_DIRSEP),
+#endif /* LDAP_PF_LOCAL */
        
        aci_bv_group_class      = BER_BVC(SLAPD_GROUP_CLASS),
        aci_bv_group_attr       = BER_BVC(SLAPD_GROUP_ATTR),
@@ -985,9 +991,80 @@ dn_match_cleanup:;
                                        {
                                                continue;
                                        }
+
                                } else {
-                                       if ( ber_bvstrcasecmp( &b->a_peername_pat, &op->o_conn->c_peer_name ) != 0 )
-                                               continue;
+                                       /* try exact match */
+                                       if ( b->a_peername_style == ACL_STYLE_BASE ) {
+                                               if ( ber_bvstrcasecmp( &b->a_peername_pat, &op->o_conn->c_peer_name ) != 0 )
+                                                       continue;
+
+                                       /* extract IP and try exact match */
+                                       } else if ( b->a_peername_style == ACL_STYLE_IP ) {
+                                               char            *port;
+                                               char            buf[] = "255.255.255.255";
+                                               struct berval   ip;
+                                               unsigned long   addr;
+                                               int             port_number = -1;
+                                               
+                                               if ( strncasecmp( op->o_conn->c_peer_name.bv_val, 
+                                                                       aci_bv_ip_eq.bv_val, aci_bv_ip_eq.bv_len ) != 0 ) 
+                                                       continue;
+
+                                               ip.bv_val = op->o_conn->c_peer_name.bv_val + aci_bv_ip_eq.bv_len;
+                                               ip.bv_len = op->o_conn->c_peer_name.bv_len - aci_bv_ip_eq.bv_len;
+
+                                               port = strrchr( ip.bv_val, ':' );
+                                               if ( port ) {
+                                                       char    *next;
+                                                       
+                                                       ip.bv_len = port - ip.bv_val;
+                                                       ++port;
+                                                       port_number = strtol( port, &next, 10 );
+                                                       if ( next[0] != '\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';
+
+                                               addr = inet_addr( buf );
+
+                                               /* unable to convert? */
+                                               if ( addr == (unsigned long)(-1) )
+                                                       continue;
+
+                                               if ( (addr & b->a_peername_mask) != b->a_peername_addr )
+                                                       continue;
+
+#ifdef LDAP_PF_LOCAL
+                                       /* extract path and try exact match */
+                                       } else if ( b->a_peername_style == ACL_STYLE_PATH ) {
+                                               struct berval path;
+                                               
+                                               if ( strncmp( op->o_conn->c_peer_name.bv_val,
+                                                                       aci_bv_path_eq.bv_val, aci_bv_path_eq.bv_len ) != 0 )
+                                                       continue;
+
+                                               path.bv_val = op->o_conn->c_peer_name.bv_val + aci_bv_path_eq.bv_len;
+                                               path.bv_len = op->o_conn->c_peer_name.bv_len - aci_bv_path_eq.bv_len;
+
+                                               if ( ber_bvcmp( &b->a_peername_pat, &path ) != 0 )
+                                                       continue;
+
+#endif /* LDAP_PF_LOCAL */
+
+                                       /* exact match (very unlikely...) */
+                                       } else if ( ber_bvcmp( &op->o_conn->c_peer_name, &b->a_peername_pat ) != 0 ) {
+                                                       continue;
+                                       }
                                }
                        }
                }
index 3eb78ea954eb9b6110168468de5b23ddf311f810..93f173611be75045e6059ca4b4c8af610b26dfcc 100644 (file)
 #include "lber_pvt.h"
 #include "lutil.h"
 
-static char *style_strings[] = { "regex",
-       "base", "one", "subtree", "children", NULL };
+static char *style_strings[] = {
+       "regex",
+       "base",
+       "one",
+       "subtree",
+       "children",
+       "attrof",
+       "ip",
+       "path",
+       NULL
+};
 
 static void            split(char *line, int splitchar, char **left, char **right);
 static void            access_append(Access **l, Access *a);
@@ -418,6 +427,17 @@ parse_acl(
                                } else if ( strcasecmp( style, "regex" ) == 0 ) {
                                        sty = ACL_STYLE_REGEX;
 
+                               } else if ( strcasecmp( style, "ip" ) == 0 ) {
+                                       sty = ACL_STYLE_IP;
+
+                               } else if ( strcasecmp( style, "path" ) == 0 ) {
+                                       sty = ACL_STYLE_PATH;
+#ifndef LDAP_PF_LOCAL
+                                       fprintf( stderr, "%s: line %d: "
+                                               "path style modifier is useless without local\n",
+                                               fname, lineno );
+#endif /* LDAP_PF_LOCAL */
+
                                } else {
                                        fprintf( stderr,
                                                "%s: line %d: unknown style \"%s\" in by clause\n",
@@ -741,7 +761,14 @@ parse_acl(
                                }
 
                                if ( strcasecmp( left, "peername" ) == 0 ) {
-                                       if (sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE) {
+                                       switch (sty) {
+                                       case ACL_STYLE_REGEX:
+                                       case ACL_STYLE_BASE:
+                                       case ACL_STYLE_IP:
+                                       case ACL_STYLE_PATH:
+                                               break;
+
+                                       default:
                                                fprintf( stderr, "%s: line %d: "
                                                        "inappropriate style \"%s\" in by clause\n",
                                                    fname, lineno, style );
@@ -770,8 +797,53 @@ parse_acl(
                                                        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 */
+                                                               fprintf( stderr, "%s: line %d: "
+                                                                       "illegal peername address \"%s\".\n",
+                                                                       fname, lineno, addr );
+                                                               acl_usage();
+                                                       }
+
+                                                       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 */
+                                                                       fprintf( stderr, "%s: line %d: "
+                                                                               "illegal peername address mask \"%s\".\n",
+                                                                               fname, lineno, mask );
+                                                                       acl_usage();
+                                                               }
+                                                       } 
+
+                                                       b->a_peername_port = -1;
+                                                       if ( port ) {
+                                                               char    *end = NULL;
+
+                                                               b->a_peername_port = strtol( port, &end, 10 );
+                                                               if ( end[ 0 ] != '}' ) {
+                                                                       /* illegal port */
+                                                                       fprintf( stderr, "%s: line %d: "
+                                                                               "illegal peername port specification \"{%s}\".\n",
+                                                                               fname, lineno, port );
+                                                                       acl_usage();
+                                                               }
+                                                       }
+                                               }
                                        }
                                        continue;
                                }
@@ -1389,14 +1461,16 @@ acl_usage( void )
                "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
                        "\t[dnattr=<attrname>]\n"
                        "\t[group[/<objectclass>[/<attrname>]][.<style>]=<group>]\n"
-                       "\t[peername[.<style>]=<peer>] [sockname[.<style>]=<name>]\n",
-                       "\t[domain[.<style>]=<domain>] [sockurl[.<style>]=<url>]\n"
+                       "\t[peername[.<peernamestyle>]=<peer>] [sockname[.<style>]=<name>]\n",
+                       "\t[domain[.<domainstyle>]=<domain>] [sockurl[.<style>]=<url>]\n"
 #ifdef SLAPD_ACI_ENABLED
                        "\t[aci=<attrname>]\n"
 #endif
                        "\t[ssf=<n>] [transport_ssf=<n>] [tls_ssf=<n>] [sasl_ssf=<n>]\n"
-               "<dnstyle> ::= base | exact | one | subtree | children | regex\n"
+               "<dnstyle> ::= base | exact | one(level) | sub(tree) | children | regex\n"
                "<style> ::= regex | base | exact\n"
+               "<peernamestyle> ::= regex | exact | ip | path\n"
+               "<domainstyle> ::= regex | base | exact | sub(tree)\n"
                "<access> ::= [self]{<level>|<priv>}\n"
                "<level> ::= none | auth | compare | search | read | write\n"
                "<priv> ::= {=|+|-}{w|r|s|c|x|0}+\n"
index d1aa9eca6ae75d28a5a12c6c5baa471e45e87a7b..c5852c8590b3013304b5ea3912e2da1c9014fd4f 100644 (file)
@@ -413,6 +413,8 @@ do_search(
        } else {
                ( void ) get_limits( op, &op->o_ndn, &op->ors_limit );
 
+               assert( op->ors_limit != NULL );
+
                /* if no limit is required, use soft limit */
                if ( op->ors_tlimit <= 0 ) {
                        op->ors_tlimit = op->ors_limit->lms_t_soft;
index 2132253e5a762de1e85301c61606f51bd38e934b..41298960d4024f788ba243588dd30d220ee6250d 100644 (file)
@@ -1082,7 +1082,9 @@ typedef enum slap_style_e {
        ACL_STYLE_ONE,
        ACL_STYLE_SUBTREE,
        ACL_STYLE_CHILDREN,
-       ACL_STYLE_ATTROF
+       ACL_STYLE_ATTROF,
+       ACL_STYLE_IP,
+       ACL_STYLE_PATH
 } slap_style_t;
 
 typedef struct slap_authz_info {
@@ -1171,6 +1173,10 @@ typedef struct slap_access {
 
        slap_style_t a_peername_style;
        struct berval   a_peername_pat;
+       unsigned long   a_peername_addr,
+                       a_peername_mask;
+       int             a_peername_port;
+
        slap_style_t a_sockname_style;
        struct berval   a_sockname_pat;