]> git.sur5r.net Git - openldap/commitdiff
ITS#4893 define LDAP_PF_LOCAL_SENDMSG in <ac/socket.h> if a message must
authorHoward Chu <hyc@openldap.org>
Sun, 25 Mar 2007 04:40:22 +0000 (04:40 +0000)
committerHoward Chu <hyc@openldap.org>
Sun, 25 Mar 2007 04:40:22 +0000 (04:40 +0000)
be sent to transmit client credentials. Buffer the message data.

include/ac/socket.h
include/lber.h
libraries/liblber/lber-int.h
libraries/liblber/sockbuf.c
libraries/libldap/os-local.c
libraries/liblutil/getpeereid.c
servers/slapd/connection.c
servers/slapd/daemon.c
servers/slapd/proto-slap.h

index 0496c4d62c92e079bf101ac64e00c7d6219e01ec..3ee751e3a6071eacf6a8bdedd3788a3d1945d860 100644 (file)
@@ -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 */
index 9d05c4f5468e2b3ddc142ef698e7e26fadde3c44..4b3a8d5ecd8ac22a03e39fa9748976d0512a7a25 100644 (file)
@@ -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
index 4e73a58ebbe0f6c24323cec965398d227f1007e9..9870f3bdda976d51d45b54102bb78522c4ebb2e9 100644 (file)
@@ -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 )
index 353d526320f30b0aa45b3b859096f74af56617bf..2739b185e18f9aeb8b5b6ef6106a153495be2092 100644 (file)
@@ -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 );
 }
 
index 4e3a19e5a29c20fa0fe19f1f73195f1996890230..fa8562369a5b2430bb9ce69440365d4f8555e604 100644 (file)
@@ -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 );
index 97d87982abf19755b707a6eaedb30de47a9cf90a..08e482e16a73f042b49686864cc1b0b73e885ad2 100644 (file)
 #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>
 
 #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;
index 42f86865c6baffd44684754ef339a0e6d497231d..9c0c05e77810ad27726981bf3ae618c97d092bad 100644 (file)
@@ -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;
 }
 
index 9a3eb6b5679d73e3af4c6ca7561a6c9e95344028..2675eb84b80fa03744513c80c2b749ba4ae7a8da 100644 (file)
@@ -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 );
index 6064c3b185c59260f67281918575c0a25b71d82e..666ca13679bfe8efdabae0b73224e03e869c6882 100644 (file)
@@ -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,