summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorchinlong <none@none>2007-04-16 15:36:28 -0700
committerchinlong <none@none>2007-04-16 15:36:28 -0700
commita1e4879402b1a0a7c410577cff81f1ce31ace7af (patch)
tree28d1b9d7317cffd21f75358a3fdffa2a5268ae7d /usr
parenta4070553c99750001687496365405ce3c957c521 (diff)
downloadillumos-gate-a1e4879402b1a0a7c410577cff81f1ce31ace7af.tar.gz
6496719 connections should fall back to primary server after it comes back
6526896 Native LDAP authentication broken on snv_58 6543897 nscd deadlock after timeshift, not working failover 6545671 Some syslog messages in ns_sasl.c need prefix "libsldap: "
Diffstat (limited to 'usr')
-rw-r--r--usr/src/lib/libsldap/common/ns_connect.c210
-rw-r--r--usr/src/lib/libsldap/common/ns_sasl.c6
-rw-r--r--usr/src/lib/nsswitch/ldap/common/getspent.c16
3 files changed, 220 insertions, 12 deletions
diff --git a/usr/src/lib/libsldap/common/ns_connect.c b/usr/src/lib/libsldap/common/ns_connect.c
index 0c221d6215..b2f3fda6f1 100644
--- a/usr/src/lib/libsldap/common/ns_connect.c
+++ b/usr/src/lib/libsldap/common/ns_connect.c
@@ -55,6 +55,8 @@ extern int ldapssl_install_gethostbyaddr(LDAP *ld, const char *skip);
static int openConnection(LDAP **, const char *, const ns_cred_t *,
int, ns_ldap_error_t **, int, int);
+static void
+_DropConnection(ConnectionID cID, int flag, int fini);
/*
* sessionLock, wait4session, sessionTid
* are variables to synchronize the creation/retrieval of a connection.
@@ -859,9 +861,13 @@ findConnection(int flags, const char *serverAddr,
const ns_cred_t *auth, Connection **conp)
{
Connection *cp;
- int i;
+ int i, j, conn_server_index, up_server_index, drop_conn;
int rc;
int try;
+ ns_server_info_t sinfo;
+ ns_ldap_error_t *errorp = NULL;
+ char **servers, *addrType;
+ void **paramVal = NULL;
#ifdef DEBUG
thread_t t = thr_self();
#endif /* DEBUG */
@@ -882,7 +888,7 @@ findConnection(int flags, const char *serverAddr,
t, serverAddr);
else
(void) fprintf(stderr, "tid= %d: serverAddr=NULL\n", t);
- printCred(stderr, auth);
+ printCred(LOG_DEBUG, auth);
fflush(stderr);
#endif /* DEBUG */
@@ -954,7 +960,7 @@ findConnection(int flags, const char *serverAddr,
#ifdef DEBUG
(void) fprintf(stderr, "tid= %d: checking connection "
"[%d] ....\n", t, i);
- printConnection(stderr, cp);
+ printConnection(LOG_DEBUG, cp);
#endif /* DEBUG */
if ((cp->usedBit) || (cp->notAvail) ||
(cp->auth->auth.type != auth->auth.type) ||
@@ -975,6 +981,198 @@ findConnection(int flags, const char *serverAddr,
((strcmp(cp->auth->cred.unix_cred.passwd,
auth->cred.unix_cred.passwd) != 0))))
continue;
+ if (!(serverAddr && *serverAddr)) {
+ /*
+ * Get preferred server list.
+ * When preferred servers are merged with default
+ * servers (S_LDAP_SERVER_P) by __s_api_getServer,
+ * preferred servers are copied sequencially.
+ * The order should be the same as the order retrieved
+ * by __ns_ldap_getParam.
+ */
+ if ((rc = __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P,
+ &paramVal, &errorp)) != NS_LDAP_SUCCESS) {
+ (void) __ns_ldap_freeError(&errorp);
+ (void) __ns_ldap_freeParam(&paramVal);
+ (void) rw_unlock(&sessionPoolLock);
+ return (-1);
+ }
+ servers = (char **)paramVal;
+ /*
+ * Do fallback only if preferred servers are defined.
+ */
+ if (servers != NULL) {
+ if (cp->auth->auth.saslmech ==
+ NS_LDAP_SASL_GSSAPI)
+ addrType = NS_CACHE_ADDR_HOSTNAME;
+ else
+ addrType = NS_CACHE_ADDR_IP;
+ /*
+ * Find the 1st available server
+ */
+ rc = __s_api_requestServer(NS_CACHE_NEW, NULL,
+ &sinfo, &errorp, addrType);
+ if (rc != NS_LDAP_SUCCESS) {
+ /*
+ * Drop the connection.
+ * Pass 1 to fini so it won't be locked
+ * inside _DropConnection
+ */
+ _DropConnection(
+ cp->connectionId,
+ NS_LDAP_NEW_CONN, 1);
+ (void) rw_unlock(
+ &sessionPoolLock);
+ (void) __ns_ldap_freeParam(
+ (void ***)&servers);
+ return (-1);
+ }
+
+ if (sinfo.server) {
+ /*
+ * Test if cp->serverAddr is a
+ * preferred server.
+ */
+ conn_server_index = -1;
+ for (j = 0; servers[j] != NULL; j++) {
+ if (strcasecmp(servers[j],
+ cp->serverAddr) == 0) {
+ conn_server_index = j;
+ break;
+ }
+ }
+ /*
+ * Test if sinfo.server is a preferred
+ * server.
+ */
+ up_server_index = -1;
+ for (j = 0; servers[j] != NULL; j++) {
+ if (strcasecmp(sinfo.server,
+ servers[j]) == 0) {
+ up_server_index = j;
+ break;
+ }
+ }
+
+ /*
+ * The following code is to fall back
+ * to preferred servers if servers
+ * are previously down but are up now.
+ * If cp->serverAddr is a preferred
+ * server, it falls back to the servers
+ * ahead of it. If cp->serverAddr is
+ * not a preferred server, it falls
+ * back to any of preferred servers
+ * returned by ldap_cachemgr.
+ */
+ if (conn_server_index >= 0 &&
+ up_server_index >= 0) {
+ /*
+ * cp->serverAddr and
+ * sinfo.server are preferred
+ * servers.
+ */
+ if (up_server_index ==
+ conn_server_index)
+ /*
+ * sinfo.server is the
+ * same as
+ * cp->serverAddr.
+ * Keep the connection.
+ */
+ drop_conn = 0;
+ else
+ /*
+ * 1.
+ * up_server_index <
+ * conn_server_index
+ *
+ * sinfo is ahead of
+ * cp->serverAddr in
+ * Need to fall back.
+ * 2.
+ * up_server_index >
+ * conn_server_index
+ * cp->serverAddr is
+ * down. Drop it.
+ */
+ drop_conn = 1;
+ } else if (conn_server_index >= 0 &&
+ up_server_index == -1) {
+ /*
+ * cp->serverAddr is a preferred
+ * server but sinfo.server is
+ * not. Preferred servers are
+ * ahead of default servers.
+ * This means cp->serverAddr is
+ * down. Drop it.
+ */
+ drop_conn = 1;
+ } else if (conn_server_index == -1 &&
+ up_server_index >= 0) {
+ /*
+ * cp->serverAddr is not a
+ * preferred server but
+ * sinfo.server is.
+ * Fall back.
+ */
+ drop_conn = 1;
+ } else {
+ /*
+ * Both index are -1
+ * cp->serverAddr and
+ * sinfo.server are not
+ * preferred servers.
+ * No fallback.
+ */
+ drop_conn = 0;
+ }
+ if (drop_conn) {
+ /*
+ * Drop the connection so the
+ * new conection can fall back
+ * to a new server later.
+ * Pass 1 to fini so it won't
+ * be locked inside
+ * _DropConnection
+ */
+ _DropConnection(
+ cp->connectionId,
+ NS_LDAP_NEW_CONN, 1);
+ (void) rw_unlock(
+ &sessionPoolLock);
+ (void) __ns_ldap_freeParam(
+ (void ***)&servers);
+ free(sinfo.server);
+ __s_api_free2dArray(
+ sinfo.saslMechanisms);
+ __s_api_free2dArray(
+ sinfo.controls);
+ return (-1);
+ } else {
+ /*
+ * Keep the connection
+ */
+ (void) __ns_ldap_freeParam(
+ (void ***)&servers);
+ free(sinfo.server);
+ __s_api_free2dArray(
+ sinfo.saslMechanisms);
+ __s_api_free2dArray(
+ sinfo.controls);
+ }
+ } else {
+ (void) rw_unlock(&sessionPoolLock);
+ syslog(LOG_WARNING, "libsldap: Null "
+ "sinfo.server from "
+ "__s_api_requestServer");
+ (void) __ns_ldap_freeParam(
+ (void ***)&servers);
+ return (-1);
+ }
+ }
+ }
+
/* found an available connection */
if (MTperConn == 0)
cp->usedBit = B_TRUE;
@@ -1132,7 +1330,8 @@ makeConnection(Connection **conp, const char *serverAddr,
sinfo.controls = NULL;
sinfo.saslMechanisms = NULL;
- if ((id = findConnection(flags, serverAddr, auth, &con)) != -1) {
+ if ((wait4session == 0 || sessionTid != thr_self()) &&
+ (id = findConnection(flags, serverAddr, auth, &con)) != -1) {
/* connection found in cache */
#ifdef DEBUG
(void) fprintf(stderr, "tid= %d: connection found in "
@@ -1417,8 +1616,7 @@ _DropConnection(ConnectionID cID, int flag, int fini)
cp = sessionPool[id];
/* sanity check before removing */
- if (!cp || (!fini && !cp->shared && (!cp->usedBit ||
- cp->threadID != thr_self()))) {
+ if (!cp || (!fini && !cp->shared && !cp->usedBit)) {
#ifdef DEBUG
if (cp == NULL)
(void) fprintf(stderr, "tid= %d: no "
diff --git a/usr/src/lib/libsldap/common/ns_sasl.c b/usr/src/lib/libsldap/common/ns_sasl.c
index 934efb148c..2aa5f0c9f9 100644
--- a/usr/src/lib/libsldap/common/ns_sasl.c
+++ b/usr/src/lib/libsldap/common/ns_sasl.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -456,7 +456,7 @@ __ns_ldap_check_dns_preq(int foreground,
CLIENT_FPRINTF(stdout, "start: %s\n",
gettext("DNS client is enabled"));
} else {
- syslog(LOG_INFO, "%s",
+ syslog(LOG_INFO, "libsldap: %s",
gettext("DNS client is enabled"));
}
return (NS_LDAP_SUCCESS);
@@ -530,7 +530,7 @@ __ns_ldap_check_gssapi_preq(int foreground,
CLIENT_FPRINTF(stdout, "start: %s\n",
gettext("sasl/GSSAPI bind works"));
} else {
- syslog(LOG_INFO, "%s",
+ syslog(LOG_INFO, "libsldap: %s",
gettext("sasl/GSSAPI bind works"));
}
return (NS_LDAP_SUCCESS);
diff --git a/usr/src/lib/nsswitch/ldap/common/getspent.c b/usr/src/lib/nsswitch/ldap/common/getspent.c
index dc93c5d9ca..707bf6ff44 100644
--- a/usr/src/lib/nsswitch/ldap/common/getspent.c
+++ b/usr/src/lib/nsswitch/ldap/common/getspent.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -82,8 +82,18 @@ _nss_ldap_shadow2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
len += strlen(uid[0]);
passwd = __ns_ldap_getAttr(result->entry, _S_USERPASSWORD);
- if (passwd == NULL || passwd[0] == NULL || strlen(passwd[0]) < 1) {
- pw_passwd = _NO_VALUE;
+ if (passwd == NULL || passwd[0] == NULL) {
+ /*
+ * ACL does not allow userpassword to return or
+ * userpassword is not defined
+ */
+ pw_passwd = np;
+ } else if (strcmp(passwd[0], "") == 0) {
+ /*
+ * An empty password is not supported
+ */
+ nss_result = NSS_STR_PARSE_PARSE;
+ goto result_spd2str;
} else {
if ((tmp = strstr(passwd[0], "{crypt}")) != NULL ||
(tmp = strstr(passwd[0], "{CRYPT}")) != NULL) {