mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-02-23 14:09:39 +08:00
ITS#9419 Add support for HAProxy proxy protocol v2
This commit is contained in:
parent
dcca73370b
commit
146889f205
@ -36,13 +36,23 @@ This option specifies alternative listener configurations. The
|
|||||||
default is {{EX:ldap:///}} which implies {{TERM:LDAP}} over
|
default is {{EX:ldap:///}} which implies {{TERM:LDAP}} over
|
||||||
{{TERM:TCP}} on all interfaces on the default LDAP port 389. You
|
{{TERM:TCP}} on all interfaces on the default LDAP port 389. You
|
||||||
can specify specific host-port pairs or other protocol schemes (such
|
can specify specific host-port pairs or other protocol schemes (such
|
||||||
as {{EX:ldaps://}} or {{EX:ldapi://}}).
|
as {{EX:ldaps://}} or {{EX:ldapi://}}). slapd supports the HAProxy
|
||||||
|
proxy protocol version 2, which allows a load balancer or proxy
|
||||||
|
server to provide the remote client IP address to slapd to be used
|
||||||
|
for access control or logging. Listeners configured using either
|
||||||
|
{{EX:pldap:///}} or {{EX:pldaps:///}} URLS will only accept
|
||||||
|
connections that include the necessary proxy protocol header.
|
||||||
|
Connections to the ports used by these listeners should be restricted
|
||||||
|
at the network level to only trusted load balancers or proxies to
|
||||||
|
avoid spoofing of client IP addresses by third parties.
|
||||||
|
|
||||||
!block table
|
!block table
|
||||||
URL Protocol Transport
|
URL Protocol Transport
|
||||||
ldap:/// LDAP TCP port 389
|
ldap:/// LDAP TCP port 389
|
||||||
ldaps:/// LDAP over SSL TCP port 636
|
pldap:/// proxied LDAP TCP port 389
|
||||||
ldapi:/// LDAP IPC (Unix-domain socket)
|
ldaps:/// LDAP over SSL TCP port 636
|
||||||
|
pldaps:/// proxied LDAP over SSL TCP port 636
|
||||||
|
ldapi:/// LDAP IPC (Unix-domain socket)
|
||||||
!endblock
|
!endblock
|
||||||
|
|
||||||
For example, {{EX:-h
|
For example, {{EX:-h
|
||||||
|
@ -142,13 +142,24 @@ For example, if lloadd is given
|
|||||||
it will listen on 127.0.0.1:9009 for LDAP, 0.0.0.0:636 for LDAP over TLS,
|
it will listen on 127.0.0.1:9009 for LDAP, 0.0.0.0:636 for LDAP over TLS,
|
||||||
and LDAP over IPC (Unix domain sockets). Host 0.0.0.0 represents
|
and LDAP over IPC (Unix domain sockets). Host 0.0.0.0 represents
|
||||||
INADDR_ANY (any interface).
|
INADDR_ANY (any interface).
|
||||||
A space separated list of URLs is expected. The URLs should be of
|
A space separated list of URLs is expected. The URLs should be of the LDAP,
|
||||||
the LDAP, LDAPS, or LDAPI schemes, and generally
|
PLDAP, LDAPS, PLDAPS, or LDAPI schemes, and generally without a DN or other
|
||||||
without a DN or other optional parameters (excepting as discussed below).
|
optional parameters (excepting as discussed below). Support for the latter
|
||||||
Support for the latter two schemes depends on selected configuration
|
three schemes depends on selected configuration options. Hosts may be specified
|
||||||
options. Hosts may be specified by name or IPv4 and IPv6 address formats.
|
by name or IPv4 and IPv6 address formats. Ports, if specified, must be
|
||||||
Ports, if specified, must be numeric. The default ldap:// port is \fB389\fP
|
numeric. The default ldap:// port is \fB389\fP and the default ldaps:// port
|
||||||
and the default ldaps:// port is \fB636\fP.
|
is \fB636\fP, same for the proxy enabled variants.
|
||||||
|
|
||||||
|
The PLDAP and PLDAPS URL schemes provide support for the HAProxy proxy protocol
|
||||||
|
version 2, which allows a load balancer or proxy server to provide the remote
|
||||||
|
client IP address to slapd to be used for access control or logging. Ports
|
||||||
|
configured for PLDAP or PLDAPS will only accept connections that include the
|
||||||
|
necessary proxy protocol header. Connections to these ports should be
|
||||||
|
restricted at the network level to only trusted load balancers or proxies to
|
||||||
|
avoid spoofing of client IP addresses by third parties.
|
||||||
|
|
||||||
|
At the moment, the load balancer does not act on the recorded address in any
|
||||||
|
way.
|
||||||
|
|
||||||
For LDAP over IPC,
|
For LDAP over IPC,
|
||||||
.B name
|
.B name
|
||||||
|
@ -192,13 +192,21 @@ For example, if slapd is given
|
|||||||
it will listen on 127.0.0.1:9009 for LDAP, 0.0.0.0:636 for LDAP over TLS,
|
it will listen on 127.0.0.1:9009 for LDAP, 0.0.0.0:636 for LDAP over TLS,
|
||||||
and LDAP over IPC (Unix domain sockets). Host 0.0.0.0 represents
|
and LDAP over IPC (Unix domain sockets). Host 0.0.0.0 represents
|
||||||
INADDR_ANY (any interface).
|
INADDR_ANY (any interface).
|
||||||
A space separated list of URLs is expected. The URLs should be of
|
A space separated list of URLs is expected. The URLs should be of the LDAP,
|
||||||
the LDAP, LDAPS, or LDAPI schemes, and generally
|
PLDAP, LDAPS, PLDAPS, or LDAPI schemes, and generally without a DN or other
|
||||||
without a DN or other optional parameters (excepting as discussed below).
|
optional parameters (excepting as discussed below). Support for the latter
|
||||||
Support for the latter two schemes depends on selected configuration
|
three schemes depends on selected configuration options. Hosts may be specified
|
||||||
options. Hosts may be specified by name or IPv4 and IPv6 address formats.
|
by name or IPv4 and IPv6 address formats. Ports, if specified, must be
|
||||||
Ports, if specified, must be numeric. The default ldap:// port is \fB389\fP
|
numeric. The default ldap:// port is \fB389\fP and the default ldaps:// port
|
||||||
and the default ldaps:// port is \fB636\fP.
|
is \fB636\fP, same for the proxy enabled variants.
|
||||||
|
|
||||||
|
The PLDAP and PLDAPS URL schemes provide support for the HAProxy proxy protocol
|
||||||
|
version 2, which allows a load balancer or proxy server to provide the remote
|
||||||
|
client IP address to slapd to be used for access control or logging. Ports
|
||||||
|
configured for PLDAP or PLDAPS will only accept connections that include the
|
||||||
|
necessary proxy protocol header. Connections to these ports should be
|
||||||
|
restricted at the network level to only trusted load balancers or proxies to
|
||||||
|
avoid spoofing of client IP addresses by third parties.
|
||||||
|
|
||||||
For LDAP over IPC,
|
For LDAP over IPC,
|
||||||
.B name
|
.B name
|
||||||
|
@ -32,6 +32,9 @@ ldap_pvt_url_scheme2proto LDAP_P((
|
|||||||
LDAP_F ( int )
|
LDAP_F ( int )
|
||||||
ldap_pvt_url_scheme2tls LDAP_P((
|
ldap_pvt_url_scheme2tls LDAP_P((
|
||||||
const char * ));
|
const char * ));
|
||||||
|
LDAP_F ( int )
|
||||||
|
ldap_pvt_url_scheme2proxied LDAP_P((
|
||||||
|
const char * ));
|
||||||
|
|
||||||
LDAP_F ( int )
|
LDAP_F ( int )
|
||||||
ldap_pvt_url_scheme_port LDAP_P((
|
ldap_pvt_url_scheme_port LDAP_P((
|
||||||
|
@ -123,8 +123,12 @@ LDAP_BEGIN_DECL
|
|||||||
|
|
||||||
#define LDAP_URL_PREFIX "ldap://"
|
#define LDAP_URL_PREFIX "ldap://"
|
||||||
#define LDAP_URL_PREFIX_LEN STRLENOF(LDAP_URL_PREFIX)
|
#define LDAP_URL_PREFIX_LEN STRLENOF(LDAP_URL_PREFIX)
|
||||||
|
#define PLDAP_URL_PREFIX "pldap://"
|
||||||
|
#define PLDAP_URL_PREFIX_LEN STRLENOF(PLDAP_URL_PREFIX)
|
||||||
#define LDAPS_URL_PREFIX "ldaps://"
|
#define LDAPS_URL_PREFIX "ldaps://"
|
||||||
#define LDAPS_URL_PREFIX_LEN STRLENOF(LDAPS_URL_PREFIX)
|
#define LDAPS_URL_PREFIX_LEN STRLENOF(LDAPS_URL_PREFIX)
|
||||||
|
#define PLDAPS_URL_PREFIX "pldaps://"
|
||||||
|
#define PLDAPS_URL_PREFIX_LEN STRLENOF(PLDAPS_URL_PREFIX)
|
||||||
#define LDAPI_URL_PREFIX "ldapi://"
|
#define LDAPI_URL_PREFIX "ldapi://"
|
||||||
#define LDAPI_URL_PREFIX_LEN STRLENOF(LDAPI_URL_PREFIX)
|
#define LDAPI_URL_PREFIX_LEN STRLENOF(LDAPI_URL_PREFIX)
|
||||||
#ifdef LDAP_CONNECTIONLESS
|
#ifdef LDAP_CONNECTIONLESS
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* LDAP URLs look like this:
|
* LDAP URLs look like this:
|
||||||
* ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
|
* [p]ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
|
||||||
*
|
*
|
||||||
* where:
|
* where:
|
||||||
* attributes is a comma separated list
|
* attributes is a comma separated list
|
||||||
@ -59,7 +59,7 @@ int ldap_pvt_url_scheme2proto( const char *scheme )
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( strcmp("ldap", scheme) == 0 ) {
|
if( strcmp("ldap", scheme) == 0 || strcmp("pldap", scheme) == 0 ) {
|
||||||
return LDAP_PROTO_TCP;
|
return LDAP_PROTO_TCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ int ldap_pvt_url_scheme2proto( const char *scheme )
|
|||||||
return LDAP_PROTO_IPC;
|
return LDAP_PROTO_IPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( strcmp("ldaps", scheme) == 0 ) {
|
if( strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0 ) {
|
||||||
return LDAP_PROTO_TCP;
|
return LDAP_PROTO_TCP;
|
||||||
}
|
}
|
||||||
#ifdef LDAP_CONNECTIONLESS
|
#ifdef LDAP_CONNECTIONLESS
|
||||||
@ -86,7 +86,7 @@ int ldap_pvt_url_scheme_port( const char *scheme, int port )
|
|||||||
if( port ) return port;
|
if( port ) return port;
|
||||||
if( scheme == NULL ) return port;
|
if( scheme == NULL ) return port;
|
||||||
|
|
||||||
if( strcmp("ldap", scheme) == 0 ) {
|
if( strcmp("ldap", scheme) == 0 || strcmp("pldap", scheme) == 0 ) {
|
||||||
return LDAP_PORT;
|
return LDAP_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ int ldap_pvt_url_scheme_port( const char *scheme, int port )
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( strcmp("ldaps", scheme) == 0 ) {
|
if( strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0 ) {
|
||||||
return LDAPS_PORT;
|
return LDAPS_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,19 @@ ldap_pvt_url_scheme2tls( const char *scheme )
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return strcmp("ldaps", scheme) == 0;
|
return strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ldap_pvt_url_scheme2proxied( const char *scheme )
|
||||||
|
{
|
||||||
|
assert( scheme != NULL );
|
||||||
|
|
||||||
|
if( scheme == NULL ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strcmp("pldap", scheme) == 0 || strcmp("pldaps", scheme) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -150,7 +162,7 @@ ldap_is_ldaps_url( LDAP_CONST char *url )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return strcmp(scheme, "ldaps") == 0;
|
return strcmp(scheme, "ldaps") == 0 || strcmp(scheme, "pldaps");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -228,6 +240,14 @@ skip_url_prefix(
|
|||||||
return( p );
|
return( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for "pldap://" prefix */
|
||||||
|
if ( strncasecmp( p, PLDAP_URL_PREFIX, PLDAP_URL_PREFIX_LEN ) == 0 ) {
|
||||||
|
/* skip over "pldap://" prefix and return success */
|
||||||
|
p += PLDAP_URL_PREFIX_LEN;
|
||||||
|
*scheme = "pldap";
|
||||||
|
return( p );
|
||||||
|
}
|
||||||
|
|
||||||
/* check for "ldaps://" prefix */
|
/* check for "ldaps://" prefix */
|
||||||
if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
|
if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
|
||||||
/* skip over "ldaps://" prefix and return success */
|
/* skip over "ldaps://" prefix and return success */
|
||||||
@ -236,6 +256,14 @@ skip_url_prefix(
|
|||||||
return( p );
|
return( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for "pldaps://" prefix */
|
||||||
|
if ( strncasecmp( p, PLDAPS_URL_PREFIX, PLDAPS_URL_PREFIX_LEN ) == 0 ) {
|
||||||
|
/* skip over "pldaps://" prefix and return success */
|
||||||
|
p += PLDAPS_URL_PREFIX_LEN;
|
||||||
|
*scheme = "pldaps";
|
||||||
|
return( p );
|
||||||
|
}
|
||||||
|
|
||||||
/* check for "ldapi://" prefix */
|
/* check for "ldapi://" prefix */
|
||||||
if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
|
if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
|
||||||
/* skip over "ldapi://" prefix and return success */
|
/* skip over "ldapi://" prefix and return success */
|
||||||
|
@ -22,7 +22,7 @@ NT_SRCS = ../slapd/nt_svc.c
|
|||||||
NT_OBJS = ../slapd/nt_svc.o ../../libraries/liblutil/slapdmsg.res
|
NT_OBJS = ../slapd/nt_svc.o ../../libraries/liblutil/slapdmsg.res
|
||||||
|
|
||||||
SRCS += main.c value.c \
|
SRCS += main.c value.c \
|
||||||
../slapd/ch_malloc.c ../slapd/sl_malloc.c ../slapd/user.c
|
../slapd/ch_malloc.c ../slapd/proxyp.c ../slapd/sl_malloc.c ../slapd/user.c
|
||||||
|
|
||||||
OBJS = $(patsubst %.c,%.o,$(SRCS)) $(@PLAT@_OBJS)
|
OBJS = $(patsubst %.c,%.o,$(SRCS)) $(@PLAT@_OBJS)
|
||||||
|
|
||||||
|
@ -404,6 +404,8 @@ lload_open_listener(
|
|||||||
l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );
|
l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );
|
||||||
#endif /* HAVE_TLS */
|
#endif /* HAVE_TLS */
|
||||||
|
|
||||||
|
l.sl_is_proxied = ldap_pvt_url_scheme2proxied( lud->lud_scheme );
|
||||||
|
|
||||||
#ifdef LDAP_TCP_BUFFER
|
#ifdef LDAP_TCP_BUFFER
|
||||||
l.sl_tcp_rmem = 0;
|
l.sl_tcp_rmem = 0;
|
||||||
l.sl_tcp_wmem = 0;
|
l.sl_tcp_wmem = 0;
|
||||||
@ -889,6 +891,16 @@ lload_listener(
|
|||||||
}
|
}
|
||||||
#endif /* SO_KEEPALIVE || TCP_NODELAY */
|
#endif /* SO_KEEPALIVE || TCP_NODELAY */
|
||||||
|
|
||||||
|
if ( sl->sl_is_proxied ) {
|
||||||
|
if ( !proxyp( s, from ) ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "lload_listener: "
|
||||||
|
"proxyp(%ld) failed\n",
|
||||||
|
(long)s );
|
||||||
|
lloadd_close( s );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cflag = 0;
|
cflag = 0;
|
||||||
switch ( from->sa_addr.sa_family ) {
|
switch ( from->sa_addr.sa_family ) {
|
||||||
#ifdef LDAP_PF_LOCAL
|
#ifdef LDAP_PF_LOCAL
|
||||||
@ -1118,8 +1130,9 @@ lload_listener_activate( void )
|
|||||||
|
|
||||||
lload_listeners[l]->sl_busy = 1;
|
lload_listeners[l]->sl_busy = 1;
|
||||||
listener = evconnlistener_new( listener_base, lload_listener,
|
listener = evconnlistener_new( listener_base, lload_listener,
|
||||||
lload_listeners[l], LEV_OPT_THREADSAFE, SLAPD_LISTEN_BACKLOG,
|
lload_listeners[l],
|
||||||
lload_listeners[l]->sl_sd );
|
LEV_OPT_THREADSAFE|LEV_OPT_DEFERRED_ACCEPT,
|
||||||
|
SLAPD_LISTEN_BACKLOG, lload_listeners[l]->sl_sd );
|
||||||
if ( !listener ) {
|
if ( !listener ) {
|
||||||
int err = sock_errno();
|
int err = sock_errno();
|
||||||
|
|
||||||
|
@ -469,6 +469,7 @@ struct LloadListener {
|
|||||||
#ifdef HAVE_TLS
|
#ifdef HAVE_TLS
|
||||||
int sl_is_tls;
|
int sl_is_tls;
|
||||||
#endif
|
#endif
|
||||||
|
int sl_is_proxied;
|
||||||
struct event_base *base;
|
struct event_base *base;
|
||||||
struct evconnlistener *listener;
|
struct evconnlistener *listener;
|
||||||
int sl_mute; /* Listener is temporarily disabled due to emfile */
|
int sl_mute; /* Listener is temporarily disabled due to emfile */
|
||||||
|
@ -29,7 +29,7 @@ SRCS = main.c globals.c bconfig.c config.c daemon.c \
|
|||||||
dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
|
dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
|
||||||
value.c ava.c bind.c unbind.c abandon.c filterentry.c \
|
value.c ava.c bind.c unbind.c abandon.c filterentry.c \
|
||||||
phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
|
phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
|
||||||
lock.c controls.c extended.c passwd.c \
|
lock.c controls.c extended.c passwd.c proxyp.c \
|
||||||
schema.c schema_check.c schema_init.c schema_prep.c \
|
schema.c schema_check.c schema_init.c schema_prep.c \
|
||||||
schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
|
schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
|
||||||
oidm.c starttls.c index.c sets.c referral.c root_dse.c \
|
oidm.c starttls.c index.c sets.c referral.c root_dse.c \
|
||||||
@ -47,7 +47,7 @@ OBJS = main.o globals.o bconfig.o config.o daemon.o \
|
|||||||
dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
|
dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
|
||||||
value.o ava.o bind.o unbind.o abandon.o filterentry.o \
|
value.o ava.o bind.o unbind.o abandon.o filterentry.o \
|
||||||
phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
|
phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
|
||||||
lock.o controls.o extended.o passwd.o \
|
lock.o controls.o extended.o passwd.o proxyp.o \
|
||||||
schema.o schema_check.o schema_init.o schema_prep.o \
|
schema.o schema_check.o schema_init.o schema_prep.o \
|
||||||
schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
|
schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
|
||||||
oidm.o starttls.o index.o sets.o referral.o root_dse.o \
|
oidm.o starttls.o index.o sets.o referral.o root_dse.o \
|
||||||
|
@ -1549,6 +1549,8 @@ slap_open_listener(
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_TLS */
|
#endif /* HAVE_TLS */
|
||||||
|
|
||||||
|
l.sl_is_proxied = ldap_pvt_url_scheme2proxied( lud->lud_scheme );
|
||||||
|
|
||||||
#ifdef LDAP_TCP_BUFFER
|
#ifdef LDAP_TCP_BUFFER
|
||||||
l.sl_tcp_rmem = 0;
|
l.sl_tcp_rmem = 0;
|
||||||
l.sl_tcp_wmem = 0;
|
l.sl_tcp_wmem = 0;
|
||||||
@ -2270,6 +2272,13 @@ slap_listener(
|
|||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
# endif /* LDAP_PF_INET6 */
|
# endif /* LDAP_PF_INET6 */
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
|
if ( sl->sl_is_proxied ) {
|
||||||
|
if ( !proxyp( sfd, &from ) ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "slapd(%ld): proxyp failed\n", (long)sfd );
|
||||||
|
slapd_close( sfd );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
lutil_sockaddrstr( &from, &peerbv );
|
lutil_sockaddrstr( &from, &peerbv );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1556,6 +1556,11 @@ LDAP_SLAPD_F (void) slap_passwd_init (void);
|
|||||||
*/
|
*/
|
||||||
LDAP_SLAPD_F (char *) phonetic LDAP_P(( char *s ));
|
LDAP_SLAPD_F (char *) phonetic LDAP_P(( char *s ));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* proxyp.c
|
||||||
|
*/
|
||||||
|
LDAP_SLAPD_F (int) proxyp LDAP_P((ber_socket_t sfd, Sockaddr *from));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* referral.c
|
* referral.c
|
||||||
*/
|
*/
|
||||||
|
219
servers/slapd/proxyp.c
Normal file
219
servers/slapd/proxyp.c
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/* $OpenLDAP$ */
|
||||||
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||||
|
*
|
||||||
|
* Copyright 2000-2020 The OpenLDAP Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted only as authorized by the OpenLDAP
|
||||||
|
* Public License.
|
||||||
|
*
|
||||||
|
* A copy of this license is available in the file LICENSE in the
|
||||||
|
* top-level directory of the distribution or, alternatively, at
|
||||||
|
* <http://www.OpenLDAP.org/license.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portable.h"
|
||||||
|
#include "slap.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <lber_types.h>
|
||||||
|
#include <ac/string.h>
|
||||||
|
#include <ac/errno.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t sig[12]; /* hex 0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a */
|
||||||
|
uint8_t ver_cmd; /* protocol version and command */
|
||||||
|
uint8_t fam; /* protocol family and address */
|
||||||
|
uint16_t len; /* length of address data */
|
||||||
|
} proxyp_header;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct { /* for TCP/UDP over IPv4, len = 12 */
|
||||||
|
uint32_t src_addr;
|
||||||
|
uint32_t dst_addr;
|
||||||
|
uint16_t src_port;
|
||||||
|
uint16_t dst_port;
|
||||||
|
} ip4;
|
||||||
|
struct { /* for TCP/UDP over IPv6, len = 36 */
|
||||||
|
uint8_t src_addr[16];
|
||||||
|
uint8_t dst_addr[16];
|
||||||
|
uint16_t src_port;
|
||||||
|
uint16_t dst_port;
|
||||||
|
} ip6;
|
||||||
|
struct { /* for AF_UNIX sockets, len = 216 */
|
||||||
|
uint8_t src_addr[108];
|
||||||
|
uint8_t dst_addr[108];
|
||||||
|
} unx;
|
||||||
|
} proxyp_addr;
|
||||||
|
|
||||||
|
static const uint8_t proxyp_sig[12] = {
|
||||||
|
0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x0d, 0x0a, 0x51, 0x55, 0x49, 0x54, 0x0a,
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
proxyp( ber_socket_t sfd, Sockaddr *from ) {
|
||||||
|
proxyp_header pph;
|
||||||
|
proxyp_addr ppa;
|
||||||
|
char peername[LUTIL_ADDRLEN];
|
||||||
|
struct berval peerbv = BER_BVC(peername);
|
||||||
|
/* Maximum size of header minus static component size is max option size */
|
||||||
|
uint8_t proxyp_options[536 - 16];
|
||||||
|
int pph_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
peername[0] = '\0';
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = tcp_read( SLAP_FD2SOCK( sfd ), &pph, sizeof(pph) );
|
||||||
|
} while ( ret == -1 && errno == EINTR );
|
||||||
|
|
||||||
|
if ( ret == -1 ) {
|
||||||
|
char ebuf[128];
|
||||||
|
int save_errno = errno;
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"header read failed %d (%s)\n",
|
||||||
|
(long)sfd, save_errno,
|
||||||
|
AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
|
||||||
|
return 0;
|
||||||
|
} else if ( ret != sizeof(pph) ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"header read insufficient data %d\n",
|
||||||
|
(long)sfd, ret );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( memcmp( pph.sig, proxyp_sig, 12 ) != 0 ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"invalid header signature\n", (long)sfd );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( pph.ver_cmd & 0xF0 ) != 0x20 ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"invalid header version %x\n",
|
||||||
|
(long)sfd, pph.ver_cmd & 0xF0 );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pph_len = ntohs( pph.len );
|
||||||
|
if ( ( pph.ver_cmd & 0x0F ) == 0x01 ) { /* PROXY command */
|
||||||
|
int addr_len;
|
||||||
|
switch ( pph.fam ) {
|
||||||
|
case 0x11: /* TCPv4 */
|
||||||
|
addr_len = sizeof( ppa.ip4 );
|
||||||
|
break;
|
||||||
|
case 0x21: /* TCPv6 */
|
||||||
|
addr_len = sizeof( ppa.ip6 );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"unsupported protocol %x\n",
|
||||||
|
(long)sfd, pph.fam );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pph_len < addr_len ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"address length %d too small, expecting %d\n",
|
||||||
|
(long)sfd, pph_len, addr_len );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = tcp_read( SLAP_FD2SOCK (sfd), &ppa, addr_len );
|
||||||
|
} while ( ret == -1 && errno == EINTR );
|
||||||
|
|
||||||
|
if ( ret == -1 ) {
|
||||||
|
char ebuf[128];
|
||||||
|
int save_errno = errno;
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"address read failed %d (%s)\n",
|
||||||
|
(long)sfd, save_errno,
|
||||||
|
AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
|
||||||
|
return 0;
|
||||||
|
} else if ( ret != addr_len ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"address read insufficient data, expecting %d, read %d\n",
|
||||||
|
(long)sfd, addr_len, ret );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pph_len -= addr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( pph.ver_cmd & 0x0F ) {
|
||||||
|
case 0x01: /* PROXY command */
|
||||||
|
switch ( pph.fam ) {
|
||||||
|
case 0x11: /* TCPv4 */
|
||||||
|
lutil_sockaddrstr( from, &peerbv );
|
||||||
|
Debug( LDAP_DEBUG_STATS, "proxyp(%ld): via %s\n",
|
||||||
|
(long)sfd, peername );
|
||||||
|
|
||||||
|
from->sa_in_addr.sin_family = AF_INET;
|
||||||
|
from->sa_in_addr.sin_addr.s_addr = ppa.ip4.src_addr;
|
||||||
|
from->sa_in_addr.sin_port = ppa.ip4.src_port;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x21: /* TCPv6 */
|
||||||
|
lutil_sockaddrstr( from, &peerbv );
|
||||||
|
Debug( LDAP_DEBUG_STATS, "proxyp(%ld): via %s\n",
|
||||||
|
(long)sfd, peername );
|
||||||
|
from->sa_in6_addr.sin6_family = AF_INET6;
|
||||||
|
memcpy( &from->sa_in6_addr.sin6_addr, ppa.ip6.src_addr,
|
||||||
|
sizeof(ppa.ip6.src_addr) );
|
||||||
|
from->sa_in6_addr.sin6_port = ppa.ip6.src_port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x00: /* LOCAL command */
|
||||||
|
Debug( LDAP_DEBUG_CONNS, "proxyp(%ld): "
|
||||||
|
"local connection, ignoring proxy data\n",
|
||||||
|
(long)sfd );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): invalid command %x\n",
|
||||||
|
(long)sfd, pph.ver_cmd & 0x0F );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear out any options left in proxy packet */
|
||||||
|
if ( pph_len > 0 ) {
|
||||||
|
if (pph_len > sizeof( proxyp_options ) ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"options size %d too big\n",
|
||||||
|
(long)sfd, pph_len );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = tcp_read( SLAP_FD2SOCK (sfd), &proxyp_options, pph_len );
|
||||||
|
} while ( ret == -1 && errno == EINTR );
|
||||||
|
|
||||||
|
if ( ret == -1 ) {
|
||||||
|
char ebuf[128];
|
||||||
|
int save_errno = errno;
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"options read failed %d (%s)\n",
|
||||||
|
(long)sfd, save_errno,
|
||||||
|
AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
|
||||||
|
return 0;
|
||||||
|
} else if ( ret != pph_len ) {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
|
||||||
|
"options read insufficient data, expecting %d, read %d\n",
|
||||||
|
(long)sfd, pph_len, ret );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
@ -3003,6 +3003,7 @@ struct Listener {
|
|||||||
#ifdef LDAP_CONNECTIONLESS
|
#ifdef LDAP_CONNECTIONLESS
|
||||||
int sl_is_udp; /* UDP listener is also data port */
|
int sl_is_udp; /* UDP listener is also data port */
|
||||||
#endif
|
#endif
|
||||||
|
int sl_is_proxied;
|
||||||
int sl_mute; /* Listener is temporarily disabled due to emfile */
|
int sl_mute; /* Listener is temporarily disabled due to emfile */
|
||||||
int sl_busy; /* Listener is busy (accept thread activated) */
|
int sl_busy; /* Listener is busy (accept thread activated) */
|
||||||
ber_socket_t sl_sd;
|
ber_socket_t sl_sd;
|
||||||
|
Loading…
Reference in New Issue
Block a user