mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-30 13:30:57 +08:00
apply advanced peername ACL (ITS#2907)
This commit is contained in:
parent
091246c6fd
commit
a4e062ca36
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user