summaryrefslogtreecommitdiff
path: root/nslcd
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2007-01-17 12:51:12 +0000
committerArthur de Jong <arthur@arthurdejong.org>2007-01-17 12:51:12 +0000
commitd6401710c0fd59a2ea500133944ee465cb65cacf (patch)
tree038ef66ced14b96f3c2f830d2c455d102598c95c /nslcd
parenta5b80c9e6e46a7fa24adab9846e7cf3f26f9077f (diff)
get rid of more code that would check if the socket was changed from under us by our caller
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-ldapd@219 ef36b2f9-881f-0410-afb5-c4e39611909c
Diffstat (limited to 'nslcd')
-rw-r--r--nslcd/ldap-nss.c306
-rw-r--r--nslcd/ldap-nss.h7
2 files changed, 5 insertions, 308 deletions
diff --git a/nslcd/ldap-nss.c b/nslcd/ldap-nss.c
index ecba382..2413546 100644
--- a/nslcd/ldap-nss.c
+++ b/nslcd/ldap-nss.c
@@ -4,8 +4,8 @@
forked into the nss-ldapd library.
Copyright (C) 1997-2006 Luke Howard
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006 Arthur de Jong
+ Copyright (C) 2006, 2007 West Consulting
+ Copyright (C) 2006, 2007 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -148,11 +148,6 @@ static int __ssl_initialized = 0;
static void do_close (void);
/*
- * Close the global session without sending an unbind.
- */
-static void do_close_no_unbind (void);
-
-/*
* Disable keepalive on a LDAP connection's socket.
*/
static void do_set_sockopts (void);
@@ -630,22 +625,6 @@ do_set_sockopts (void)
(void) setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, (void *) &off,
sizeof (off));
(void) fcntl (sd, F_SETFD, FD_CLOEXEC);
- /*
- * NSS modules shouldn't open file descriptors that the program/utility
- * linked against NSS doesn't know about. The LDAP library opens a
- * connection to the LDAP server transparently. There's an edge case
- * where a daemon might fork a child and, being written well, closes
- * all its file descriptors. This will close the socket descriptor
- * being used by the LDAP library! Worse, the daemon might open many
- * files and sockets, eventually opening a descriptor with the same number
- * as that originally used by the LDAP library. The only way to know that
- * this isn't "our" socket descriptor is to save the local and remote
- * sockaddr_in structures for later comparison.
- */
- (void) getsockname (sd, (struct sockaddr *) &__session.ls_sockname,
- &socknamelen);
- (void) getpeername (sd, (struct sockaddr *) &__session.ls_peername,
- &peernamelen);
}
log_log(LOG_DEBUG,"<== do_set_sockopts");
#endif /* HAVE_LDAPSSL_CLIENT_INIT */
@@ -688,277 +667,6 @@ do_close (void)
log_log(LOG_DEBUG,"<== do_close");
}
-static int
-do_sockaddr_isequal (struct sockaddr_storage *_s1,
- socklen_t _slen1,
- struct sockaddr_storage *_s2,
- socklen_t _slen2)
-{
- int ret;
-
- if (_s1->ss_family != _s2->ss_family)
- return 0;
-
- if (_slen1 != _slen2)
- return 0;
-
- ret = 0;
-
- switch (_s1->ss_family)
- {
- case AF_INET:
- {
- struct sockaddr_in *s1 = (struct sockaddr_in *) _s1;
- struct sockaddr_in *s2 = (struct sockaddr_in *) _s2;
-
- ret = (s1->sin_port == s2->sin_port &&
- memcmp (&s1->sin_addr, &s2->sin_addr, sizeof(struct in_addr)) == 0);
- break;
- }
- case AF_UNIX:
- {
- struct sockaddr_un *s1 = (struct sockaddr_un *) _s1;
- struct sockaddr_un *s2 = (struct sockaddr_un *) _s2;
-
- ret = (memcmp (s1->sun_path, s2->sun_path,
- _slen1 - sizeof (_s1->ss_family)) == 0);
- break;
- }
-#ifdef INET6
- case AF_INET6:
- {
- struct sockaddr_in6 *s1 = (struct sockaddr_in6 *) _s1;
- struct sockaddr_in6 *s2 = (struct sockaddr_in6 *) _s2;
-
- ret = (s1->sin6_port == s2->sin6_port &&
- memcmp (&s1->sin6_addr, &s2->sin6_addr, sizeof(struct in6_addr)) == 0 &&
- s1->sin6_scope_id == s2->sin6_scope_id);
- break;
- }
-#endif
- default:
- ret = (memcmp (_s1, _s2, _slen1) == 0);
- break;
- }
-
- return ret;
-}
-
-static int
-do_get_our_socket(int *sd)
-{
- /*
- * Before freeing the LDAP context or closing the socket descriptor,
- * we must ensure that it is *our* socket descriptor. See the much
- * lengthier description of this at the end of do_open () where the
- * values __session.ls_sockname and __session.ls_peername are saved.
- * With HAVE_LDAPSSL_CLIENT_INIT this returns 0 if the socket has
- * been closed or reopened, and sets *sd to the ldap socket
- * descriptor.. Returns 1 in all other cases.
- */
-
- int isOurSocket = 1;
-
-#ifndef HAVE_LDAPSSL_CLIENT_INIT
- if (ldap_get_option (__session.ls_conn, LDAP_OPT_DESC, sd) == 0)
- {
- struct sockaddr_storage sockname;
- struct sockaddr_storage peername;
- socklen_t socknamelen = sizeof (sockname);
- socklen_t peernamelen = sizeof (peername);
-
- if (getsockname (*sd, (struct sockaddr *) &sockname, &socknamelen) != 0 ||
- getpeername (*sd, (struct sockaddr *) &peername, &peernamelen) != 0)
- {
- isOurSocket = 0;
- }
- else
- {
- isOurSocket = do_sockaddr_isequal (&__session.ls_sockname,
- socknamelen,
- &sockname,
- socknamelen);
- if (isOurSocket)
- {
- isOurSocket = do_sockaddr_isequal (&__session.ls_peername,
- peernamelen,
- &peername,
- peernamelen);
- }
- }
- }
-#endif /* HAVE_LDAPSSL_CLIENT_INIT */
- return isOurSocket;
-}
-
-static int
-do_dupfd(int oldfd, int newfd)
-{
- int d = -1;
- int flags;
-
- flags = fcntl(oldfd, F_GETFD);
-
- while (1)
- {
- d = (newfd > -1) ? dup2 (oldfd, newfd) : dup (oldfd);
- if (d > -1)
- break;
-
- if (errno == EBADF)
- return -1; /* not open */
-
- if (errno != EINTR
-#ifdef EBUSY
- && errno != EBUSY
-#endif
- )
- return -1;
- }
-
- /* duplicate close-on-exec flag */
- (void) fcntl (d, F_SETFD, flags);
-
- return d;
-}
-
-static int
-do_closefd(int fd)
-{
- int rc;
-
- while ((rc = close(fd)) < 0 && errno == EINTR)
- ;
-
- return rc;
-}
-
-static void
-do_drop_connection(int sd, int closeSd)
-{
- /* Close the LDAP connection without writing anything to the
- underlying socket. The socket will be left open afterwards if
- closeSd is 0 */
-#ifndef HAVE_LDAPSSL_CLIENT_INIT
- {
- int dummyfd = -1, savedfd = -1;
- /* Under OpenLDAP 2.x, ldap_set_option (..., LDAP_OPT_DESC, ...) is
- a no-op, so to shut down the LDAP connection without writing
- anything to the socket, we swap a dummy socket onto that file
- descriptor, and then swap the real fd back once the shutdown is
- done. */
- savedfd = do_dupfd (sd, -1);
- dummyfd = socket (AF_INET, SOCK_STREAM, 0);
- if (dummyfd > -1 && dummyfd != sd)
- {
- do_closefd (sd);
- do_dupfd (dummyfd, sd);
- do_closefd (dummyfd);
- }
-
-#ifdef HAVE_LDAP_LD_FREE
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
- (void) ldap_ld_free (__session.ls_conn, 0, NULL, NULL);
-#else
- (void) ldap_ld_free (__session.ls_conn, 0);
-#endif /* OPENLDAP 2.x */
-#else
- ldap_unbind (__session.ls_conn);
-#endif /* HAVE_LDAP_LD_FREE */
-
- /* Do we want our original sd back? */
- do_closefd (sd);
- if (savedfd > -1)
- {
- if (closeSd == 0)
- do_dupfd (savedfd, sd);
- do_closefd (savedfd);
- }
- }
-#else /* No sd available */
- {
- int bogusSd = -1;
- if (closeSd == 0)
- {
- sd = -1; /* don't want to really close the socket */
-#ifdef HAVE_LDAP_LD_FREE
-#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_DESC)
- (void) ldap_set_option (__session.ls_conn, LDAP_OPT_DESC, &sd);
-#else
- __session.ls_conn->ld_sb.sb_sd = -1;
-#endif /* LDAP_OPT_DESC */
-#endif /* HAVE_LDAP_LD_FREE */
- }
-
-#ifdef HAVE_LDAP_LD_FREE
-
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
- (void) ldap_ld_free (__session.ls_conn, 0, NULL, NULL);
-#else
- (void) ldap_ld_free (__session.ls_conn, 0);
-#endif /* OPENLDAP 2.x */
-
-#else
-
-#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_DESC)
- (void) ldap_set_option (__session.ls_conn, LDAP_OPT_DESC, &bogusSd);
-#else
- __session.ls_conn->ld_sb.sb_sd = bogusSd;
-#endif /* LDAP_OPT_DESC */
-
- /* hope we closed it OK! */
- ldap_unbind (__session.ls_conn);
-
-#endif /* HAVE_LDAP_LD_FREE */
-
- }
-#endif /* HAVE_LDAPSSL_CLIENT_INIT */
- __session.ls_conn = NULL;
- __session.ls_state = LS_UNINITIALIZED;
-
- return;
-}
-
-/*
- * If we've forked, then we need to open a new session.
- * Careful: we have the socket shared with our parent,
- * so we don't want to send an unbind to the server.
- * However, we want to close the descriptor to avoid
- * leaking it, and we also want to release the memory
- * used by __session.ls_conn. The only entry point
- * we have is ldap_unbind() which does both of these
- * things, so we use an internal API, at the expense
- * of compatibility.
- */
-static void
-do_close_no_unbind (void)
-{
- int sd = -1;
- int closeSd = 1;
-
- log_log(LOG_DEBUG,"==> do_close_no_unbind");
-
- if (__session.ls_state == LS_UNINITIALIZED)
- {
- assert (__session.ls_conn == NULL);
- log_log(LOG_DEBUG,"<== do_close_no_unbind (connection was not open)");
- return;
- }
-
- closeSd = do_get_our_socket (&sd);
-
-#if defined(DEBUG) || defined(DEBUG_SOCKETS)
- syslog (LOG_AUTHPRIV | LOG_INFO, "nss_ldap: %sclosing connection (no unbind) %p fd %d",
- closeSd ? "" : "not ", (void *)__session.ls_conn, sd);
-#endif /* DEBUG */
-
- do_drop_connection(sd, closeSd);
-
- log_log(LOG_DEBUG,"<== do_close_no_unbind");
-
- return;
-}
-
static enum nss_status
do_init_session (LDAP ** ld, const char *uri, int defport)
{
@@ -1034,7 +742,6 @@ do_init (void)
{
struct ldap_config *cfg;
enum nss_status stat;
- int sd=-1;
log_log(LOG_DEBUG,"==> do_init");
@@ -1045,14 +752,7 @@ do_init (void)
__session.ls_current_uri = 0;
}
- if (__session.ls_state == LS_CONNECTED_TO_DSA &&
- do_get_our_socket (&sd) == 0)
- {
- /* The calling app has stolen our socket. */
- log_log(LOG_DEBUG,":== do_init (stolen socket detected)");
- do_drop_connection (sd, 0);
- }
- else if (__session.ls_state == LS_CONNECTED_TO_DSA)
+ if (__session.ls_state == LS_CONNECTED_TO_DSA)
{
time_t current_time;
diff --git a/nslcd/ldap-nss.h b/nslcd/ldap-nss.h
index e4d4eb1..8322a73 100644
--- a/nslcd/ldap-nss.h
+++ b/nslcd/ldap-nss.h
@@ -4,8 +4,8 @@
forked into the nss-ldapd library.
Copyright (C) 1997-2005 Luke Howard
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006 Arthur de Jong
+ Copyright (C) 2006, 2007 West Consulting
+ Copyright (C) 2006, 2007 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -269,9 +269,6 @@ struct ldap_session
time_t ls_timestamp;
/* has session been connected? */
enum ldap_session_state ls_state;
- /* keep track of the LDAP sockets */
- struct sockaddr_storage ls_sockname;
- struct sockaddr_storage ls_peername;
/* index into ldc_uris: currently connected DSA */
int ls_current_uri;
};