Author: nhosoi
Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv20423
Modified Files:
slap.h getsocketpeer.c daemon.c bind.c
Log Message:
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.
Index: slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slap.h,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- slap.h 3 Apr 2008 16:52:46 -0000 1.31
+++ slap.h 16 May 2008 16:46:49 -0000 1.32
@@ -1247,9 +1247,10 @@
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
Index: getsocketpeer.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/getsocketpeer.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- getsocketpeer.c 27 Feb 2007 20:16:08 -0000 1.3
+++ getsocketpeer.c 16 May 2008 16:46:49 -0000 1.4
@@ -70,7 +70,7 @@
}
}
-#elif 0 /*defined(HAVE_GETPEERUCRED)*/ /* solaris */
+#elif defined(HAVE_GETPEERUCRED) /* solaris10 */
ucred_t *creds = 0;
@@ -78,15 +78,15 @@
{
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 @@
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);
+ 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(recvmsg(fd, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen ==
sizeof(int))
- {
+ 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
Index: daemon.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/daemon.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- daemon.c 14 Nov 2007 20:18:53 -0000 1.18
+++ daemon.c 16 May 2008 16:46:49 -0000 1.19
@@ -1963,11 +1963,13 @@
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 @@
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 @@
#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 */
Index: bind.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/bind.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- bind.c 18 Oct 2007 00:08:34 -0000 1.11
+++ bind.c 16 May 2008 16:46:49 -0000 1.12
@@ -259,20 +259,24 @@
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 @@
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.