Mercurial > illumos > illumos-gate
changeset 4048:7212bc4f07cc
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: "
author | chinlong |
---|---|
date | Mon, 16 Apr 2007 15:36:28 -0700 |
parents | a400e4a801fd |
children | 1799c30fb70c |
files | usr/src/lib/libsldap/common/ns_connect.c usr/src/lib/libsldap/common/ns_sasl.c usr/src/lib/nsswitch/ldap/common/getspent.c |
diffstat | 3 files changed, 220 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libsldap/common/ns_connect.c Mon Apr 16 15:36:17 2007 -0700 +++ b/usr/src/lib/libsldap/common/ns_connect.c Mon Apr 16 15:36:28 2007 -0700 @@ -55,6 +55,8 @@ 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 @@ 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 @@ 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 @@ #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 @@ ((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 @@ 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 @@ 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 "
--- a/usr/src/lib/libsldap/common/ns_sasl.c Mon Apr 16 15:36:17 2007 -0700 +++ b/usr/src/lib/libsldap/common/ns_sasl.c Mon Apr 16 15:36:28 2007 -0700 @@ -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 @@ 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 @@ 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);
--- a/usr/src/lib/nsswitch/ldap/common/getspent.c Mon Apr 16 15:36:17 2007 -0700 +++ b/usr/src/lib/nsswitch/ldap/common/getspent.c Mon Apr 16 15:36:28 2007 -0700 @@ -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 @@ 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) {