mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-05 22:50:51 -05:00
ITS#4893 define LDAP_PF_LOCAL_SENDMSG in <ac/socket.h> if a message must
be sent to transmit client credentials. Buffer the message data.
This commit is contained in:
parent
724784e6cb
commit
7426ab07fc
9 changed files with 127 additions and 58 deletions
|
|
@ -213,8 +213,24 @@ LDAP_F (int) ldap_pvt_inet_aton LDAP_P(( const char *, struct in_addr * ));
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETPEEREID
|
||||
LDAP_LUTIL_F( int ) getpeereid( int s, uid_t *, gid_t * );
|
||||
#if defined(LDAP_PF_LOCAL) && \
|
||||
!defined(HAVE_GETPEEREID) && \
|
||||
!defined(HAVE_GETPEERUCRED) && \
|
||||
!defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
|
||||
defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
|
||||
defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
|
||||
# define LDAP_PF_LOCAL_SENDMSG 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETPEEREID
|
||||
#define LUTIL_GETPEEREID( s, uid, gid, bv ) getpeereid( s, uid, gid )
|
||||
#elif defined(LDAP_PF_LOCAL_SENDMSG)
|
||||
struct berval;
|
||||
LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t *, struct berval *bv );
|
||||
#define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid, bv )
|
||||
#else
|
||||
LDAP_LUTIL_F( int ) lutil_getpeereid( int s, uid_t *, gid_t * );
|
||||
#define LUTIL_GETPEEREID( s, uid, gid, bv ) lutil_getpeereid( s, uid, gid )
|
||||
#endif
|
||||
|
||||
/* DNS RFC defines max host name as 255. New systems seem to use 1024 */
|
||||
|
|
|
|||
|
|
@ -138,8 +138,12 @@ typedef struct lber_memory_fns {
|
|||
#define LBER_SB_OPT_NEEDS_WRITE 12
|
||||
#define LBER_SB_OPT_GET_MAX_INCOMING 13
|
||||
#define LBER_SB_OPT_SET_MAX_INCOMING 14
|
||||
|
||||
/* Only meaningful ifdef LDAP_PF_LOCAL_SENDMSG */
|
||||
#define LBER_SB_OPT_UNGET_BUF 15
|
||||
|
||||
/* Largest option used by the library */
|
||||
#define LBER_SB_OPT_OPT_MAX 14
|
||||
#define LBER_SB_OPT_OPT_MAX 15
|
||||
|
||||
/* LBER IO operations stacking levels */
|
||||
#define LBER_SBIOD_LEVEL_PROVIDER 10
|
||||
|
|
|
|||
|
|
@ -99,9 +99,13 @@ struct sockbuf {
|
|||
#define sb_options sb_opts.lbo_options
|
||||
#define sb_debug sb_opts.lbo_debug
|
||||
ber_socket_t sb_fd;
|
||||
ber_len_t sb_max_incoming;
|
||||
unsigned int sb_trans_needs_read:1;
|
||||
unsigned int sb_trans_needs_write:1;
|
||||
ber_len_t sb_max_incoming;
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
char sb_ungetlen;
|
||||
char sb_ungetbuf[8];
|
||||
#endif
|
||||
};
|
||||
|
||||
#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
|
||||
|
|
|
|||
|
|
@ -150,6 +150,20 @@ ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
|
|||
ret = 1;
|
||||
break;
|
||||
|
||||
case LBER_SB_OPT_UNGET_BUF:
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
|
||||
if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
|
||||
AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
|
||||
sb->sb_ungetlen );
|
||||
ret = 1;
|
||||
} else {
|
||||
sb->sb_ungetlen = 0;
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
|
||||
break;
|
||||
|
|
@ -704,6 +718,24 @@ sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
|
|||
assert( sbiod != NULL);
|
||||
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
|
||||
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
if ( sbiod->sbiod_sb->sb_ungetlen ) {
|
||||
ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
|
||||
if ( blen > len )
|
||||
blen = len;
|
||||
AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
|
||||
buf += blen;
|
||||
len -= blen;
|
||||
if ( blen < sbiod->sbiod_sb->sb_ungetlen ) {
|
||||
sbiod->sbiod_sb->sb_ungetlen -= blen;
|
||||
AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
|
||||
sbiod->sbiod_sb->sb_ungetbuf+blen,
|
||||
sbiod->sbiod_sb->sb_ungetlen );
|
||||
}
|
||||
if ( len == 0 )
|
||||
return blen;
|
||||
}
|
||||
#endif
|
||||
return read( sbiod->sbiod_sb->sb_fd, buf, len );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,12 +154,7 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s)
|
|||
}
|
||||
#undef TRACE
|
||||
|
||||
#if !defined(HAVE_GETPEEREID) && \
|
||||
!defined(HAVE_GETPEERUCRED) && \
|
||||
!defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
|
||||
defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
|
||||
defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
|
||||
#define DO_SENDMSG
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
static const char abandonPDU[] = {LDAP_TAG_MESSAGE, 6,
|
||||
LDAP_TAG_MSGID, 1, 0, LDAP_REQ_ABANDON, 1, 0};
|
||||
#endif
|
||||
|
|
@ -185,7 +180,7 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async)
|
|||
{
|
||||
if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
|
||||
|
||||
#ifdef DO_SENDMSG
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
/* Send a dummy message with access rights. Remote side will
|
||||
* obtain our uid/gid by fstat'ing this descriptor.
|
||||
*/
|
||||
|
|
@ -266,7 +261,7 @@ sendcred:
|
|||
if( fd.revents & POLL_WRITE ) {
|
||||
if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1;
|
||||
if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
|
||||
#ifdef DO_SENDMSG
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
goto sendcred;
|
||||
#else
|
||||
return ( 0 );
|
||||
|
|
@ -297,7 +292,7 @@ sendcred:
|
|||
if ( FD_ISSET(s, &wfds) ) {
|
||||
if ( ldap_pvt_is_socket_ready(ld, s) == -1 ) return -1;
|
||||
if ( ldap_pvt_ndelay_off(ld, s) == -1 ) return -1;
|
||||
#ifdef DO_SENDMSG
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
goto sendcred;
|
||||
#else
|
||||
return ( 0 );
|
||||
|
|
|
|||
|
|
@ -21,6 +21,14 @@
|
|||
#include <sys/types.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
#include <lber.h>
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/errno.h>
|
||||
|
||||
|
|
@ -35,21 +43,13 @@
|
|||
#include <sys/ucred.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_GETPEERUCRED) && \
|
||||
!defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
|
||||
defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
|
||||
defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
|
||||
#define DO_SENDMSG
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
int getpeereid( int s, uid_t *euid, gid_t *egid )
|
||||
int lutil_getpeereid( int s, uid_t *euid, gid_t *egid
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
, struct berval *peerbv
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef LDAP_PF_LOCAL
|
||||
#if defined( HAVE_GETPEERUCRED )
|
||||
|
|
@ -85,9 +85,8 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
|
|||
*egid = peercred.cr_gid;
|
||||
return 0;
|
||||
}
|
||||
#elif defined( DO_SENDMSG )
|
||||
char dummy[8];
|
||||
int err, fd[2];
|
||||
#elif defined( LDAP_PF_LOCAL_SENDMSG )
|
||||
int err, fd;
|
||||
struct iovec iov;
|
||||
struct msghdr msg = {0};
|
||||
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
|
||||
|
|
@ -108,8 +107,8 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
|
|||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
iov.iov_base = dummy;
|
||||
iov.iov_len = sizeof dummy;
|
||||
iov.iov_base = peerbv->bv_val;
|
||||
iov.iov_len = peerbv->bv_len;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
|
||||
|
|
@ -117,30 +116,34 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
|
|||
msg.msg_controllen = sizeof( control_un.control );
|
||||
|
||||
cmsg = CMSG_FIRSTHDR( &msg );
|
||||
# else
|
||||
msg.msg_accrights = (char *)&fd;
|
||||
msg.msg_accrightslen = sizeof(fd);
|
||||
# endif
|
||||
|
||||
/*
|
||||
* AIX returns a bogus file descriptor if recvmsg() is
|
||||
* called with MSG_PEEK (is this a bug?). Hence we need
|
||||
* to receive the Abandon PDU.
|
||||
*/
|
||||
if( recvmsg( s, &msg, MSG_WAITALL ) >= 0 &&
|
||||
peerbv->bv_len = recvmsg( s, &msg, MSG_WAITALL );
|
||||
if( peerbv->bv_len >= 0 &&
|
||||
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
|
||||
cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) &&
|
||||
cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS )
|
||||
cmsg->cmsg_type == SCM_RIGHTS
|
||||
# else
|
||||
msg.msg_accrights = (char *)fd;
|
||||
msg.msg_accrightslen = sizeof(fd);
|
||||
if( recvmsg( s, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen == sizeof(int) )
|
||||
msg.msg_accrightslen == sizeof(int)
|
||||
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/
|
||||
{
|
||||
) {
|
||||
/* We must receive a valid descriptor, it must be a pipe,
|
||||
* and it must only be accessible by its owner.
|
||||
*/
|
||||
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
|
||||
fd[0] = (*(int *)CMSG_DATA( cmsg ));
|
||||
fd = (*(int *)CMSG_DATA( cmsg ));
|
||||
# endif
|
||||
err = fstat( fd[0], &st );
|
||||
close(fd[0]);
|
||||
err = fstat( fd, &st );
|
||||
close(fd);
|
||||
if( err == 0 && S_ISFIFO(st.st_mode) &&
|
||||
((st.st_mode & (S_IRWXG|S_IRWXO)) == 0))
|
||||
{
|
||||
|
|
@ -148,6 +151,8 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
|
|||
*egid = st.st_gid;
|
||||
return 0;
|
||||
}
|
||||
} else if ( peer->bv_len < 0 ) {
|
||||
peer->bv_len = 0;
|
||||
}
|
||||
#elif defined(SOCKCREDSIZE)
|
||||
struct msghdr msg;
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ static void connection_return( Connection *c )
|
|||
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
|
||||
}
|
||||
|
||||
long connection_init(
|
||||
Connection * connection_init(
|
||||
ber_socket_t s,
|
||||
Listener *listener,
|
||||
const char* dnsname,
|
||||
|
|
@ -385,7 +385,7 @@ long connection_init(
|
|||
if( s == AC_SOCKET_INVALID ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert( s >= 0 );
|
||||
|
|
@ -442,7 +442,7 @@ long connection_init(
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"connection_init(%d): connection table full "
|
||||
"(%d/%d)\n", s, i, dtblsize);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -526,13 +526,14 @@ long connection_init(
|
|||
c->c_listener = listener;
|
||||
|
||||
if ( flags == CONN_IS_CLIENT ) {
|
||||
c->c_connid = 0;
|
||||
c->c_conn_state = SLAP_C_CLIENT;
|
||||
c->c_struct_state = SLAP_C_USED;
|
||||
c->c_close_reason = "?"; /* should never be needed */
|
||||
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &s );
|
||||
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
|
||||
|
||||
return 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
|
||||
|
|
@ -622,7 +623,7 @@ long connection_init(
|
|||
|
||||
backend_connection_init(c);
|
||||
|
||||
return id;
|
||||
return c;
|
||||
}
|
||||
|
||||
void connection2anonymous( Connection *c )
|
||||
|
|
@ -1187,17 +1188,15 @@ int connection_client_setup(
|
|||
int rc;
|
||||
Connection *c;
|
||||
|
||||
rc = connection_init( s, (Listener *)&dummy_list, "", "",
|
||||
c = connection_init( s, (Listener *)&dummy_list, "", "",
|
||||
CONN_IS_CLIENT, 0, NULL );
|
||||
if ( rc < 0 ) return -1;
|
||||
if ( !c ) return -1;
|
||||
|
||||
c = connection_get( s );
|
||||
c->c_clientfunc = func;
|
||||
c->c_clientarg = arg;
|
||||
|
||||
slapd_add_internal( s, 0 );
|
||||
slapd_set_read( s, 1 );
|
||||
connection_return( c );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1572,7 +1572,7 @@ slap_listener(
|
|||
|
||||
ber_socket_t s;
|
||||
socklen_t len = sizeof(from);
|
||||
long id;
|
||||
Connection *c;
|
||||
slap_ssf_t ssf = 0;
|
||||
struct berval authid = BER_BVNULL;
|
||||
#ifdef SLAPD_RLOOKUPS
|
||||
|
|
@ -1583,6 +1583,10 @@ slap_listener(
|
|||
char *peeraddr = NULL;
|
||||
#ifdef LDAP_PF_LOCAL
|
||||
char peername[MAXPATHLEN + sizeof("PATH=")];
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
char peerbuf[8];
|
||||
struct berval peerbv = BER_BVNULL;
|
||||
#endif
|
||||
#elif defined(LDAP_PF_INET6)
|
||||
char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
|
||||
#else /* ! LDAP_PF_LOCAL && ! LDAP_PF_INET6 */
|
||||
|
|
@ -1716,8 +1720,13 @@ slap_listener(
|
|||
{
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
int rc;
|
||||
|
||||
if( getpeereid( s, &uid, &gid ) == 0 ) {
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
peerbv.bv_val = peerbuf;
|
||||
peerbv.bv_len = sizeof( peerbuf );
|
||||
#endif
|
||||
if( LUTIL_GETPEEREID( s, &uid, &gid, &peerbv ) == 0 ) {
|
||||
authid.bv_val = ch_malloc(
|
||||
STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
|
||||
"cn=peercred,cn=external,cn=auth" ) + 1 );
|
||||
|
|
@ -1809,7 +1818,7 @@ slap_listener(
|
|||
#endif /* HAVE_TCPD */
|
||||
}
|
||||
|
||||
id = connection_init(s, sl,
|
||||
c = connection_init(s, sl,
|
||||
dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
|
||||
peername,
|
||||
#ifdef HAVE_TLS
|
||||
|
|
@ -1822,7 +1831,7 @@ slap_listener(
|
|||
|
||||
if( authid.bv_val ) ch_free(authid.bv_val);
|
||||
|
||||
if( id < 0 ) {
|
||||
if( !c ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"daemon: connection_init(%ld, %s, %s) failed.\n",
|
||||
(long) s, peername, sl->sl_name.bv_val );
|
||||
|
|
@ -1830,9 +1839,14 @@ slap_listener(
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LDAP_PF_LOCAL_SENDMSG
|
||||
if ( !BER_BVISEMPTY( &peerbv ))
|
||||
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_UNGET_BUF, &peerbv );
|
||||
#endif
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"conn=%ld fd=%ld ACCEPT from %s (%s)\n",
|
||||
id, (long) s, peername, sl->sl_name.bv_val,
|
||||
c->c_connid, (long) s, peername, sl->sl_name.bv_val,
|
||||
0 );
|
||||
|
||||
return 0;
|
||||
|
|
@ -2516,16 +2530,16 @@ connectionless_init( void )
|
|||
|
||||
for ( l = 0; slap_listeners[l] != NULL; l++ ) {
|
||||
Listener *lr = slap_listeners[l];
|
||||
long id;
|
||||
Connection *c;
|
||||
|
||||
if ( !lr->sl_is_udp ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
id = connection_init( lr->sl_sd, lr, "", "",
|
||||
c = connection_init( lr->sl_sd, lr, "", "",
|
||||
CONN_IS_UDP, (slap_ssf_t) 0, NULL );
|
||||
|
||||
if ( id < 0 ) {
|
||||
if ( !c ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"connectionless_init: failed on %s (%d)\n",
|
||||
lr->sl_url, lr->sl_sd, 0 );
|
||||
|
|
|
|||
|
|
@ -686,7 +686,7 @@ LDAP_SLAPD_F (void) connection_client_enable LDAP_P(( ber_socket_t s ));
|
|||
LDAP_SLAPD_F (void) connection_client_stop LDAP_P(( ber_socket_t s ));
|
||||
|
||||
|
||||
LDAP_SLAPD_F (long) connection_init LDAP_P((
|
||||
LDAP_SLAPD_F (Connection *) connection_init LDAP_P((
|
||||
ber_socket_t s,
|
||||
Listener* url,
|
||||
const char* dnsname,
|
||||
|
|
|
|||
Loading…
Reference in a new issue