diff options
| author | Noriko Hosoi <nhosoi@redhat.com> | 2008-05-16 16:46:49 +0000 |
|---|---|---|
| committer | Noriko Hosoi <nhosoi@redhat.com> | 2008-05-16 16:46:49 +0000 |
| commit | f4cadfcc40326a6ce29cb4b2aafee568fc15bb05 (patch) | |
| tree | 6b53ba554b92ed780d769960146da2a038c99baa | |
| parent | c6f0c0228924cf4984b0de6ce3e8e965a9c2d3ce (diff) | |
| download | ds-f4cadfcc40326a6ce29cb4b2aafee568fc15bb05.tar.gz ds-f4cadfcc40326a6ce29cb4b2aafee568fc15bb05.tar.xz ds-f4cadfcc40326a6ce29cb4b2aafee568fc15bb05.zip | |
Resolves: #436390
Summary: LDAPI: support auto-bind
Description:
1) Debugged the basic code of slapd_get_socket_peer, which is used for Solaris9
and HP-UX. The recvmsg call returns an error immediately if no data is waiting
to be received since the socket is set PR_SockOpt_Nonblocking (O_NONBLOCK). To
make slapd_get_socket_peer more robust, we have to retry recvmsg if it returns
EAGAIN. But set a retry count not to hang there.
2) Introduced c_local_valid in the Connection handle to tell the autobind
code that the uid/gid pair is valid or not.
3) Stops the automagic/unconditional auto-bind (the code used to be in
daemon.c).
4) Auto-bind is effective only when the client passes the SASL/EXTERNAL request.
| -rw-r--r-- | ldap/servers/slapd/bind.c | 32 | ||||
| -rw-r--r-- | ldap/servers/slapd/daemon.c | 21 | ||||
| -rw-r--r-- | ldap/servers/slapd/getsocketpeer.c | 59 | ||||
| -rw-r--r-- | ldap/servers/slapd/slap.h | 7 |
4 files changed, 75 insertions, 44 deletions
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c index 6b8314d2..aede545c 100644 --- a/ldap/servers/slapd/bind.c +++ b/ldap/servers/slapd/bind.c @@ -259,20 +259,24 @@ do_bind( Slapi_PBlock *pb ) bind_credentials_clear( pb->pb_conn, PR_FALSE, /* do not lock conn */ PR_FALSE /* do not clear external creds. */ ); +#if defined(ENABLE_AUTOBIND) /* LDAPI might have auto bind on, binding as anon should mean bind as self in this case */ -#if defined(ENABLE_AUTOBIND) - if((0 == dn || 0 == dn[0]) && pb->pb_conn->c_unix_local) + /* You are "bound" when the SSL connection is made, + but the client still passes a BIND SASL/EXTERNAL request. + */ + if((LDAP_AUTH_SASL == method) && + (0 == strcasecmp (saslmech, LDAP_SASL_EXTERNAL)) && + (0 == dn || 0 == dn[0]) && pb->pb_conn->c_unix_local) { slapd_bind_local_user(pb->pb_conn); - - if(pb->pb_conn->c_dn) - { + if(pb->pb_conn->c_dn) + { auto_bind = 1; /* flag the bind method */ - dn = slapi_ch_strdup(pb->pb_conn->c_dn); - slapi_sdn_init_dn_passin(&sdn,dn); - } + dn = slapi_ch_strdup(pb->pb_conn->c_dn); + slapi_sdn_init_dn_passin(&sdn,dn); + } } #endif /* ENABLE_AUTOBIND */ @@ -365,11 +369,17 @@ do_bind( Slapi_PBlock *pb ) ids_sasl_check_bind(pb); goto free_and_return; } - else { - charray_free(supported); /* Avoid leaking */ - } + else { + charray_free(supported); /* Avoid leaking */ + } if (!strcasecmp (saslmech, LDAP_SASL_EXTERNAL)) { +#if defined(ENABLE_AUTOBIND) + if (1 == auto_bind) { + /* Already AUTO-BOUND */ + break; + } +#endif /* * if this is not an SSL connection, fail and return an * inappropriateAuth error. diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c index 8bdd6521..71531b51 100644 --- a/ldap/servers/slapd/daemon.c +++ b/ldap/servers/slapd/daemon.c @@ -1963,11 +1963,13 @@ slapd_identify_local_user(Connection *conn) int ret = -1; uid_t uid = 0; gid_t gid = 0; + conn->c_local_valid = 0; if(0 == slapd_get_socket_peer(conn->c_prfd, &uid, &gid)) { conn->c_local_uid = uid; conn->c_local_gid = gid; + conn->c_local_valid = 1; ret = 0; } @@ -1983,6 +1985,11 @@ slapd_bind_local_user(Connection *conn) uid_t uid = conn->c_local_uid; gid_t gid = conn->c_local_gid; + if (!conn->c_local_valid) + { + goto bail; + } + /* observe configuration for auto binding */ /* bind at all? */ if(config_get_ldapi_bind_switch()) @@ -2338,16 +2345,12 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i #if defined(ENABLE_LDAPI) #if !defined( XP_WIN32 ) - /* ldapi */ - if( local ) - { - conn->c_unix_local = 1; + /* ldapi */ + if( local ) + { + conn->c_unix_local = 1; slapd_identify_local_user(conn); - -#if defined(ENABLE_AUTOBIND) - slapd_bind_local_user(conn); -#endif /* ENABLE_AUTOBIND */ - } + } #endif #endif /* ENABLE_LDAPI */ diff --git a/ldap/servers/slapd/getsocketpeer.c b/ldap/servers/slapd/getsocketpeer.c index bf980cad..0c3b5748 100644 --- a/ldap/servers/slapd/getsocketpeer.c +++ b/ldap/servers/slapd/getsocketpeer.c @@ -70,7 +70,7 @@ int slapd_get_socket_peer(PRFileDesc *nspr_fd, uid_t *uid, gid_t *gid) } } -#elif 0 /*defined(HAVE_GETPEERUCRED)*/ /* solaris */ +#elif defined(HAVE_GETPEERUCRED) /* solaris10 */ ucred_t *creds = 0; @@ -78,15 +78,15 @@ int slapd_get_socket_peer(PRFileDesc *nspr_fd, uid_t *uid, gid_t *gid) { if(uid) { - uid = ucred_getruid(creds); + *uid = ucred_getruid(creds); if(-1 != uid) ret = 0; } if(gid) { - gid = ucred_getrgid(creds); - if(-1 == gid) + *gid = ucred_getrgid(creds); + if(-1 == *gid) ret = -1; else ret = 0; @@ -95,44 +95,61 @@ int slapd_get_socket_peer(PRFileDesc *nspr_fd, uid_t *uid, gid_t *gid) ucred_free(creds); } -#elif 0 /* defined(HAVE_GETPEEREID) */ /* osx / some BSDs */ +#elif defined(HAVE_GETPEEREID) /* osx / some BSDs */ if(0 == getpeereid(fd, &uid, &gid)) ret = 0; -#elif 0 /* hpux / some BSDs - file descriptor cooperative auth */ - - struct msghdr msg; +#else /* hpux / Solaris9 / some BSDs - file descriptor cooperative auth */ +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + struct msghdr msg; struct iovec iov; char dummy[8]; - int fd[2]; + int pass_sd[2]; + int rc = 0; + unsigned int retrycnt = 0xffffffff; /* safety net */ + int myerrno = 0; - memset(msg, 0, sizeof(msg)); + memset((void *)&msg, 0, sizeof(msg)); iov.iov_base = dummy; iov.iov_len = sizeof(dummy); msg.msg_iov = &iov; msg.msg_iovlen = 1; - msg.msg_accrights = (char*)fd; - msg.msg_accrightslen = sizeof(fd); - - if(recvmsg(fd, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen == sizeof(int)) - { + msg.msg_accrights = (caddr_t)&pass_sd; + msg.msg_accrightslen = sizeof(pass_sd); /* Initialize it with 8 bytes. + If recvmsg is successful, + 4 is supposed to be returned. */ + /* + Since PR_SockOpt_Nonblocking is set to the socket, + recvmsg returns immediately if no data is waiting to be received. + If recvmsg returns an error and EGAIN (== EWOULDBLOCK) is set to errno, + we should retry some time. + */ + while ((rc = recvmsg(fd, &msg, MSG_PEEK)) < 0 && (EAGAIN == (myerrno = errno)) && retrycnt-- >= 0) + ; + + if (rc >= 0 && msg.msg_accrightslen == sizeof(int)) + { struct stat st; - ret = fstat(fd[0], &st); - close(fd[0]); + ret = fstat(pass_sd[0], &st); if(0 == ret && S_ISFIFO(st.st_mode) && - 0 == st.st_mode & (S_IRWXG|S_IRWXO)) + 0 == (st.st_mode & (S_IRWXG|S_IRWXO))) { if(uid) - uid = st.st_uid; + *uid = st.st_uid; if(gid) - gid = st.st_gid; + *gid = st.st_gid; + } else { + ret = -1; } - } + } #endif diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index 0b3305e3..982b9be8 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -1247,9 +1247,10 @@ typedef struct conn { int c_enable_sasl_io; /* Flag to tell us to enable SASL I/O on the next read */ int c_sasl_io; /* Flag to tell us to enable SASL I/O on the next read */ int c_sasl_ssf; /* flag to tell us the SASL SSF */ - int c_unix_local; /* flag true for LDAPI */ - uid_t c_local_uid; /* uid of connecting process */ - gid_t c_local_gid; /* gid of connecting process */ + int c_unix_local; /* flag true for LDAPI */ + int c_local_valid; /* flag true if the uid/gid are valid */ + uid_t c_local_uid; /* uid of connecting process */ + gid_t c_local_gid; /* gid of connecting process */ } Connection; #define CONN_FLAG_SSL 1 /* Is this connection an SSL connection or not ? * Used to direct I/O code when SSL is handled differently |
