apply advanced peername ACL (ITS#2907)

This commit is contained in:
Pierangelo Masarati 2004-03-08 18:49:12 +00:00
parent 091246c6fd
commit a4e062ca36
4 changed files with 168 additions and 9 deletions

View 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;
}
}
}
}

View File

@ -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 )
"<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"

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

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