diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2014-11-28 17:29:41 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2014-11-28 17:29:41 -0500 |
commit | d90f3a3da924ea9074b3c4eecb99dfef1cd9899c (patch) | |
tree | 72732881489344cb1ca6fd3d2b0fcb8eeaf905a2 | |
parent | 70852a24b6a17727e79cf627aa918a4664e50e38 (diff) |
no more myldap
-rw-r--r-- | nslcd/Makefile.am | 1 | ||||
-rw-r--r-- | nslcd/common.h | 4 | ||||
-rw-r--r-- | nslcd/myldap.c | 2028 |
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(¤t_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; -} |