mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-24 13:24:56 +08:00
implement full IPv6 support in ACLs; use URL notation (as suggested by Howard) to disambiguate parsing (ITS#4756)
This commit is contained in:
parent
3164c73276
commit
97e6225cc9
@ -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 );
|
||||
|
||||
@ -1317,6 +1319,58 @@ 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 */
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
if ( ( addr.s6_addr32[i] & b->a_peername_mask6.s6_addr32[i] )
|
||||
!= b->a_peername_addr6.s6_addr32[i] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i != 4 )
|
||||
continue;
|
||||
#endif /* LDAP_PF_INET6 */
|
||||
|
||||
#ifdef LDAP_PF_LOCAL
|
||||
/* extract path and try exact match */
|
||||
} else if ( b->a_peername_style == ACL_STYLE_PATH ) {
|
||||
|
@ -804,6 +804,14 @@ parse_acl(
|
||||
} else if ( strcasecmp( style, "ip" ) == 0 ) {
|
||||
sty = ACL_STYLE_IP;
|
||||
|
||||
} else if ( strcasecmp( style, "ipv6" ) == 0 ) {
|
||||
#ifndef LDAP_PF_INET6
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: IPv6 not supported\n",
|
||||
fname, lineno, 0 );
|
||||
#endif /* ! LDAP_PF_INET6 */
|
||||
sty = ACL_STYLE_IPV6;
|
||||
|
||||
} else if ( strcasecmp( style, "path" ) == 0 ) {
|
||||
sty = ACL_STYLE_PATH;
|
||||
#ifndef LDAP_PF_LOCAL
|
||||
@ -1301,6 +1309,7 @@ parse_acl(
|
||||
case ACL_STYLE_EXPAND:
|
||||
/* cheap replacement to regex for simple expansion */
|
||||
case ACL_STYLE_IP:
|
||||
case ACL_STYLE_IPV6:
|
||||
case ACL_STYLE_PATH:
|
||||
/* legal, peername specific */
|
||||
break;
|
||||
@ -1384,6 +1393,52 @@ parse_acl(
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LDAP_PF_INET6
|
||||
} else if ( sty == ACL_STYLE_IPV6 ) {
|
||||
char *addr = NULL,
|
||||
*mask = NULL,
|
||||
*port = NULL;
|
||||
|
||||
split( right, '{', &addr, &port );
|
||||
split( addr, '%', &addr, &mask );
|
||||
|
||||
if ( inet_pton( AF_INET6, addr, &b->a_peername_addr6 ) != 1 ) {
|
||||
/* illegal address */
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"illegal peername address \"%s\".\n",
|
||||
fname, lineno, addr );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( mask == NULL ) {
|
||||
mask = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF";
|
||||
}
|
||||
|
||||
if ( inet_pton( AF_INET6, mask, &b->a_peername_mask6 ) != 1 ) {
|
||||
/* illegal mask */
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"illegal peername address mask "
|
||||
"\"%s\".\n",
|
||||
fname, lineno, mask );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
b->a_peername_port = -1;
|
||||
if ( port ) {
|
||||
char *end = NULL;
|
||||
|
||||
b->a_peername_port = strtol( port, &end, 10 );
|
||||
if ( end == port || end[0] != '}' ) {
|
||||
/* illegal port */
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"illegal peername port specification "
|
||||
"\"{%s}\".\n",
|
||||
fname, lineno, port );
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif /* LDAP_PF_INET6 */
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
@ -1388,9 +1388,9 @@ slap_open_listener(
|
||||
inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
|
||||
addr, sizeof addr);
|
||||
port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port );
|
||||
l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535");
|
||||
l.sl_name.bv_len = strlen(addr) + sizeof("IP=[]:65535");
|
||||
l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len );
|
||||
snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d",
|
||||
snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=[%s]:%d",
|
||||
addr, port );
|
||||
l.sl_name.bv_len = strlen( l.sl_name.bv_val );
|
||||
} break;
|
||||
@ -1595,7 +1595,7 @@ slap_listener(
|
||||
#ifdef LDAP_PF_LOCAL
|
||||
char peername[MAXPATHLEN + sizeof("PATH=")];
|
||||
#elif defined(LDAP_PF_INET6)
|
||||
char peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
|
||||
char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
|
||||
#else /* ! LDAP_PF_LOCAL && ! LDAP_PF_INET6 */
|
||||
char peername[sizeof("IP=255.255.255.255:65336")];
|
||||
#endif /* LDAP_PF_LOCAL */
|
||||
@ -1759,7 +1759,7 @@ slap_listener(
|
||||
peeraddr = (char *) inet_ntop( AF_INET6,
|
||||
&from.sa_in6_addr.sin6_addr,
|
||||
addr, sizeof addr );
|
||||
sprintf( peername, "IP=%s %d",
|
||||
sprintf( peername, "IP=[%s]:%d",
|
||||
peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
|
||||
(unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
|
||||
}
|
||||
@ -1767,10 +1767,10 @@ slap_listener(
|
||||
# endif /* LDAP_PF_INET6 */
|
||||
|
||||
case AF_INET:
|
||||
peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
|
||||
sprintf( peername, "IP=%s:%d",
|
||||
peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
|
||||
(unsigned) ntohs( from.sa_in_addr.sin_port ) );
|
||||
peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
|
||||
sprintf( peername, "IP=%s:%d",
|
||||
peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
|
||||
(unsigned) ntohs( from.sa_in_addr.sin_port ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1231,6 +1231,7 @@ typedef enum slap_style_e {
|
||||
ACL_STYLE_USERS,
|
||||
ACL_STYLE_SELF,
|
||||
ACL_STYLE_IP,
|
||||
ACL_STYLE_IPV6,
|
||||
ACL_STYLE_PATH
|
||||
} slap_style_t;
|
||||
|
||||
@ -1398,8 +1399,15 @@ typedef struct slap_access {
|
||||
/* connection related stuff */
|
||||
slap_style_t a_peername_style;
|
||||
struct berval a_peername_pat;
|
||||
#ifdef LDAP_PF_INET6
|
||||
struct in6_addr a_peername_addr6,
|
||||
a_peername_mask6;
|
||||
#define a_peername_addr a_peername_addr6.s6_addr32[0]
|
||||
#define a_peername_mask a_peername_mask6.s6_addr32[0]
|
||||
#else /* ! LDAP_PF_INET6 */
|
||||
unsigned long a_peername_addr,
|
||||
a_peername_mask;
|
||||
#endif /* ! LDAP_PF_INET6 */
|
||||
int a_peername_port;
|
||||
|
||||
slap_style_t a_sockname_style;
|
||||
|
Loading…
Reference in New Issue
Block a user