From: Pierangelo Masarati Date: Mon, 8 Mar 2004 18:49:12 +0000 (+0000) Subject: apply advanced peername ACL (ITS#2907) X-Git-Tag: OPENLDAP_REL_ENG_2_2_BP~344 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a4e062ca367a350a3b924208222d113d3f1c1b03;p=openldap apply advanced peername ACL (ITS#2907) --- diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 1ddd783cd2..e73d5d2cfd 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -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; + } } } } diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 3eb78ea954..93f173611b 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -38,8 +38,17 @@ #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 ) " ::= [ * | anonymous | users | self | dn[.]= ]\n" "\t[dnattr=]\n" "\t[group[/[/]][.