summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2014-11-28 17:29:41 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2014-11-28 17:29:41 -0500
commitd90f3a3da924ea9074b3c4eecb99dfef1cd9899c (patch)
tree72732881489344cb1ca6fd3d2b0fcb8eeaf905a2
parent70852a24b6a17727e79cf627aa918a4664e50e38 (diff)
no more myldap
-rw-r--r--nslcd/Makefile.am1
-rw-r--r--nslcd/common.h4
-rw-r--r--nslcd/myldap.c2028
3 files changed, 3 insertions, 2030 deletions
diff --git a/nslcd/Makefile.am b/nslcd/Makefile.am
index fa73910..ab50a9f 100644
--- a/nslcd/Makefile.am
+++ b/nslcd/Makefile.am
@@ -28,7 +28,6 @@ nslcd_SOURCES = nslcd.c ../nslcd.h ../common/nslcd-prot.h \
../compat/attrs.h \
log.c log.h \
common.c common.h \
- myldap.c myldap.h \
cfg.c cfg.h \
nsswitch.c invalidator.c \
db_config.c db_pam.c db_passwd.c db_shadow.c
diff --git a/nslcd/common.h b/nslcd/common.h
index 1893698..0f57c34 100644
--- a/nslcd/common.h
+++ b/nslcd/common.h
@@ -35,9 +35,11 @@
#include "common/nslcd-prot.h"
#include "common/tio.h"
#include "compat/attrs.h"
-#include "myldap.h"
#include "cfg.h"
+typedef struct ldap_session MYLDAP_SESSION;
+#define MYLDAP_ENTRY void
+
/* macros for basic read and write operations, the following
ERROR_OUT* marcos define the action taken on errors
the stream is not closed because the caller closes the
diff --git a/nslcd/myldap.c b/nslcd/myldap.c
deleted file mode 100644
index 095e8e6..0000000
--- a/nslcd/myldap.c
+++ /dev/null
@@ -1,2028 +0,0 @@
-/*
- myldap.c - simple interface to do LDAP requests
- Parts of this file were part of the nss_ldap library (as ldap-nss.c)
- which has been forked into the nss-pam-ldapd library.
-
- Copyright (C) 1997-2006 Luke Howard
- Copyright (C) 2006-2007 West Consulting
- Copyright (C) 2006-2014 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
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA
-*/
-
-/*
- This library expects to use an LDAP library to provide the real
- functionality and only provides a convenient wrapper.
- Some pointers for more information on the LDAP API:
- http://tools.ietf.org/id/draft-ietf-ldapext-ldap-c-api-05.txt
- http://www.mozilla.org/directory/csdk-docs/function.htm
- http://publib.boulder.ibm.com/infocenter/iseries/v5r3/topic/apis/dirserv1.htm
- http://www.openldap.org/software/man.cgi?query=ldap
-*/
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/time.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <lber.h>
-#include <ldap.h>
-#ifdef HAVE_LDAP_SSL_H
-#include <ldap_ssl.h>
-#endif
-#ifdef HAVE_GSSLDAP_H
-#include <gssldap.h>
-#endif
-#ifdef HAVE_GSSSASL_H
-#include <gsssasl.h>
-#endif
-#ifdef HAVE_SASL_SASL_H
-#include <sasl/sasl.h>
-#endif
-#ifdef HAVE_SASL_H
-#include <sasl.h>
-#endif
-#include <ctype.h>
-#include <pthread.h>
-#include <stdarg.h>
-
-#include "myldap.h"
-#include "common.h"
-#include "log.h"
-#include "cfg.h"
-#include "common/set.h"
-#include "compat/ldap_compat.h"
-#include "attmap.h"
-
-/* the maximum number of searches per session */
-#define MAX_SEARCHES_IN_SESSION 4
-
-/* the maximum number of dn's to log to the debug log for each search */
-#define MAX_DEBUG_LOG_DNS 10
-
-/* This refers to a current LDAP session that contains the connection
- information. */
-struct ldap_session {
- /* the connection */
- LDAP *ld;
- /* timestamp of last activity */
- time_t lastactivity;
- /* index into uris: currently connected LDAP uri */
- int current_uri;
- /* a list of searches registered with this session */
- struct myldap_search *searches[MAX_SEARCHES_IN_SESSION];
- /* the username to bind with */
- char binddn[BUFLEN_DN];
- /* the password to bind with if any */
- char bindpw[BUFLEN_PASSWORD];
- /* the authentication result (NSLCD_PAM_* code) */
- int policy_response;
- /* the authentication message */
- char policy_message[BUFLEN_MESSAGE];
-};
-
-/* A search description set as returned by myldap_search(). */
-struct myldap_search {
- /* reference to the session */
- MYLDAP_SESSION *session;
- /* indicator that the search is still valid */
- int valid;
- /* the parameters descibing the search */
- const char *base;
- int scope;
- const char *filter;
- char **attrs;
- /* a pointer to the current result entry, used for
- freeing resource allocated with that entry */
- MYLDAP_ENTRY *entry;
- /* LDAP message id for the search, -1 indicates absense of an active search */
- int msgid;
- /* the last result that was returned by ldap_result() */
- LDAPMessage *msg;
- /* cookie for paged searches */
- struct berval *cookie;
- /* to indicate that we can retry the search from myldap_get_entry() */
- int may_retry_search;
- /* the number of resutls returned so far */
- int count;
-};
-
-/* The maximum number of calls to myldap_get_values() that may be
- done per returned entry. */
-#define MAX_ATTRIBUTES_PER_ENTRY 16
-
-/* The maximum number of buffers (used for ranged attribute values and
- values returned by bervalues_to_values()) that may be stored per entry. */
-#define MAX_BUFFERS_PER_ENTRY 8
-
-/* A single entry from the LDAP database as returned by
- myldap_get_entry(). */
-struct myldap_entry {
- /* reference to the search to be used to get parameters
- (e.g. LDAP connection) for other calls */
- MYLDAP_SEARCH *search;
- /* the DN */
- const char *dn;
- /* a cached version of the exploded rdn */
- char **exploded_rdn;
- /* a cache of attribute to value list */
- char **attributevalues[MAX_ATTRIBUTES_PER_ENTRY];
- /* a reference to buffers so we can free() them later on */
- char **buffers[MAX_BUFFERS_PER_ENTRY];
-};
-
-/* Flag to record first search operation */
-int first_search = 1;
-
-static void myldap_err(int pri, LDAP *ld, int rc, const char *format, ...)
-{
- char message[BUFLEN_MESSAGE];
- char *msg_ldap = NULL;
- char *msg_diag = NULL;
- char *msg_errno = NULL;
- va_list ap;
- /* make the message */
- va_start(ap, format);
- vsnprintf(message, sizeof(message), format, ap);
- message[sizeof(message) - 1] = '\0';
- va_end(ap);
- /* get the various error message */
- if (rc != LDAP_SUCCESS)
- {
- msg_ldap = ldap_err2string(rc);
- /* get the diagnostic information */
-#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
- if (ld != NULL)
- ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &msg_diag);
-#endif /* LDAP_OPT_DIAGNOSTIC_MESSAGE */
- }
- if (errno != 0)
- msg_errno = strerror(errno);
- /* log the message */
- log_log(pri, "%s%s%s%s%s%s%s", message,
- (msg_ldap == NULL) ? "" : ": ", (msg_ldap == NULL) ? "" : msg_ldap,
- (msg_diag == NULL) ? "" : ": ", (msg_diag == NULL) ? "" : msg_diag,
- (msg_errno == NULL) ? "" : ": ", (msg_errno == NULL) ? "" : msg_errno);
- /* free diagnostic message */
- if (msg_diag != NULL)
- ldap_memfree(msg_diag);
-}
-
-static MYLDAP_ENTRY *myldap_entry_new(MYLDAP_SEARCH *search)
-{
- MYLDAP_ENTRY *entry;
- int i;
- /* Note: as an alternative we could embed the myldap_entry into the
- myldap_search struct to save on malloc() and free() calls. */
- /* allocate new entry */
- entry = (MYLDAP_ENTRY *)malloc(sizeof(struct myldap_entry));
- if (entry == NULL)
- {
- log_log(LOG_CRIT, "myldap_entry_new(): malloc() failed to allocate memory");
- exit(EXIT_FAILURE);
- }
- /* fill in fields */
- entry->search = search;
- entry->dn = NULL;
- entry->exploded_rdn = NULL;
- for (i = 0; i < MAX_ATTRIBUTES_PER_ENTRY; i++)
- entry->attributevalues[i] = NULL;
- for (i = 0; i < MAX_BUFFERS_PER_ENTRY; i++)
- entry->buffers[i] = NULL;
- /* return the fresh entry */
- return entry;
-}
-
-static void myldap_entry_free(MYLDAP_ENTRY *entry)
-{
- int i;
- /* free the DN */
- if (entry->dn != NULL)
- ldap_memfree((char *)entry->dn);
- /* free the exploded RDN */
- if (entry->exploded_rdn != NULL)
- ldap_value_free(entry->exploded_rdn);
- /* free all attribute values */
- for (i = 0; i < MAX_ATTRIBUTES_PER_ENTRY; i++)
- if (entry->attributevalues[i] != NULL)
- ldap_value_free(entry->attributevalues[i]);
- /* free all buffers */
- for (i = 0; i < MAX_BUFFERS_PER_ENTRY; i++)
- if (entry->buffers[i] != NULL)
- free(entry->buffers[i]);
- /* we don't need the result anymore, ditch it. */
- ldap_msgfree(entry->search->msg);
- entry->search->msg = NULL;
- /* free the actual memory for the struct */
- free(entry);
-}
-
-static MYLDAP_SEARCH *myldap_search_new(MYLDAP_SESSION *session,
- const char *base, int scope,
- const char *filter,
- const char **attrs)
-{
- char *buffer;
- MYLDAP_SEARCH *search;
- int i;
- size_t sz;
- /* figure out size for new memory block to allocate
- this has the advantage that we can free the whole lot with one call */
- sz = sizeof(struct myldap_search);
- sz += strlen(base) + 1 + strlen(filter) + 1;
- for (i = 0; attrs[i] != NULL; i++)
- sz += strlen(attrs[i]) + 1;
- sz += (i + 1) * sizeof(char *);
- /* allocate new results memory region */
- buffer = (char *)malloc(sz);
- if (buffer == NULL)
- {
- log_log(LOG_CRIT, "myldap_search_new(): malloc() failed to allocate memory");
- exit(EXIT_FAILURE);
- }
- /* initialize struct */
- search = (MYLDAP_SEARCH *)(void *)(buffer);
- buffer += sizeof(struct myldap_search);
- /* save pointer to session */
- search->session = session;
- /* flag as valid search */
- search->valid = 1;
- /* initialize array of attributes */
- search->attrs = (char **)(void *)buffer;
- buffer += (i + 1) * sizeof(char *);
- /* copy base */
- strcpy(buffer, base);
- search->base = buffer;
- buffer += strlen(base) + 1;
- /* just plainly store scope */
- search->scope = scope;
- /* copy filter */
- strcpy(buffer, filter);
- search->filter = buffer;
- buffer += strlen(filter) + 1;
- /* copy attributes themselves */
- for (i = 0; attrs[i] != NULL; i++)
- {
- strcpy(buffer, attrs[i]);
- search->attrs[i] = buffer;
- buffer += strlen(attrs[i]) + 1;
- }
- search->attrs[i] = NULL;
- /* initialize context */
- search->cookie = NULL;
- search->msg = NULL;
- search->msgid = -1;
- search->may_retry_search = 1;
- /* clear result entry */
- search->entry = NULL;
- search->count = 0;
- /* return the new search struct */
- return search;
-}
-
-static MYLDAP_SESSION *myldap_session_new(void)
-{
- MYLDAP_SESSION *session;
- int i;
- /* allocate memory for the session storage */
- session = (struct ldap_session *)malloc(sizeof(struct ldap_session));
- if (session == NULL)
- {
- log_log(LOG_CRIT, "myldap_session_new(): malloc() failed to allocate memory");
- exit(EXIT_FAILURE);
- }
- /* initialize the session */
- session->ld = NULL;
- session->lastactivity = 0;
- session->current_uri = 0;
- for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
- session->searches[i] = NULL;
- session->binddn[0] = '\0';
- memset(session->bindpw, 0, sizeof(session->bindpw));
- session->bindpw[0] = '\0';
- session->policy_response = NSLCD_PAM_SUCCESS;
- session->policy_message[0] = '\0';
- /* return the new session */
- return session;
-}
-
-PURE static inline int is_valid_entry(MYLDAP_ENTRY *entry)
-{
- return (entry != NULL) && (entry->search != NULL) &&
- (entry->search->session != NULL) && (entry->search->session->ld != NULL) &&
- (entry->search->msg != NULL);
-}
-
-#ifdef HAVE_SASL_INTERACT_T
-/* this is registered with ldap_sasl_interactive_bind_s() in do_bind() */
-static int do_sasl_interact(LDAP UNUSED(*ld), unsigned UNUSED(flags),
- void *defaults, void *_interact)
-{
- struct ldap_config *cfg = defaults;
- sasl_interact_t *interact = _interact;
- while (interact->id != SASL_CB_LIST_END)
- {
- switch (interact->id)
- {
- case SASL_CB_GETREALM:
- if (cfg->sasl_realm)
- {
- log_log(LOG_DEBUG, "do_sasl_interact(): returning sasl_realm \"%s\"",
- cfg->sasl_realm);
- interact->result = cfg->sasl_realm;
- interact->len = strlen(cfg->sasl_realm);
- }
- else
- log_log(LOG_DEBUG, "do_sasl_interact(): were asked for sasl_realm but we don't have any");
- break;
- case SASL_CB_AUTHNAME:
- if (cfg->sasl_authcid)
- {
- log_log(LOG_DEBUG, "do_sasl_interact(): returning sasl_authcid \"%s\"",
- cfg->sasl_authcid);
- interact->result = cfg->sasl_authcid;
- interact->len = strlen(cfg->sasl_authcid);
- }
- else
- log_log(LOG_DEBUG, "do_sasl_interact(): were asked for sasl_authcid but we don't have any");
- break;
- case SASL_CB_USER:
- if (cfg->sasl_authzid)
- {
- log_log(LOG_DEBUG, "do_sasl_interact(): returning sasl_authzid \"%s\"",
- cfg->sasl_authzid);
- interact->result = cfg->sasl_authzid;
- interact->len = strlen(cfg->sasl_authzid);
- }
- else
- log_log(LOG_DEBUG, "do_sasl_interact(): were asked for sasl_authzid but we don't have any");
- break;
- case SASL_CB_PASS:
- if (cfg->bindpw)
- {
- log_log(LOG_DEBUG, "do_sasl_interact(): returning bindpw \"***\"");
- interact->result = cfg->bindpw;
- interact->len = strlen(cfg->bindpw);
- }
- else
- log_log(LOG_DEBUG, "do_sasl_interact(): were asked for bindpw but we don't have any");
- break;
- default:
- /* just ignore */
- break;
- }
- interact++;
- }
- return LDAP_SUCCESS;
-}
-#endif /* HAVE_SASL_INTERACT_T */
-
-#define LDAP_SET_OPTION(ld, option, invalue) \
- rc = ldap_set_option(ld, option, invalue); \
- if (rc != LDAP_SUCCESS) \
- { \
- myldap_err(LOG_ERR, ld, rc, "ldap_set_option(" #option ") failed"); \
- return rc; \
- }
-
-#if defined(HAVE_LDAP_SASL_BIND) && defined(LDAP_SASL_SIMPLE)
-static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPControl **ctrls)
-{
- int i;
- int rc;
- /* clear policy response information in session */
- session->policy_response = NSLCD_PAM_SUCCESS;
- strncpy(session->policy_message, "", sizeof(session->policy_message));
- for (i = 0; ctrls[i] != NULL; i++)
- {
- if (strcmp(ctrls[i]->ldctl_oid, LDAP_CONTROL_PWEXPIRED) == 0)
- {
- /* check for expired control: force the user to change their password */
- log_log(LOG_DEBUG, "got LDAP_CONTROL_PWEXPIRED (password expired, user should change)");
- if (session->policy_response == NSLCD_PAM_SUCCESS)
- session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
- }
- else if (strcmp(ctrls[i]->ldctl_oid, LDAP_CONTROL_PWEXPIRING) == 0)
- {
- /* check for password expiration warning control: the password is about
- to expire (returns the number of seconds remaining until the password
- expires) */
- char seconds[32];
- long int sec;
- mysnprintf(seconds, sizeof(seconds), "%.*s", (int)ctrls[i]->ldctl_value.bv_len,
- ctrls[i]->ldctl_value.bv_val);
- sec = atol(seconds);
- log_log(LOG_DEBUG, "got LDAP_CONTROL_PWEXPIRING (password will expire in %ld seconds)",
- sec);
- /* return this warning to PAM */
- if (session->policy_response == NSLCD_PAM_SUCCESS)
- {
- session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "password will expire in %ld seconds", sec);
- }
- }
- else if (strcmp(ctrls[i]->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0)
- {
- /* check for password policy control */
- int expire = 0, grace = 0;
- LDAPPasswordPolicyError error = -1;
- rc = ldap_parse_passwordpolicy_control(ld, ctrls[i], &expire, &grace, &error);
- if (rc != LDAP_SUCCESS)
- myldap_err(LOG_WARNING, ld, rc, "ldap_parse_passwordpolicy_control() failed (ignored)");
- else
- {
- /* log returned control information */
- if (error != PP_noError)
- log_log(LOG_DEBUG, "got LDAP_CONTROL_PASSWORDPOLICYRESPONSE (%s)",
- ldap_passwordpolicy_err2txt(error));
- if (expire >= 0)
- log_log(LOG_DEBUG, "got LDAP_CONTROL_PASSWORDPOLICYRESPONSE (password will expire in %d seconds)",
- expire);
- if (grace >= 0)
- log_log(LOG_DEBUG, "got LDAP_CONTROL_PASSWORDPOLICYRESPONSE (%d grace logins left)",
- grace);
- /* return this information to PAM */
- if ((error == PP_passwordExpired) &&
- ((session->policy_response == NSLCD_PAM_SUCCESS) ||
- (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
- {
- session->policy_response = NSLCD_PAM_AUTHTOK_EXPIRED;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "%s", ldap_passwordpolicy_err2txt(error));
- }
- else if ((error == PP_accountLocked) &&
- ((session->policy_response == NSLCD_PAM_SUCCESS) ||
- (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
- {
- session->policy_response = NSLCD_PAM_ACCT_EXPIRED;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "%s", ldap_passwordpolicy_err2txt(error));
- }
- else if ((error == PP_changeAfterReset) &&
- (session->policy_response == NSLCD_PAM_SUCCESS))
- {
- session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "%s", ldap_passwordpolicy_err2txt(error));
- }
- else if ((error != PP_noError) &&
- ((session->policy_response == NSLCD_PAM_SUCCESS) ||
- (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
- {
- session->policy_response = NSLCD_PAM_PERM_DENIED;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "%s", ldap_passwordpolicy_err2txt(error));
- }
- else if ((expire >= 0) &&
- ((session->policy_response == NSLCD_PAM_SUCCESS) ||
- (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
- {
- session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "Password will expire in %d seconds", expire);
- }
- else if ((grace >= 0) &&
- (session->policy_response == NSLCD_PAM_SUCCESS))
- {
- session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
- mysnprintf(session->policy_message, sizeof(session->policy_message),
- "Password expired, %d grace logins left", grace);
- }
- }
- }
- /* ignore any other controls */
- }
-}
-
-static int do_ppolicy_bind(MYLDAP_SESSION *session, LDAP *ld, const char *uri)
-{
- int rc, parserc;
- struct berval cred;
- LDAPControl passwd_policy_req;
- LDAPControl *requestctrls[2];
- LDAPControl **responsectrls;
- int msgid;
- struct timeval timeout;
- LDAPMessage *result;
- /* build password policy request control */
- passwd_policy_req.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
- passwd_policy_req.ldctl_value.bv_val = NULL; /* none */
- passwd_policy_req.ldctl_value.bv_len = 0;
- passwd_policy_req.ldctl_iscritical = 0; /* not critical */
- requestctrls[0] = &passwd_policy_req;
- requestctrls[1] = NULL;
- /* build password berval */
- cred.bv_val = (char *)session->bindpw;
- cred.bv_len = (session->bindpw == NULL) ? 0 : strlen(session->bindpw);
- /* do a SASL simple bind with the binddn and bindpw */
- log_log(LOG_DEBUG, "ldap_sasl_bind(\"%s\",%s) (uri=\"%s\")", session->binddn,
- ((session->bindpw != NULL) && (session->bindpw[0] != '\0')) ? "\"***\"" : "\"\"", uri);
- rc = ldap_sasl_bind(ld, session->binddn, LDAP_SASL_SIMPLE, &cred, requestctrls, NULL, &msgid);
- if (rc != LDAP_SUCCESS)
- return rc;
- if (msgid == -1)
- {
- myldap_err(LOG_WARNING, ld, rc,"ldap_sasl_bind() failed (msgid=-1, uri=%s)", uri);
- return LDAP_OPERATIONS_ERROR;
- }
- /* get the result from the bind operation */
- timeout.tv_sec = nslcd_cfg->bind_timelimit;
- timeout.tv_usec = 0;
- result = NULL;
- rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &timeout, &result);
- if (rc == -1) /* some error */
- {
- if (ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS)
- rc = LDAP_UNAVAILABLE;
- myldap_err(LOG_ERR, ld, rc, "ldap_result() failed");
- if (result != NULL)
- ldap_msgfree(result);
- return LDAP_LOCAL_ERROR;
- }
- if (rc == 0) /* the timeout expired */
- {
- log_log(LOG_ERR, "ldap_result() timed out");
- if (result != NULL)
- ldap_msgfree(result);
- return LDAP_TIMEOUT;
- }
- /* parse the result from the bind operation (frees result, gets controls) */
- responsectrls = NULL;
- parserc = ldap_parse_result(ld, result, &rc, NULL, NULL, NULL, &responsectrls, 1);
- if (parserc != LDAP_SUCCESS)
- {
- myldap_err(LOG_ERR, ld, parserc, "ldap_parse_result() failed");
- if (responsectrls != NULL)
- ldap_controls_free(responsectrls);
- return parserc;
- }
- /* handle any returned controls */
- if (responsectrls != NULL)
- {
- handle_ppasswd_controls(session, ld, responsectrls);
- ldap_controls_free(responsectrls);
- }
- /* return the result of the BIND operation */
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_DEBUG, ld, rc, "ldap_parse_result() result");
- return rc;
- }
- /* check the returned controls */
- return LDAP_SUCCESS;
-}
-#endif /* no SASL, so no ppolicy */
-
-/* This function performs the authentication phase of opening a connection.
- The binddn and bindpw parameters may be used to override the authentication
- mechanism defined in the configuration. This returns an LDAP result
- code. */
-static int do_bind(MYLDAP_SESSION *session, LDAP *ld, const char *uri)
-{
- int rc;
-#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
-#ifndef HAVE_SASL_INTERACT_T
- struct berval cred;
-#endif /* not HAVE_SASL_INTERACT_T */
-#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
-#ifdef LDAP_OPT_X_TLS
- /* check if StartTLS is requested */
- if (nslcd_cfg->ssl == SSL_START_TLS)
- {
- log_log(LOG_DEBUG, "ldap_start_tls_s()");
- errno = 0;
- rc = ldap_start_tls_s(ld, NULL, NULL);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_WARNING, ld, rc, "ldap_start_tls_s() failed (uri=%s)",
- uri);
- return rc;
- }
- }
-#endif /* LDAP_OPT_X_TLS */
- /* check if the binddn and bindpw are overwritten in the session */
- if ((session->binddn != NULL) && (session->binddn[0] != '\0'))
- {
-#if defined(HAVE_LDAP_SASL_BIND) && defined(LDAP_SASL_SIMPLE)
- return do_ppolicy_bind(session, ld, uri);
-#else /* no SASL, so no ppolicy */
- /* do a simple bind */
- log_log(LOG_DEBUG, "ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",
- session->binddn,
- ((session->bindpw != NULL) && (session->bindpw[0] != '\0')) ? "\"***\"" : "\"\"",
- uri);
- return ldap_simple_bind_s(ld, session->binddn, session->bindpw);
-#endif
- }
- /* perform SASL bind if requested and available on platform */
-#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
- /* TODO: store this information in the session */
- if (nslcd_cfg->sasl_mech != NULL)
- {
- /* do a SASL bind */
- if (nslcd_cfg->sasl_secprops != NULL)
- {
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_SASL_SECPROPS,\"%s\")",
- nslcd_cfg->sasl_secprops);
- LDAP_SET_OPTION(ld, LDAP_OPT_X_SASL_SECPROPS, (void *)nslcd_cfg->sasl_secprops);
- }
-#ifdef HAVE_SASL_INTERACT_T
- if (nslcd_cfg->binddn != NULL)
- log_log(LOG_DEBUG, "ldap_sasl_interactive_bind_s(\"%s\",\"%s\") (uri=\"%s\")",
- nslcd_cfg->binddn, nslcd_cfg->sasl_mech, uri);
- else
- log_log(LOG_DEBUG, "ldap_sasl_interactive_bind_s(NULL,\"%s\") (uri=\"%s\")",
- nslcd_cfg->sasl_mech, uri);
- return ldap_sasl_interactive_bind_s(ld, nslcd_cfg->binddn,
- nslcd_cfg->sasl_mech, NULL, NULL,
- LDAP_SASL_QUIET, do_sasl_interact,
- (void *)nslcd_cfg);
-#else /* HAVE_SASL_INTERACT_T */
- if (nslcd_cfg->bindpw != NULL)
- {
- cred.bv_val = nslcd_cfg->bindpw;
- cred.bv_len = strlen(nslcd_cfg->bindpw);
- }
- else
- {
- cred.bv_val = "";
- cred.bv_len = 0;
- }
- if (nslcd_cfg->binddn != NULL)
- log_log(LOG_DEBUG, "ldap_sasl_bind_s(\"%s\",\"%s\",%s) (uri=\"%s\")",
- nslcd_cfg->binddn, nslcd_cfg->sasl_mech,
- nslcd_cfg->bindpw ? "\"***\"" : "NULL", uri);
- else
- log_log(LOG_DEBUG, "ldap_sasl_bind_s(NULL,\"%s\",%s) (uri=\"%s\")",
- nslcd_cfg->sasl_mech,
- nslcd_cfg->bindpw ? "\"***\"" : "NULL", uri);
- return ldap_sasl_bind_s(ld, nslcd_cfg->binddn,
- nslcd_cfg->sasl_mech, &cred, NULL, NULL, NULL);
-#endif /* not HAVE_SASL_INTERACT_T */
- }
-#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
- /* do a simple bind */
- if (nslcd_cfg->binddn)
- log_log(LOG_DEBUG, "ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",
- nslcd_cfg->binddn, nslcd_cfg->bindpw ? "\"***\"" : "NULL",
- uri);
- else
- log_log(LOG_DEBUG, "ldap_simple_bind_s(NULL,%s) (uri=\"%s\")",
- nslcd_cfg->bindpw ? "\"***\"" : "NULL", uri);
- return ldap_simple_bind_s(ld, nslcd_cfg->binddn, nslcd_cfg->bindpw);
-}
-
-#ifdef HAVE_LDAP_SET_REBIND_PROC
-/* This function is called by the LDAP library when chasing referrals.
- It is configured with the ldap_set_rebind_proc() below. */
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-static int do_rebind(LDAP *ld, LDAP_CONST char *url,
- ber_tag_t UNUSED(request),
- ber_int_t UNUSED(msgid), void *arg)
-{
- MYLDAP_SESSION *session = (MYLDAP_SESSION *)arg;
- log_log(LOG_DEBUG, "rebinding to %s", url);
- return do_bind(session, ld, url);
-}
-#else /* not recent OpenLDAP */
-static int do_rebind(LDAP *ld, char **dnp, char **passwdp, int *authmethodp,
- int freeit, void *arg)
-{
- MYLDAP_SESSION *session = (MYLDAP_SESSION *)arg;
- if (freeit)
- {
- free(*dnp);
- memset(*passwdp, 0, strlen(*passwdp));
- free(*passwdp);
- }
- else
- {
- log_log(LOG_DEBUG, "rebinding");
- *dnp = strdup(session->binddn);
- *passwdp = strdup(session->bindpw);
- *authmethodp = LDAP_AUTH_SIMPLE;
- if ((*dnp == NULL) || (*passwdp == NULL))
- {
- if (*dnp != NULL)
- free(*dnp);
- log_log(LOG_CRIT, "do_rebind(): strdup() failed to allocate memory");
- return LDAP_NO_MEMORY;
- }
- }
- return LDAP_SUCCESS;
-}
-#endif /* not recent OpenLDAP */
-#endif /* HAVE_LDAP_SET_REBIND_PROC */
-
-/* set a recieve and send timeout on a socket */
-static int set_socket_timeout(LDAP *ld, time_t sec, suseconds_t usec)
-{
- struct timeval tv;
- int rc = LDAP_SUCCESS;
- int sd;
- log_log(LOG_DEBUG, "set_socket_timeout(%lu,%lu)",
- (unsigned long)sec, (unsigned long)usec);
- /* get the socket */
- if ((rc = ldap_get_option(ld, LDAP_OPT_DESC, &sd)) != LDAP_SUCCESS)
- {
- myldap_err(LOG_ERR, ld, rc, "ldap_get_option(LDAP_OPT_DESC) failed");
- return rc;
- }
- /* ignore invalid (probably closed) file descriptors */
- if (sd <= 0)
- return LDAP_SUCCESS;
- /* set timeouts */
- memset(&tv, 0, sizeof(tv));
- tv.tv_sec = sec;
- tv.tv_usec = usec;
- if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)))
- {
- log_log(LOG_ERR, "setsockopt(%d,SO_RCVTIMEO) failed: %s",
- sd, strerror(errno));
- rc = LDAP_LOCAL_ERROR;
- }
- if (setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(tv)))
- {
- log_log(LOG_ERR, "setsockopt(%d,SO_RCVTIMEO) failed: %s",
- sd, strerror(errno));
- rc = LDAP_LOCAL_ERROR;
- }
- return rc;
-}
-
-#ifdef LDAP_OPT_CONNECT_CB
-/* This function is called by the LDAP library once a connection was made to the server. We
- set a timeout on the socket here, to catch network timeouts during the ssl
- handshake phase. It is configured with LDAP_OPT_CONNECT_CB. */
-static int connect_cb(LDAP *ld, Sockbuf UNUSED(*sb),
- LDAPURLDesc UNUSED(*srv), struct sockaddr UNUSED(*addr),
- struct ldap_conncb UNUSED(*ctx))
-{
- /* set timeout options on socket to avoid hang in some cases (a little
- more than the normal timeout so this should only be triggered in cases
- where the library behaves incorrectly) */
- if (nslcd_cfg->timelimit)
- set_socket_timeout(ld, nslcd_cfg->timelimit, 500000);
- return LDAP_SUCCESS;
-}
-
-/* We have an empty disconnect callback because LDAP_OPT_CONNECT_CB expects
- both functions to be available. */
-static void disconnect_cb(LDAP UNUSED(*ld), Sockbuf UNUSED(*sb),
- struct ldap_conncb UNUSED(*ctx))
-{
-}
-#endif /* LDAP_OPT_CONNECT_CB */
-
-/* This function sets a number of properties on the connection, based
- what is configured in the configfile. This function returns an
- LDAP status code. */
-static int do_set_options(MYLDAP_SESSION *session)
-{
- int rc;
- struct timeval tv;
-#ifdef LDAP_OPT_CONNECT_CB
- /* make this static because OpenLDAP doesn't make its own copy */
- static struct ldap_conncb cb;
-#endif /* LDAP_OPT_CONNECT_CB */
-#ifdef LDAP_OPT_X_TLS
- int i;
-#endif /* LDAP_OPT_X_TLS */
-#ifdef HAVE_LDAP_SET_REBIND_PROC
- /* the rebind function that is called when chasing referrals, see
- http://publib.boulder.ibm.com/infocenter/iseries/v5r3/topic/apis/ldap_set_rebind_proc.htm
- http://www.openldap.org/software/man.cgi?query=ldap_set_rebind_proc&manpath=OpenLDAP+2.4-Release */
- /* TODO: probably only set this if we should chase referrals */
- log_log(LOG_DEBUG, "ldap_set_rebind_proc()");
-#ifndef LDAP_SET_REBIND_PROC_RETURNS_VOID /* it returns int */
- rc = ldap_set_rebind_proc(session->ld, do_rebind, session);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_ERR, session->ld, rc, "ldap_set_rebind_proc() failed");
- return rc;
- }
-#else /* ldap_set_rebind_proc() returns void */
- ldap_set_rebind_proc(session->ld, do_rebind, session);
-#endif
-#endif /* HAVE_LDAP_SET_REBIND_PROC */
- /* set the protocol version to use */
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,%d)",
- nslcd_cfg->ldap_version);
- LDAP_SET_OPTION(session->ld, LDAP_OPT_PROTOCOL_VERSION,
- &nslcd_cfg->ldap_version);
- /* set some other options */
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_DEREF,%d)",
- nslcd_cfg->deref);
- LDAP_SET_OPTION(session->ld, LDAP_OPT_DEREF, &nslcd_cfg->deref);
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_TIMELIMIT,%d)",
- nslcd_cfg->timelimit);
- LDAP_SET_OPTION(session->ld, LDAP_OPT_TIMELIMIT, &nslcd_cfg->timelimit);
- tv.tv_sec = nslcd_cfg->bind_timelimit;
- tv.tv_usec = 0;
-#ifdef LDAP_OPT_TIMEOUT
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_TIMEOUT,%d)",
- nslcd_cfg->timelimit);
- LDAP_SET_OPTION(session->ld, LDAP_OPT_TIMEOUT, &tv);
-#endif /* LDAP_OPT_TIMEOUT */
-#ifdef LDAP_OPT_NETWORK_TIMEOUT
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT,%d)",
- nslcd_cfg->timelimit);
- LDAP_SET_OPTION(session->ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
-#endif /* LDAP_OPT_NETWORK_TIMEOUT */
-#ifdef LDAP_X_OPT_CONNECT_TIMEOUT
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_X_OPT_CONNECT_TIMEOUT,%d)",
- nslcd_cfg->timelimit);
- LDAP_SET_OPTION(session->ld, LDAP_X_OPT_CONNECT_TIMEOUT, &tv);
-#endif /* LDAP_X_OPT_CONNECT_TIMEOUT */
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_REFERRALS,%s)",
- nslcd_cfg->referrals ? "LDAP_OPT_ON" : "LDAP_OPT_OFF");
- LDAP_SET_OPTION(session->ld, LDAP_OPT_REFERRALS,
- nslcd_cfg->referrals ? LDAP_OPT_ON : LDAP_OPT_OFF);
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_RESTART,LDAP_OPT_ON)");
- LDAP_SET_OPTION(session->ld, LDAP_OPT_RESTART, LDAP_OPT_ON);
-#ifdef LDAP_OPT_CONNECT_CB
- /* register a connection callback */
- cb.lc_add = connect_cb;
- cb.lc_del = disconnect_cb;
- cb.lc_arg = NULL;
- LDAP_SET_OPTION(session->ld, LDAP_OPT_CONNECT_CB, (void *)&cb);
-#endif /* LDAP_OPT_CONNECT_CB */
-#ifdef LDAP_OPT_X_TLS
- /* if SSL is desired, then enable it */
- if ((nslcd_cfg->ssl == SSL_LDAPS) ||
- (strncasecmp(nslcd_cfg->uris[session->current_uri].uri, "ldaps://", 8) == 0))
- {
- /* use tls */
- i = LDAP_OPT_X_TLS_HARD;
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS,LDAP_OPT_X_TLS_HARD)");
- LDAP_SET_OPTION(session->ld, LDAP_OPT_X_TLS, &i);
- }
-#endif /* LDAP_OPT_X_TLS */
-#ifdef LDAP_OPT_X_SASL_NOCANON
- if (nslcd_cfg->sasl_canonicalize >= 0)
- {
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_SASL_NOCANON,%s)",
- nslcd_cfg->sasl_canonicalize ? "LDAP_OPT_OFF" : "LDAP_OPT_ON");
- LDAP_SET_OPTION(session->ld, LDAP_OPT_X_SASL_NOCANON,
- nslcd_cfg->sasl_canonicalize ? LDAP_OPT_OFF : LDAP_OPT_ON);
- }
-#endif /* LDAP_OPT_X_SASL_NOCANON */
- /* if nothing above failed, everything should be fine */
- return LDAP_SUCCESS;
-}
-
-/* close the connection to the server and invalidate any running searches */
-static void do_close(MYLDAP_SESSION *session)
-{
- int i;
- int rc;
- time_t sec;
- /* if we had reachability problems with the server close the connection */
- if (session->ld != NULL)
- {
- /* set timeout options on socket to avoid hang in some cases
- (we set a short timeout because we don't care too much about properly
- shutting down the connection) */
- if (nslcd_cfg->timelimit)
- {
- sec = nslcd_cfg->timelimit / 2;
- if (!sec)
- sec = 1;
- set_socket_timeout(session->ld, sec, 0);
- }
- /* go over the other searches and partially close them */
- for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
- {
- if (session->searches[i] != NULL)
- {
- /* free any messages (because later ld is no longer valid) */
- if (session->searches[i]->msg != NULL)
- {
- ldap_msgfree(session->searches[i]->msg);
- session->searches[i]->msg = NULL;
- }
- /* abandon the search if there were more results to fetch */
- if (session->searches[i]->msgid != -1)
- {
- log_log(LOG_DEBUG, "ldap_abandon()");
- if (ldap_abandon(session->searches[i]->session->ld, session->searches[i]->msgid))
- {
- if (ldap_get_option(session->ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS)
- rc = LDAP_OTHER;
- myldap_err(LOG_WARNING, session->ld, rc,
- "ldap_abandon() failed to abandon search");
- }
- session->searches[i]->msgid = -1;
- }
- /* flag the search as invalid */
- session->searches[i]->valid = 0;
- }
- }
- /* close the connection to the server */
- log_log(LOG_DEBUG, "ldap_unbind()");
- rc = ldap_unbind(session->ld);
- session->ld = NULL;
- if (rc != LDAP_SUCCESS)
- myldap_err(LOG_WARNING, session->ld, rc, "ldap_unbind() failed");
- }
-}
-
-void myldap_session_check(MYLDAP_SESSION *session)
-{
- int i;
- time_t current_time;
- int sd;
- int rc;
- struct sockaddr sa;
- socklen_t salen = sizeof(sa);
- /* check parameters */
- if (session == NULL)
- {
- log_log(LOG_ERR, "myldap_session_check(): invalid parameter passed");
- errno = EINVAL;
- return;
- }
- if (session->ld != NULL)
- {
- rc = ldap_get_option(session->ld, LDAP_OPT_DESC, &sd);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_WARNING, session->ld, rc,
- "ldap_get_option(LDAP_OPT_DESC) failed (ignored)");
- }
- else
- {
- /* check if the connection was closed by the peer */
- if (getpeername(sd, &sa, &salen) == -1)
- {
- if (errno == ENOTCONN)
- {
- log_log(LOG_DEBUG, "myldap_session_check(): connection reset by peer");
- do_close(session);
- return;
- }
- }
- }
- /* check if we should time out the connection */
- if (nslcd_cfg->idle_timelimit > 0)
- {
- /* if we have any running searches, don't time out */
- for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
- if ((session->searches[i] != NULL) && (session->searches[i]->valid))
- return;
- /* consider timeout (there are no running searches) */
- time(&current_time);
- if ((session->lastactivity + nslcd_cfg->idle_timelimit) < current_time)
- {
- log_log(LOG_DEBUG, "myldap_session_check(): idle_timelimit reached");
- do_close(session);
- }
- }
- }
-}
-
-/* This opens connection to an LDAP server, sets all connection options
- and binds to the server. This returns an LDAP status code. */
-static int do_open(MYLDAP_SESSION *session)
-{
- int rc;
- /* if the connection is still there (ie. ldap_unbind() wasn't
- called) then we can return the cached connection */
- if (session->ld != NULL)
- return LDAP_SUCCESS;
- /* we should build a new session now */
- session->ld = NULL;
- session->lastactivity = 0;
- /* open the connection */
- log_log(LOG_DEBUG, "ldap_initialize(%s)",
- nslcd_cfg->uris[session->current_uri].uri);
- errno = 0;
- rc = ldap_initialize(&(session->ld), nslcd_cfg->uris[session->current_uri].uri);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_WARNING, session->ld, rc, "ldap_initialize(%s) failed",
- nslcd_cfg->uris[session->current_uri].uri);
- if (session->ld != NULL)
- do_close(session);
- return rc;
- }
- else if (session->ld == NULL)
- {
- log_log(LOG_WARNING, "ldap_initialize() returned NULL");
- return LDAP_LOCAL_ERROR;
- }
- /* set the options for the connection */
- rc = do_set_options(session);
- if (rc != LDAP_SUCCESS)
- {
- do_close(session);
- return rc;
- }
- /* bind to the server */
- errno = 0;
- rc = do_bind(session, session->ld, nslcd_cfg->uris[session->current_uri].uri);
- if (rc != LDAP_SUCCESS)
- {
- /* log actual LDAP error code */
- myldap_err((session->binddn[0] == '\0') ? LOG_WARNING : LOG_DEBUG,
- session->ld, rc, "failed to bind to LDAP server %s",
- nslcd_cfg->uris[session->current_uri].uri);
- do_close(session);
- return rc;
- }
- /* update last activity and finish off state */
- time(&(session->lastactivity));
- return LDAP_SUCCESS;
-}
-
-/* Set alternative credentials for the session. */
-int myldap_set_credentials(MYLDAP_SESSION *session, const char *dn,
- const char *password)
-{
- /* error out when buffers are too small */
- if (strlen(dn) >= sizeof(session->binddn))
- {
- log_log(LOG_ERR,
- "myldap_set_credentials(): binddn buffer too small (%d required)",
- strlen(dn));
- return -1;
- }
- if (strlen(password) >= sizeof(session->bindpw))
- {
- log_log(LOG_ERR,
- "myldap_set_credentials(): bindpw buffer too small (%d required)",
- strlen(password));
- return -1;
- }
- /* copy dn and password into session */
- strncpy(session->binddn, dn, sizeof(session->binddn));
- session->binddn[sizeof(session->binddn) - 1] = '\0';
- strncpy(session->bindpw, password, sizeof(session->bindpw));
- session->bindpw[sizeof(session->bindpw) - 1] = '\0';
- return 0;
-}
-
-/* Get bind ppolicy results from the last bind operation. This function
- returns a NSLCD_PAM_* code and optional message. */
-void myldap_get_policy_response(MYLDAP_SESSION *session, int *response,
- const char **message)
-{
- if (response != NULL)
- *response = session->policy_response;
- if (message != NULL)
- *message = session->policy_message;
-}
-
-static int do_try_search(MYLDAP_SEARCH *search)
-{
- int ctrlidx = 0;
- int rc;
- LDAPControl *serverctrls[3];
-#ifdef HAVE_LDAP_CREATE_DEREF_CONTROL
- int i;
- struct LDAPDerefSpec ds[2];
- char *deref_attrs[2];
-#endif /* HAVE_LDAP_CREATE_DEREF_CONTROL */
- int msgid;
- /* ensure that we have an open connection */
- rc = do_open(search->session);
- if (rc != LDAP_SUCCESS)
- return rc;
- /* if we're using paging, build a page control */
- if ((nslcd_cfg->pagesize > 0) && (search->scope != LDAP_SCOPE_BASE))
- {
- rc = ldap_create_page_control(search->session->ld, nslcd_cfg->pagesize,
- search->cookie, 0, &serverctrls[ctrlidx]);
- if (rc == LDAP_SUCCESS)
- ctrlidx++;
- else
- {
- myldap_err(LOG_WARNING, search->session->ld, rc,
- "ldap_create_page_control() failed");
- serverctrls[ctrlidx] = NULL;
- /* if we were paging, failure building the second control is fatal */
- if (search->cookie != NULL)
- return rc;
- }
- }
-#ifdef HAVE_LDAP_CREATE_DEREF_CONTROL
- /* if doing group searches, add deref control to search request
- (this is currently a bit of a hack and hard-coded for group searches
- which are detected by requesting the attmap_group_member member
- attribute) */
- for (i = 0; search->attrs[i] != NULL; i++)
- if (strcasecmp(search->attrs[i], attmap_group_member) == 0)
- {
- /* attributes from dereff'd entries */
- deref_attrs[0] = (void *)attmap_passwd_uid;
- deref_attrs[1] = NULL;
- /* build deref control */
- ds[0].derefAttr = (void *)attmap_group_member;
- ds[0].attributes = deref_attrs;
- ds[1].derefAttr = NULL;
- ds[1].attributes = NULL;
- rc = ldap_create_deref_control(search->session->ld, ds, 0, &serverctrls[ctrlidx]);
- if (rc == LDAP_SUCCESS)
- ctrlidx++;
- else
- {
- myldap_err(LOG_WARNING, search->session->ld, rc,
- "ldap_create_deref_control() failed");
- serverctrls[ctrlidx] = NULL;
- }
- }
-#endif /* HAVE_LDAP_CREATE_DEREF_CONTROL */
- /* NULL terminate control list */
- serverctrls[ctrlidx] = NULL;
- /* clear error flag (perhaps control setting failed) */
- if (ctrlidx > 0)
- {
- 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");
- }
- /* perform the search */
- rc = ldap_search_ext(search->session->ld, search->base, search->scope,
- search->filter, (char **)(search->attrs),
- 0, serverctrls[0] == NULL ? NULL : serverctrls,
- NULL, NULL, LDAP_NO_LIMIT, &msgid);
- /* free the controls if we had them */
- for (ctrlidx = 0; serverctrls[ctrlidx] != NULL; ctrlidx++)
- ldap_control_free(serverctrls[ctrlidx]);
- /* handle errors */
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_WARNING, search->session->ld, rc, "ldap_search_ext() failed");
- return rc;
- }
- /* update the last activity on the connection */
- time(&(search->session->lastactivity));
- /* save msgid */
- search->msgid = msgid;
- /* return the new search */
- return LDAP_SUCCESS;
-}
-
-MYLDAP_SESSION *myldap_create_session(void)
-{
- return myldap_session_new();
-}
-
-void myldap_session_cleanup(MYLDAP_SESSION *session)
-{
- int i;
- /* check parameter */
- if (session == NULL)
- {
- log_log(LOG_ERR, "myldap_session_cleanup(): invalid session passed");
- return;
- }
- /* go over all searches in the session and close them */
- for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
- {
- if (session->searches[i] != NULL)
- {
- myldap_search_close(session->searches[i]);
- session->searches[i] = NULL;
- }
- }
-}
-
-void myldap_session_close(MYLDAP_SESSION *session)
-{
- /* check parameter */
- if (session == NULL)
- {
- log_log(LOG_ERR, "myldap_session_cleanup(): invalid session passed");
- return;
- }
- /* close pending searches */
- myldap_session_cleanup(session);
- /* close any open connections */
- do_close(session);
- /* free allocated memory */
- memset(session->bindpw, 0, sizeof(session->bindpw));
- free(session);
-}
-
-
-void myldap_search_close(MYLDAP_SEARCH *search)
-{
- search->close(search);
-}
-
-struct myldap_search {
- MYLDAP_ENTRY *(*get_entry)(void *data, int *rcp);
- void *data;
-}
-
-MYLDAP_ENTRY *myldap_get_entry(MYLDAP_SEARCH *search, int *rcp)
-{
- return search->get_entry(search->data, rcp);
-}
-
-/* Get the DN from the entry. This function only returns NULL (and sets
- errno) if an incorrect entry is passed. If the DN value cannot be
- retrieved "unknown" is returned instead. */
-const char *myldap_get_dn(MYLDAP_ENTRY *entry)
-{
- int rc;
- /* check parameters */
- if (!is_valid_entry(entry))
- {
- log_log(LOG_ERR, "myldap_get_dn(): invalid result entry passed");
- errno = EINVAL;
- return "unknown";
- }
- /* if we don't have it yet, retreive it */
- if ((entry->dn == NULL) && (entry->search->valid))
- {
- entry->dn = ldap_get_dn(entry->search->session->ld, entry->search->msg);
- if (entry->dn == NULL)
- {
- if (ldap_get_option(entry->search->session->ld, LDAP_OPT_ERROR_NUMBER,
- &rc) != LDAP_SUCCESS)
- rc = LDAP_UNAVAILABLE;
- myldap_err(LOG_WARNING, entry->search->session->ld, rc, "ldap_get_dn() returned NULL");
- /* close connection on connection problems */
- if ((rc == LDAP_UNAVAILABLE) || (rc == LDAP_SERVER_DOWN))
- do_close(entry->search->session);
- }
- }
- /* if we still don't have it, return unknown */
- if (entry->dn == NULL)
- return "unknown";
- /* return it */
- return entry->dn;
-}
-
-char *myldap_cpy_dn(MYLDAP_ENTRY *entry, char *buf, size_t buflen)
-{
- const char *dn;
- /* get the dn */
- dn = myldap_get_dn(entry);
- /* copy into buffer */
- if (strlen(dn) < buflen)
- strcpy(buf, dn);
- else
- buf = NULL;
- return buf;
-}
-
-/* Perform ranged retreival of attributes.
- http://msdn.microsoft.com/en-us/library/aa367017(vs.85).aspx
- http://www.tkk.fi/cc/docs/kerberos/draft-kashi-incremental-00.txt */
-static char **myldap_get_ranged_values(MYLDAP_ENTRY *entry, const char *attr)
-{
- char **values;
- char *attn;
- const char *attrs[2];
- BerElement *ber;
- int i;
- int startat = 0, nxt = 0;
- char attbuf[80];
- const char *dn = myldap_get_dn(entry);
- MYLDAP_SESSION *session = entry->search->session;
- MYLDAP_SEARCH *search = NULL;
- SET *set = NULL;
- /* build the attribute name to find */
- if (mysnprintf(attbuf, sizeof(attbuf), "%s;range=0-*", attr))
- {
- log_log(LOG_ERR, "myldap_get_ranged_values(): attbuf buffer too small (%d required)",
- strlen(attr) + 10);
- return NULL;
- }
- /* keep doing lookups untul we can't get any more results */
- while (1)
- {
- /* go over all attributes to find the ranged attribute */
- ber = NULL;
- attn = ldap_first_attribute(entry->search->session->ld, entry->search->msg, &ber);
- values = NULL;
- while (attn != NULL)
- {
- if (strncasecmp(attn, attbuf, strlen(attbuf) - 1) == 0)
- {
- log_log(LOG_DEBUG, "found ranged results %s", attn);
- nxt = atoi(attn + strlen(attbuf) - 1) + 1;
- values = ldap_get_values(entry->search->session->ld, entry->search->msg, attn);
- ldap_memfree(attn);
- break;
- }
- /* free old attribute name and get next one */
- ldap_memfree(attn);
- attn = ldap_next_attribute(entry->search->session->ld, entry->search->msg, ber);
- }
- ber_free(ber, 0);
- /* see if we found any values */
- if ((values == NULL) || (*values == NULL))
- break;
- /* allocate memory */
- if (set == NULL)
- {
- set = set_new();
- if (set == NULL)
- {
- ldap_value_free(values);
- log_log(LOG_CRIT, "myldap_get_ranged_values(): set_new() failed to allocate memory");
- return NULL;
- }
- }
- /* add to the set */
- for (i = 0; values[i] != NULL; i++)
- set_add(set, values[i]);
- /* free results */
- ldap_value_free(values);
- /* check if we should start a new search */
- if (nxt <= startat)
- break;
- startat = nxt;
- /* build attributes for a new search */
- if (mysnprintf(attbuf, sizeof(attbuf), "%s;range=%d-*", attr, startat))
- {
- log_log(LOG_ERR, "myldap_get_ranged_values(): attbuf buffer too small");
- break;
- }
- attrs[0] = attbuf;
- attrs[1] = NULL;
- /* close the previous search, if any */
- if (search != NULL)
- myldap_search_close(search);
- /* start the new search */
- search = myldap_search(session, dn, LDAP_SCOPE_BASE, "(objectClass=*)", attrs, NULL);
- if (search == NULL)
- break;
- entry = myldap_get_entry(search, NULL);
- if (entry == NULL)
- break;
- }
- /* close any started searches */
- if (search != NULL)
- myldap_search_close(search);
- /* return the contents of the set as a list */
- if (set == NULL)
- return NULL;
- values = (char **)set_tolist(set);
- set_free(set);
- if (values == NULL)
- log_log(LOG_CRIT, "myldap_get_ranged_values(): malloc() failed to allocate memory");
- return values;
-}
-
-/* Simple wrapper around ldap_get_values(). */
-const char **myldap_get_values(MYLDAP_ENTRY *entry, const char *attr)
-{
- char **values;
- int rc;
- int i;
- /* check parameters */
- if (!is_valid_entry(entry))
- {
- log_log(LOG_ERR, "myldap_get_values(): invalid result entry passed");
- errno = EINVAL;
- return NULL;
- }
- else if (attr == NULL)
- {
- log_log(LOG_ERR, "myldap_get_values(): invalid attribute name passed");
- errno = EINVAL;
- return NULL;
- }
- if (!entry->search->valid)
- return NULL; /* search has been stopped */
- /* get from LDAP */
- values = ldap_get_values(entry->search->session->ld, entry->search->msg, attr);
- if (values == NULL)
- {
- if (ldap_get_option(entry->search->session->ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS)
- rc = LDAP_UNAVAILABLE;
- /* ignore decoding errors as they are just nonexisting attribute values */
- if (rc == LDAP_DECODING_ERROR)
- {
- rc = LDAP_SUCCESS;
- if (ldap_set_option(entry->search->session->ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS)
- log_log(LOG_WARNING, "failed to clear the error flag");
- }
- else if (rc == LDAP_SUCCESS)
- {
- /* we have a success code but no values, let's try to get ranged
- values */
- values = myldap_get_ranged_values(entry, attr);
- if (values == NULL)
- return NULL;
- /* store values entry so we can free it later on */
- for (i = 0; i < MAX_BUFFERS_PER_ENTRY; i++)
- if (entry->buffers[i] == NULL)
- {
- entry->buffers[i] = values;
- return (const char **)entry->buffers[i];
- }
- /* we found no room to store the values */
- log_log(LOG_ERR, "ldap_get_values() couldn't store results, increase MAX_BUFFERS_PER_ENTRY");
- free(values);
- return NULL;
- }
- else
- myldap_err(LOG_WARNING, entry->search->session->ld, rc,
- "ldap_get_values() of attribute \"%s\" on entry \"%s\" returned NULL",
- attr, myldap_get_dn(entry));
- return NULL;
- }
- /* store values entry so we can free it later on */
- for (i = 0; i < MAX_ATTRIBUTES_PER_ENTRY; i++)
- if (entry->attributevalues[i] == NULL)
- {
- entry->attributevalues[i] = values;
- return (const char **)values;
- }
- /* we found no room to store the entry */
- log_log(LOG_ERR, "ldap_get_values() couldn't store results, increase MAX_ATTRIBUTES_PER_ENTRY");
- ldap_value_free(values);
- return NULL;
-}
-
-/* Convert the bervalues to a simple list of strings that can be freed
- with one call to free(). */
-static const char **bervalues_to_values(struct berval **bvalues)
-{
- int num_values;
- int i;
- size_t sz;
- char *buf;
- char **values;
- /* figure out how much memory to allocate */
- num_values = ldap_count_values_len(bvalues);
- sz = (num_values + 1) * sizeof(char *);
- for (i = 0; i < num_values; i++)
- sz += bvalues[i]->bv_len + 1;
- /* allocate the needed memory */
- values = (char **)malloc(sz);
- if (values == NULL)
- {
- log_log(LOG_CRIT, "bervalues_to_values(): malloc() failed to allocate memory");
- return NULL;
- }
- buf = (char *)values;
- buf += (num_values + 1) * sizeof(char *);
- /* copy from bvalues */
- for (i = 0; i < num_values; i++)
- {
- values[i] = buf;
- memcpy(values[i], bvalues[i]->bv_val, bvalues[i]->bv_len);
- values[i][bvalues[i]->bv_len] = '\0';
- buf += bvalues[i]->bv_len + 1;
- }
- values[i] = NULL;
- return (const char **)values;
-}
-
-/* Simple wrapper around ldap_get_values(). */
-const char **myldap_get_values_len(MYLDAP_ENTRY *entry, const char *attr)
-{
- const char **values;
- struct berval **bvalues;
- int rc;
- int i;
- /* check parameters */
- if (!is_valid_entry(entry))
- {
- log_log(LOG_ERR, "myldap_get_values_len(): invalid result entry passed");
- errno = EINVAL;
- return NULL;
- }
- else if (attr == NULL)
- {
- log_log(LOG_ERR, "myldap_get_values_len(): invalid attribute name passed");
- errno = EINVAL;
- return NULL;
- }
- if (!entry->search->valid)
- return NULL; /* search has been stopped */
- /* get from LDAP */
- bvalues = ldap_get_values_len(entry->search->session->ld, entry->search->msg, attr);
- if (bvalues == NULL)
- {
- if (ldap_get_option(entry->search->session->ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS)
- rc = LDAP_UNAVAILABLE;
- /* ignore decoding errors as they are just nonexisting attribute values */
- if (rc == LDAP_DECODING_ERROR)
- {
- rc = LDAP_SUCCESS;
- if (ldap_set_option(entry->search->session->ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS)
- log_log(LOG_WARNING, "failed to clear the error flag");
- return NULL;
- }
- else if (rc == LDAP_SUCCESS)
- {
- /* we have a success code but no values, let's try to get ranged
- values */
- values = (const char **)myldap_get_ranged_values(entry, attr);
- }
- else
- {
- myldap_err(LOG_WARNING, entry->search->session->ld, rc,
- "myldap_get_values_len() of attribute \"%s\" on entry \"%s\" returned NULL",
- attr, myldap_get_dn(entry));
- return NULL;
- }
- }
- else
- {
- values = bervalues_to_values(bvalues);
- ldap_value_free_len(bvalues);
- }
- /* check if we got allocated memory */
- if (values == NULL)
- return NULL;
- /* store values entry so we can free it later on */
- for (i = 0; i < MAX_BUFFERS_PER_ENTRY; i++)
- if (entry->buffers[i] == NULL)
- {
- entry->buffers[i] = (char **)values;
- return values;
- }
- /* we found no room to store the values */
- log_log(LOG_ERR, "myldap_get_values_len() couldn't store results, increase MAX_BUFFERS_PER_ENTRY");
- free(values);
- return NULL;
-}
-
-/* Go over the entries in exploded_rdn and see if any start with
- the requested attribute. Return a reference to the value part of
- the DN (does not modify exploded_rdn). */
-static const char *find_rdn_value(char **exploded_rdn, const char *attr)
-{
- int i, j;
- int l;
- if (exploded_rdn == NULL)
- return NULL;
- /* go over all RDNs */
- l = strlen(attr);
- for (i = 0; exploded_rdn[i] != NULL; i++)
- {
- /* check that RDN starts with attr */
- if (strncasecmp(exploded_rdn[i], attr, l) != 0)
- continue;
- j = l;
- /* skip spaces */
- while (isspace(exploded_rdn[i][j]))
- j++;
- /* ensure that we found an equals sign now */
- if (exploded_rdn[i][j] != '=')
- continue;
- j++;
- /* skip more spaces */
- while (isspace(exploded_rdn[i][j]))
- j++;
- /* ensure that we're not at the end of the string */
- if (exploded_rdn[i][j] == '\0')
- continue;
- /* we found our value */
- return exploded_rdn[i] + j;
- }
- /* fail */
- return NULL;
-}
-
-/* explode the first part of DN into parts
- (e.g. "cn=Test", "uid=test")
- The returned value should be freed with ldap_value_free(). */
-static char **get_exploded_rdn(const char *dn)
-{
- char **exploded_dn;
- char **exploded_rdn;
- /* check if we have a DN */
- if ((dn == NULL) || (strcasecmp(dn, "unknown") == 0))
- return NULL;
- /* explode dn into { "uid=test", "ou=people", ..., NULL } */
- exploded_dn = ldap_explode_dn(dn, 0);
- if ((exploded_dn == NULL) || (exploded_dn[0] == NULL))
- {
- log_log(LOG_WARNING, "ldap_explode_dn(%s) returned NULL: %s",
- dn, strerror(errno));
- return NULL;
- }
- /* explode rdn (first part of exploded_dn),
- e.g. "cn=Test User+uid=testusr" into
- { "cn=Test User", "uid=testusr", NULL } */
- errno = 0;
- exploded_rdn = ldap_explode_rdn(exploded_dn[0], 0);
- if ((exploded_rdn == NULL) || (exploded_rdn[0] == NULL))
- {
- log_log(LOG_WARNING, "ldap_explode_rdn(%s) returned NULL: %s",
- exploded_dn[0], strerror(errno));
- if (exploded_rdn != NULL)
- ldap_value_free(exploded_rdn);
- ldap_value_free(exploded_dn);
- return NULL;
- }
- ldap_value_free(exploded_dn);
- return exploded_rdn;
-}
-
-const char *myldap_get_rdn_value(MYLDAP_ENTRY *entry, const char *attr)
-{
- /* check parameters */
- if (!is_valid_entry(entry))
- {
- log_log(LOG_ERR, "myldap_get_rdn_value(): invalid result entry passed");
- errno = EINVAL;
- return NULL;
- }
- else if (attr == NULL)
- {
- log_log(LOG_ERR, "myldap_get_rdn_value(): invalid attribute name passed");
- errno = EINVAL;
- return NULL;
- }
- /* check if entry contains exploded_rdn */
- if (entry->exploded_rdn == NULL)
- {
- entry->exploded_rdn = get_exploded_rdn(myldap_get_dn(entry));
- if (entry->exploded_rdn == NULL)
- return NULL;
- }
- /* find rnd value */
- return find_rdn_value(entry->exploded_rdn, attr);
-}
-
-const char *myldap_cpy_rdn_value(const char *dn, const char *attr,
- char *buf, size_t buflen)
-{
- char **exploded_rdn;
- const char *value;
- /* explode dn into { "cn=Test", "uid=test", NULL } */
- exploded_rdn = get_exploded_rdn(dn);
- if (exploded_rdn == NULL)
- return NULL;
- /* see if we have a match */
- value = find_rdn_value(exploded_rdn, attr);
- /* if we have something store it in the buffer */
- if ((value != NULL) && (strlen(value) < buflen))
- strcpy(buf, value);
- else
- value = NULL;
- /* free allocated stuff */
- ldap_value_free(exploded_rdn);
- /* check if we have something to return */
- return (value != NULL) ? buf : NULL;
-}
-
-int myldap_has_objectclass(MYLDAP_ENTRY *entry, const char *objectclass)
-{
- const char **values;
- int i;
- if ((!is_valid_entry(entry)) || (objectclass == NULL))
- {
- log_log(LOG_ERR, "myldap_has_objectclass(): invalid argument passed");
- errno = EINVAL;
- return 0;
- }
- values = myldap_get_values(entry, "objectClass");
- if (values == NULL)
- return 0;
- for (i = 0; values[i] != NULL; i++)
- {
- if (strcasecmp(values[i], objectclass) == 0)
- return -1;
- }
- return 0;
-}
-
-#ifdef HAVE_LDAP_PARSE_DEREF_CONTROL
-const char ***myldap_get_deref_values(MYLDAP_ENTRY *entry,
- const char *derefattr, const char *getattr)
-{
- LDAPControl **entryctrls;
- LDAPDerefRes *deref, *d;
- LDAPDerefVal *a;
- int i, pass;
- int rc;
- int found;
- int counts[2];
- size_t sizes[2], size;
- char *buffer = NULL;
- char ***results = NULL;
- rc = ldap_get_entry_controls(entry->search->session->ld, entry->search->msg,
- &entryctrls);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_WARNING, entry->search->session->ld, rc,
- "ldap_get_entry_controls() failed");
- return NULL;
- }
- if (entryctrls == NULL)
- return NULL;
- /* see if we can find a deref control */
- rc = ldap_parse_deref_control(entry->search->session->ld, entryctrls,
- &deref);
- if ((rc != LDAP_SUCCESS) || (deref == NULL))
- {
- if ((rc != LDAP_SUCCESS) && (rc != LDAP_CONTROL_NOT_FOUND))
- myldap_err(LOG_WARNING, entry->search->session->ld, rc,
- "ldap_parse_deref_control() failed");
- /* clear error flag */
- rc = LDAP_SUCCESS;
- if (ldap_set_option(entry->search->session->ld, LDAP_OPT_ERROR_NUMBER,
- &rc) != LDAP_SUCCESS)
- log_log(LOG_WARNING, "failed to clear the error flag");
- ldap_controls_free(entryctrls);
- return NULL;
- }
- /* two passes: one to calculate size, one to store data */
- for (pass=0; pass < 2; pass++)
- {
- /* reset counters and size */
- for (i = 0; i < 2; i++)
- {
- counts[i] = 0;
- sizes[i] = 0;
- }
- /* go over all deref'd attributes and find the one we're looking for */
- for (d = deref; d != NULL; d = d->next)
- if ((d->derefAttr != NULL) && (d->derefVal.bv_val != NULL) &&
- (strcasecmp(derefattr, d->derefAttr) == 0))
- {
- /* we should have one d per original attribute value */
- found = 0;
- /* go over deref'd attribute values to find the ones we're looking for */
- for (a = d->attrVals; a != NULL; a = a->next)
- if ((a->type != NULL) && (a->vals != NULL) &&
- (strcasecmp(getattr, a->type) == 0))
- for (i=0; a->vals[i].bv_val != NULL; i++)
- {
- found = 1;
- if (results == NULL)
- {
- log_log(LOG_DEBUG, "deref %s %s=%s -> %s=%s",
- myldap_get_dn(entry), d->derefAttr, d->derefVal.bv_val,
- a->type, a->vals[i].bv_val);
- counts[0]++;
- sizes[0] += strlen(a->vals[i].bv_val) + 1;
- }
- else
- {
- strcpy(buffer, a->vals[i].bv_val);
- results[0][counts[0]++] = buffer;
- buffer += strlen(buffer) + 1;
- }
- }
- if (!found)
- {
- if (results == NULL)
- {
- log_log(LOG_DEBUG, "no %s deref %s %s=%s", getattr,
- myldap_get_dn(entry), d->derefAttr, d->derefVal.bv_val);
- counts[1]++;
- sizes[1] += strlen(d->derefVal.bv_val) + 1;
- }
- else
- {
- strcpy(buffer, d->derefVal.bv_val);
- results[1][counts[1]++] = buffer;
- buffer += strlen(buffer) + 1;
- }
- }
- }
- /* allocate memory after first pass */
- if (results == NULL)
- {
- size = sizeof(char **) * 3;
- for (i = 0; i < 2; i++)
- size += sizeof(char *) * (counts[i] + 1);
- for (i = 0; i < 2; i++)
- size += sizeof(char) * sizes[i];
- buffer = (char *)malloc(size);
- if (buffer == NULL)
- {
- log_log(LOG_CRIT, "myldap_get_deref_values(): malloc() failed to allocate memory");
- return NULL;
- }
- /* allocate the list of lists */
- results = (void *)buffer;
- buffer += sizeof(char **) * 3;
- /* allocate the lists */
- for (i = 0; i < 2; i++)
- {
- results[i] = (char **)buffer;
- buffer += sizeof(char *) * (counts[i] + 1);
- }
- results[i] = NULL;
- }
- }
- /* NULL terminate the lists */
- results[0][counts[0]] = NULL;
- results[1][counts[1]] = NULL;
- /* free control data */
- ldap_derefresponse_free(deref);
- ldap_controls_free(entryctrls);
- /* store results so we can free it later on */
- for (i = 0; i < MAX_BUFFERS_PER_ENTRY; i++)
- if (entry->buffers[i] == NULL)
- {
- entry->buffers[i] = (void *)results;
- return (const char ***)results;
- }
- /* we found no room to store the values */
- log_log(LOG_ERR, "myldap_get_deref_values() couldn't store results, "
- "increase MAX_BUFFERS_PER_ENTRY");
- free(results);
- return NULL;
-}
-#else /* not HAVE_LDAP_PARSE_DEREF_CONTROL */
-const char ***myldap_get_deref_values(MYLDAP_ENTRY UNUSED(*entry),
- const char UNUSED(*derefattr), const char UNUSED(*getattr))
-{
- return NULL;
-}
-#endif /* not HAVE_LDAP_PARSE_DEREF_CONTROL */
-
-int myldap_escape(const char *src, char *buffer, size_t buflen)
-{
- size_t pos = 0;
- /* go over all characters in source string */
- for (; *src != '\0'; src++)
- {
- /* check if char will fit */
- if ((pos + 4) >= buflen)
- return -1;
- /* do escaping for some characters */
- switch (*src)
- {
- case '*':
- strcpy(buffer + pos, "\\2a");
- pos += 3;
- break;
- case '(':
- strcpy(buffer + pos, "\\28");
- pos += 3;
- break;
- case ')':
- strcpy(buffer + pos, "\\29");
- pos += 3;
- break;
- case '\\':
- strcpy(buffer + pos, "\\5c");
- pos += 3;
- break;
- default:
- /* just copy character */
- buffer[pos++] = *src;
- break;
- }
- }
- /* terminate destination string */
- buffer[pos] = '\0';
- return 0;
-}
-
-int myldap_set_debuglevel(int level)
-{
- int i;
- int rc;
- /* turn on debugging */
- if (level > 1)
- {
-#ifdef LBER_OPT_LOG_PRINT_FILE
- log_log(LOG_DEBUG, "ber_set_option(LBER_OPT_LOG_PRINT_FILE)");
- rc = ber_set_option(NULL, LBER_OPT_LOG_PRINT_FILE, stderr);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_ERR, NULL, rc, "ber_set_option(LBER_OPT_LOG_PRINT_FILE) failed");
- return rc;
- }
-#endif /* LBER_OPT_LOG_PRINT_FILE */
-#ifdef LBER_OPT_DEBUG_LEVEL
- if (level > 2)
- {
- i = -1;
- log_log(LOG_DEBUG, "ber_set_option(LBER_OPT_DEBUG_LEVEL,-1)");
- rc = ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &i);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_ERR, NULL, rc, "ber_set_option(LBER_OPT_DEBUG_LEVEL) failed");
- return rc;
- }
- }
-#endif /* LBER_OPT_DEBUG_LEVEL */
-#ifdef LDAP_OPT_DEBUG_LEVEL
- i = -1;
- log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_DEBUG_LEVEL,-1)");
- rc = ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &i);
- if (rc != LDAP_SUCCESS)
- {
- myldap_err(LOG_ERR, NULL, rc, "ldap_set_option(LDAP_OPT_DEBUG_LEVEL) failed");
- return rc;
- }
-#endif /* LDAP_OPT_DEBUG_LEVEL */
- }
- return LDAP_SUCCESS;
-}
-
-int myldap_passwd(MYLDAP_SESSION *session,
- const char *userdn, const char *oldpassword,
- const char *newpasswd)
-{
- int rc;
- struct berval ber_userdn, ber_oldpassword, ber_newpassword, ber_retpassword;
- /* check parameters */
- if ((session == NULL) || (userdn == NULL) || (newpasswd == NULL))
- {
- log_log(LOG_ERR, "myldap_passwd(): invalid parameter passed");
- errno = EINVAL;
- return LDAP_OTHER;
- }
- /* log the call */
- log_log(LOG_DEBUG, "myldap_passwd(userdn=\"%s\",oldpasswd=%s,newpasswd=\"***\")",
- userdn, oldpassword ? "\"***\"" : "NULL");
- /* translate to ber stuff */
- ber_userdn.bv_val = (char *)userdn;
- ber_userdn.bv_len = strlen(userdn);
- ber_newpassword.bv_val = (char *)newpasswd;
- ber_newpassword.bv_len = strlen(newpasswd);
- ber_retpassword.bv_val = NULL;
- ber_retpassword.bv_len = 0;
- /* perform request */
- log_log(LOG_DEBUG, "myldap_passwd(): try ldap_passwd_s() without old password");
- rc = ldap_passwd_s(session->ld, &ber_userdn, NULL, &ber_newpassword,
- &ber_retpassword, NULL, NULL);
- if (rc != LDAP_SUCCESS)
- myldap_err(LOG_ERR, session->ld, rc, "ldap_passwd_s() without old password failed");
- /* free returned data if needed */
- if (ber_retpassword.bv_val != NULL)
- ldap_memfree(ber_retpassword.bv_val);
- if ((rc != LDAP_SUCCESS) && (oldpassword != NULL))
- {
- /* retry with old password */
- log_log(LOG_DEBUG, "myldap_passwd(): try ldap_passwd_s() with old password");
- ber_oldpassword.bv_val = (char *)oldpassword;
- ber_oldpassword.bv_len = strlen(oldpassword);
- /* perform request */
- rc = ldap_passwd_s(session->ld, &ber_userdn, &ber_oldpassword,
- &ber_newpassword, &ber_retpassword, NULL, NULL);
- if (rc != LDAP_SUCCESS)
- myldap_err(LOG_ERR, session->ld, rc, "ldap_passwd_s() with old password failed");
- /* free returned data if needed */
- if (ber_retpassword.bv_val != NULL)
- ldap_memfree(ber_retpassword.bv_val);
- }
- return rc;
-}
-
-int myldap_modify(MYLDAP_SESSION *session, const char *dn, LDAPMod * mods[])
-{
- if ((session == NULL) || (dn == NULL))
- {
- log_log(LOG_ERR, "myldap_passwd(): invalid parameter passed");
- errno = EINVAL;
- return LDAP_OTHER;
- }
- return ldap_modify_ext_s(session->ld, dn, mods, NULL, NULL);
-}
-
-int myldap_error_message(MYLDAP_SESSION *session, int rc,
- char *buffer, size_t buflen)
-{
- char *msg_diag = NULL;
- if ((session == NULL) || (buffer == NULL) || (buflen <= 0))
- {
- log_log(LOG_ERR, "myldap_error_message(): invalid parameter passed");
- errno = EINVAL;
- return LDAP_OTHER;
- }
- /* clear buffer */
- buffer[0] = '\0';
-#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
- if (session->ld != NULL)
- ldap_get_option(session->ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &msg_diag);
-#endif /* LDAP_OPT_DIAGNOSTIC_MESSAGE */
- /* return msg_diag or generic error message */
- mysnprintf(buffer, buflen - 1, "%s",
- ((msg_diag != NULL) && (msg_diag[0]!='\0')) ?
- msg_diag : ldap_err2string(rc));
- /* free diagnostic message */
- if (msg_diag != NULL)
- ldap_memfree(msg_diag);
- return LDAP_SUCCESS;
-}