summaryrefslogtreecommitdiff
path: root/nslcd/myldap.c
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2014-10-04 16:13:03 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2014-10-04 16:13:03 -0400
commitc9618dfe442305531ee6cab9660333f4a697e094 (patch)
tree63da3cf1c107fdebd82987519b858f0d98c12d23 /nslcd/myldap.c
parentbe4588009b7106859e1beae6038aaea8d7f85825 (diff)
foo
Diffstat (limited to 'nslcd/myldap.c')
-rw-r--r--nslcd/myldap.c432
1 files changed, 6 insertions, 426 deletions
diff --git a/nslcd/myldap.c b/nslcd/myldap.c
index cf16dd6..095e8e6 100644
--- a/nslcd/myldap.c
+++ b/nslcd/myldap.c
@@ -1226,440 +1226,20 @@ void myldap_session_close(MYLDAP_SESSION *session)
free(session);
}
-/* mutex for updating the times in the uri */
-pthread_mutex_t uris_mutex = PTHREAD_MUTEX_INITIALIZER;
-static int do_retry_search(MYLDAP_SEARCH *search)
-{
- int sleeptime = 0;
- int start_uri;
- time_t endtime;
- time_t nexttry;
- time_t t;
- int rc = LDAP_UNAVAILABLE;
- struct myldap_uri *current_uri;
- int dotry[NSS_LDAP_CONFIG_MAX_URIS];
- int do_invalidate = 0;
- /* clear time stamps */
- for (start_uri = 0; start_uri < NSS_LDAP_CONFIG_MAX_URIS; start_uri++)
- dotry[start_uri] = 1;
- /* keep trying until we time out */
- endtime = time(NULL) + nslcd_cfg->reconnect_retrytime;
- while (1)
- {
- nexttry = endtime;
- /* try each configured URL once */
- pthread_mutex_lock(&uris_mutex);
- start_uri = search->session->current_uri;
- do
- {
- current_uri = &(nslcd_cfg->uris[search->session->current_uri]);
- /* only try this URI if we should */
- if (!dotry[search->session->current_uri])
- { /* skip this URI */ }
- else if ((current_uri->lastfail > (current_uri->firstfail + nslcd_cfg->reconnect_retrytime)) &&
- ((t = time(NULL)) < (current_uri->lastfail + nslcd_cfg->reconnect_retrytime)))
- {
- /* we are in a hard fail state and have retried not long ago */
- log_log(LOG_DEBUG, "not retrying server %s which failed just %d second(s) ago and has been failing for %d seconds",
- current_uri->uri, (int)(t - current_uri->lastfail),
- (int)(t - current_uri->firstfail));
- dotry[search->session->current_uri] = 0;
- }
- else
- {
- /* try to start the search */
- pthread_mutex_unlock(&uris_mutex);
- rc = do_try_search(search);
- if (rc == LDAP_SUCCESS)
- {
- pthread_mutex_lock(&uris_mutex);
- /* check if we are coming back from an error */
- if ((current_uri->lastfail > 0) || (search->session->current_uri != start_uri))
- {
- log_log(LOG_INFO, "connected to LDAP server %s", current_uri->uri);
- do_invalidate = 1;
- }
- if (first_search)
- {
- do_invalidate = 1;
- first_search = 0;
- }
- /* update ok time */
- current_uri->firstfail = 0;
- current_uri->lastfail = 0;
- pthread_mutex_unlock(&uris_mutex);
- /* flag the search as valid */
- search->valid = 1;
- /* signal external invalidation of configured caches */
- if (do_invalidate)
- invalidator_do(LM_NONE);
- return LDAP_SUCCESS;
- }
- /* close the current connection */
- do_close(search->session);
- /* update time of failure and figure out when we should retry */
- pthread_mutex_lock(&uris_mutex);
- t = time(NULL);
- /* update timestaps unless we are doing an authentication search */
- if (search->session->binddn[0] == '\0')
- {
- if (current_uri->firstfail == 0)
- current_uri->firstfail = t;
- current_uri->lastfail = t;
- }
- /* if it is one of these, retrying this URI is not going to help */
- if ((rc == LDAP_INVALID_CREDENTIALS) || (rc == LDAP_INSUFFICIENT_ACCESS) ||
- (rc == LDAP_AUTH_METHOD_NOT_SUPPORTED))
- dotry[search->session->current_uri] = 0;
- /* check when we should try this URI again */
- else if (t <= (current_uri->firstfail + nslcd_cfg->reconnect_retrytime))
- {
- t += nslcd_cfg->reconnect_sleeptime;
- if (t < nexttry)
- nexttry = t;
- }
- }
- /* try the next URI (with wrap-around) */
- search->session->current_uri++;
- if (nslcd_cfg->uris[search->session->current_uri].uri == NULL)
- search->session->current_uri = 0;
- }
- while (search->session->current_uri != start_uri);
- pthread_mutex_unlock(&uris_mutex);
- /* see if it is any use sleeping */
- if (nexttry >= endtime)
- {
- if (search->session->binddn[0] == '\0')
- myldap_err(LOG_ERR, search->session->ld, rc, "no available LDAP server found");
- return rc;
- }
- /* sleep between tries */
- sleeptime = nexttry - time(NULL);
- if (sleeptime > 0)
- {
- log_log(LOG_WARNING, "no available LDAP server found, sleeping %d seconds",
- sleeptime);
- (void)sleep(sleeptime);
- }
- }
-}
-
-/* force quick retries of all failing LDAP servers */
-void myldap_immediate_reconnect(void)
-{
- int i;
- time_t t;
- t = time(NULL) - nslcd_cfg->reconnect_retrytime;
- pthread_mutex_lock(&uris_mutex);
- for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++)
- {
- /* only adjust failing connections that are in a hard fail state */
- if ((nslcd_cfg->uris[i].lastfail > t) &&
- (nslcd_cfg->uris[i].lastfail > (nslcd_cfg->uris[i].firstfail + nslcd_cfg->reconnect_retrytime)))
- {
- /* move lastfail back to ensure quick retry */
- log_log(LOG_DEBUG, "moving lastfail of %s %d second(s) back to force retry",
- nslcd_cfg->uris[i].uri, (int)(nslcd_cfg->uris[i].lastfail - t));
- nslcd_cfg->uris[i].lastfail = t;
- }
- }
- pthread_mutex_unlock(&uris_mutex);
-}
-
-MYLDAP_SEARCH *myldap_search(MYLDAP_SESSION *session,
- const char *base, int scope, const char *filter,
- const char **attrs, int *rcp)
+void myldap_search_close(MYLDAP_SEARCH *search)
{
- MYLDAP_SEARCH *search;
- int i;
- int rc;
- /* check parameters */
- if ((session == NULL) || (base == NULL) || (filter == NULL) || (attrs == NULL))
- {
- log_log(LOG_ERR, "myldap_search(): invalid parameter passed");
- errno = EINVAL;
- if (rcp != NULL)
- *rcp = LDAP_OPERATIONS_ERROR;
- return NULL;
- }
- /* log the call */
- log_log(LOG_DEBUG, "myldap_search(base=\"%s\", filter=\"%s\")",
- base, filter);
- /* check if the idle time for the connection has expired */
- myldap_session_check(session);
- /* allocate a new search entry */
- search = myldap_search_new(session, base, scope, filter, attrs);
- /* find a place in the session where we can register our search */
- for (i = 0; (session->searches[i] != NULL) && (i < MAX_SEARCHES_IN_SESSION); i++)
- /* nothing */ ;
- if (i >= MAX_SEARCHES_IN_SESSION)
- {
- log_log(LOG_ERR, "myldap_search(): too many searches registered with session (max %d)",
- MAX_SEARCHES_IN_SESSION);
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = LDAP_OPERATIONS_ERROR;
- return NULL;
- }
- /* register search with the session so we can free it later on */
- session->searches[i] = search;
- /* do the search with retries to all configured servers */
- rc = do_retry_search(search);
- if (rc != LDAP_SUCCESS)
- {
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = rc;
- return NULL;
- }
- if (rcp != NULL)
- *rcp = LDAP_SUCCESS;
- return search;
+ search->close(search);
}
-void myldap_search_close(MYLDAP_SEARCH *search)
-{
- int i;
- if (search == NULL)
- return;
- /* free any messages */
- if (search->msg != NULL)
- {
- ldap_msgfree(search->msg);
- search->msg = NULL;
- }
- /* abandon the search if there were more results to fetch */
- if ((search->session->ld != NULL) && (search->msgid != -1))
- {
- ldap_abandon(search->session->ld, search->msgid);
- search->msgid = -1;
- }
- /* find the reference to this search in the session */
- for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
- {
- if (search->session->searches[i] == search)
- search->session->searches[i] = NULL;
- }
- /* free any search entries */
- if (search->entry != NULL)
- myldap_entry_free(search->entry);
- /* clean up cookie */
- if (search->cookie != NULL)
- ber_bvfree(search->cookie);
- /* free read messages */
- if (search->msg != NULL)
- ldap_msgfree(search->msg);
- /* free the storage we allocated */
- free(search);
+struct myldap_search {
+ MYLDAP_ENTRY *(*get_entry)(void *data, int *rcp);
+ void *data;
}
MYLDAP_ENTRY *myldap_get_entry(MYLDAP_SEARCH *search, int *rcp)
{
- int rc;
- int parserc;
- struct timeval tv, *tvp;
- LDAPControl **resultcontrols;
- ber_int_t count;
- /* check parameters */
- if ((search == NULL) || (search->session == NULL) || (search->session->ld == NULL))
- {
- log_log(LOG_ERR, "myldap_get_entry(): invalid search passed");
- errno = EINVAL;
- if (rcp != NULL)
- *rcp = LDAP_OPERATIONS_ERROR;
- return NULL;
- }
- /* check if the connection wasn't closed in another search */
- if (!search->valid)
- {
- log_log(LOG_WARNING, "myldap_get_entry(): connection was closed");
- /* retry the search */
- if (search->may_retry_search)
- {
- log_log(LOG_DEBUG, "myldap_get_entry(): retry search");
- search->may_retry_search = 0;
- if (do_retry_search(search) == LDAP_SUCCESS)
- return myldap_get_entry(search, rcp);
- }
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = LDAP_SERVER_DOWN;
- return NULL;
- }
- /* set up a timelimit value for operations */
- if (nslcd_cfg->timelimit == LDAP_NO_LIMIT)
- tvp = NULL;
- else
- {
- tv.tv_sec = nslcd_cfg->timelimit;
- tv.tv_usec = 0;
- tvp = &tv;
- }
- /* if we have an existing result entry, free it */
- if (search->entry != NULL)
- {
- myldap_entry_free(search->entry);
- search->entry = NULL;
- }
- /* try to parse results until we have a final error or ok */
- while (1)
- {
- /* free the previous message if there was any */
- if (search->msg != NULL)
- {
- ldap_msgfree(search->msg);
- search->msg = NULL;
- }
- /* get the next result */
- rc = ldap_result(search->session->ld, search->msgid, LDAP_MSG_ONE, tvp,
- &(search->msg));
- /* handle result */
- switch (rc)
- {
- case LDAP_RES_SEARCH_ENTRY:
- /* we have a normal search entry, update timestamp and return result */
- time(&(search->session->lastactivity));
- search->entry = myldap_entry_new(search);
- if (rcp != NULL)
- *rcp = LDAP_SUCCESS;
- /* log the first couple of dns in the result (but not all, to
- prevent swamping the log) */
- if (search->count < MAX_DEBUG_LOG_DNS)
- log_log(LOG_DEBUG, "ldap_result(): %s", myldap_get_dn(search->entry));
- search->count++;
- search->may_retry_search = 0;
- return search->entry;
- case LDAP_RES_SEARCH_RESULT:
- /* we have a search result, parse it */
- resultcontrols = NULL;
- if (search->cookie != NULL)
- {
- ber_bvfree(search->cookie);
- search->cookie = NULL;
- }
- /* NB: this frees search->msg */
- parserc = ldap_parse_result(search->session->ld, search->msg, &rc,
- NULL, NULL, NULL, &resultcontrols, 1);
- search->msg = NULL;
- /* check for errors during parsing */
- if ((parserc != LDAP_SUCCESS) && (parserc != LDAP_MORE_RESULTS_TO_RETURN))
- {
- if (resultcontrols != NULL)
- ldap_controls_free(resultcontrols);
- myldap_err(LOG_ERR, search->session->ld, parserc, "ldap_parse_result() failed");
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = parserc;
- return NULL;
- }
- /* check for errors in message */
- if ((rc != LDAP_SUCCESS) && (rc != LDAP_MORE_RESULTS_TO_RETURN))
- {
- if (resultcontrols != NULL)
- ldap_controls_free(resultcontrols);
- myldap_err(LOG_ERR, search->session->ld, rc, "ldap_result() failed");
- /* close connection on connection problems */
- if ((rc == LDAP_UNAVAILABLE) || (rc == LDAP_SERVER_DOWN))
- do_close(search->session);
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = rc;
- return NULL;
- }
- /* handle result controls */
- if (resultcontrols != NULL)
- {
- /* see if there are any more pages to come */
- rc = ldap_parse_page_control(search->session->ld, resultcontrols,
- &count, &(search->cookie));
- if (rc != LDAP_SUCCESS)
- {
- if (rc != LDAP_CONTROL_NOT_FOUND)
- myldap_err(LOG_WARNING, search->session->ld, rc, "ldap_parse_page_control() failed");
- /* clear error flag */
- rc = LDAP_SUCCESS;
- if (ldap_set_option(search->session->ld, LDAP_OPT_ERROR_NUMBER,
- &rc) != LDAP_SUCCESS)
- log_log(LOG_WARNING, "failed to clear the error flag");
- }
- /* TODO: handle the above return code?? */
- ldap_controls_free(resultcontrols);
- }
- search->msgid = -1;
- /* check if there are more pages to come */
- if ((search->cookie == NULL) || (search->cookie->bv_len == 0))
- {
- if (search->count > MAX_DEBUG_LOG_DNS)
- log_log(LOG_DEBUG, "ldap_result(): ... %d more results",
- search->count - MAX_DEBUG_LOG_DNS);
- log_log(LOG_DEBUG, "ldap_result(): end of results (%d total)",
- search->count);
- /* we are at the end of the search, no more results */
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = LDAP_SUCCESS;
- return NULL;
- }
- /* try the next page */
- rc = do_try_search(search);
- if (rc != LDAP_SUCCESS)
- {
- /* close connection on connection problems */
- if ((rc == LDAP_UNAVAILABLE) || (rc == LDAP_SERVER_DOWN))
- do_close(search->session);
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = rc;
- return NULL;
- }
- /* we continue with another pass */
- break;
- case LDAP_RES_SEARCH_REFERENCE:
- break; /* just ignore search references */
- default:
- /* we have some error condition, find out which */
- switch (rc)
- {
- case -1:
- /* try to get error code */
- if (ldap_get_option(search->session->ld, LDAP_OPT_ERROR_NUMBER,
- &rc) != LDAP_SUCCESS)
- rc = LDAP_UNAVAILABLE;
- myldap_err(LOG_ERR, search->session->ld, rc, "ldap_result() failed");
- break;
- case 0:
- /* the timeout expired */
- log_log(LOG_ERR, "ldap_result() timed out");
- rc = LDAP_TIMELIMIT_EXCEEDED;
- break;
- default:
- /* unknown code */
- log_log(LOG_WARNING, "ldap_result() returned unexpected result type");
- rc = LDAP_PROTOCOL_ERROR;
- }
- /* close connection on some connection problems */
- if ((rc == LDAP_UNAVAILABLE) || (rc == LDAP_SERVER_DOWN) ||
- (rc == LDAP_SUCCESS) || (rc == LDAP_TIMELIMIT_EXCEEDED) ||
- (rc == LDAP_OPERATIONS_ERROR) || (rc == LDAP_PROTOCOL_ERROR))
- {
- do_close(search->session);
- /* retry once if no data has been received yet */
- if (search->may_retry_search)
- {
- log_log(LOG_DEBUG, "myldap_get_entry(): retry search");
- search->may_retry_search = 0;
- if (do_retry_search(search) == LDAP_SUCCESS)
- return myldap_get_entry(search, rcp);
- }
- }
- /* close search */
- myldap_search_close(search);
- if (rcp != NULL)
- *rcp = rc;
- return NULL;
- }
- }
+ return search->get_entry(search->data, rcp);
}
/* Get the DN from the entry. This function only returns NULL (and sets