diff --git a/src/ldapauth.c b/src/ldapauth.c index 7b785d1..b67756c 100644 --- a/src/ldapauth.c +++ b/src/ldapauth.c @@ -9,20 +9,22 @@ #include "config.h" +enum { bufsize = 1024 }; + +/** shared connection, used for searching users and + * comparing their passwords if mode set to 'compare' + * @returns 0 on success, 1 on error + */ +LDAP *ld = NULL; + int -check_against_ldap(oal_config_t * const config, - const char * const username, - const char * const password) +oal_connect(oal_config_t * const config) { - enum { bufsize = 1024 }; + const short int ldapver = LDAP_VERSION3; + const short int sizelimit = 5; struct timeval tv = { 30, 0 }; - short int tmp; - LDAP *ld = NULL; - LDAPMessage *res = NULL; - LDAPMessage *entry = NULL; char err[bufsize]; - char *searchattr[] = { (char *) LDAP_NO_ATTRS, NULL }; - int rc; + int rc = 0; if ((rc = ldap_initialize(&ld, config->bindurls)) != LDAP_SUCCESS) { snprintf(err, bufsize, "can't connnect to ldap server(s): %s", strerror(errno)); @@ -33,62 +35,91 @@ check_against_ldap(oal_config_t * const config, tv.tv_sec = config->bindtimeout; /* hardcoded options */ - tmp = LDAP_VERSION3; - if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &tmp) != LDAP_OPT_SUCCESS) { + if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapver) != LDAP_OPT_SUCCESS) { snprintf(err, bufsize, "can't set ldap protocol version"); - goto error_opts; + goto error; } - tmp = 5; - if (ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &tmp) != LDAP_OPT_SUCCESS) { + if (ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) { snprintf(err, bufsize, "can't set max results limit"); - goto error_opts; + goto error; } /* timeouts */ if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv) != LDAP_OPT_SUCCESS) { snprintf(err, bufsize, "can't set network timeout: %d", config->bindtimeout); - goto error_opts; + goto error; } if (ldap_set_option(ld, LDAP_OPT_TIMEOUT, &tv) != LDAP_OPT_SUCCESS) { snprintf(err, bufsize, "can't set search timeout: %d", config->bindtimeout); - goto error_opts; + goto error; } /* TODO: hardcoded */ if (ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) != LDAP_OPT_SUCCESS) { snprintf(err, bufsize, "can't set follow referrals to 'off'"); - goto error_opts; + goto error; } /* required */ if (ldap_set_option(ld, LDAP_OPT_DEFBASE, config->basedn) != LDAP_OPT_SUCCESS) { snprintf(err, bufsize, "can't set searchbase: %s", config->basedn); - goto error_opts; + goto error; } if((rc = ldap_simple_bind_s(ld, config->binddn, config->bindpass)) != LDAP_SUCCESS) { snprintf(err, bufsize, "can't bind to ldap server: %s", ldap_err2string(rc)); - goto error_opts; + goto error; } + return 0; /* success */ + + error: + config->error = strndup(err, bufsize); + return 1; +} + +/** + * @returns 1 if user pass the check, 0 on password mismatch and -1 on error + */ +int +oal_check_cred(oal_config_t * const config, + const char * const username, + const char * const password) +{ + LDAPMessage *res = NULL; /* whole search result */ + LDAPMessage *msg = NULL; /* first message from search result */ + char *searchattr[] = { (char *) LDAP_NO_ATTRS, NULL }; + char *udn = NULL; /* DN of found user */ + char err[bufsize]; + int rc = 0; + + if (!ld && !oal_connect(config)) + return -1; /* error text already set inside oal_connect() */ + rc = ldap_search_s(ld, config->basedn, LDAP_SCOPE_SUBTREE, config->userfilter, searchattr, 1, &res); if (rc != LDAP_SUCCESS) { - ; + snprintf(err, bufsize, "ldap search failed: %s", ldap_err2string(rc)); + goto error; /* TODO */ } - while (1) { - if ((ldap_simple_bind_s(ld, NULL, password)) != LDAP_SUCCESS) { - } + if (ldap_count_messages(ld, res) <= 0) { + ldap_msgfree(res); + return 0; /* no such user or error */ } - if (res) { - ldap_msgfree(res); - res = NULL; + if ((msg = ldap_first_message(ld, res)) == NULL) { + snprintf(err, bufsize, "ldap search found something, but can't get result"); + goto error; } - if (ld) - ldap_unbind(ld); + if ((udn = ldap_get_dn(ld, msg)) == NULL) { + snprintf(err, bufsize, "can't get DN of found user"); + goto error; + } - return 0; + return 1; - error_opts: + error: + if (res) ldap_msgfree(res); + if (msg) ldap_msgfree(msg); + if (udn) ldap_memfree(udn); config->error = strndup(err, bufsize); - return 1; + return -1; }