diff options
author | chinlong <none@none> | 2007-04-16 15:36:28 -0700 |
---|---|---|
committer | chinlong <none@none> | 2007-04-16 15:36:28 -0700 |
commit | a1e4879402b1a0a7c410577cff81f1ce31ace7af (patch) | |
tree | 28d1b9d7317cffd21f75358a3fdffa2a5268ae7d /usr | |
parent | a4070553c99750001687496365405ce3c957c521 (diff) | |
download | illumos-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.c | 210 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/ns_sasl.c | 6 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/ldap/common/getspent.c | 16 |
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, + ¶mVal, &errorp)) != NS_LDAP_SUCCESS) { + (void) __ns_ldap_freeError(&errorp); + (void) __ns_ldap_freeParam(¶mVal); + (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) { |