/*
- $Id: ldap.c,v 1.1 2009-02-02 11:55:01 franklahm Exp $
- Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
- */
+ $Id: ldap.c,v 1.6 2010-04-22 12:08:14 franklahm Exp $
+ Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include <atalk/logger.h>
#include <atalk/afp.h>
#include <atalk/uuid.h>
-#include <atalk/ldapconfig.h> /* For struct ldap_pref */
+#include <atalk/ldapconfig.h> /* For struct ldap_pref */
typedef enum {
KEEPALIVE = 1
} ldapcon_t;
/********************************************************
- * LDAP config stuff. Filled by etc/afpd/acl_config.c
+ * LDAP config stuff. Filled by libatalk/acl/ldap_config.c
********************************************************/
int ldap_config_valid;
char *ldap_auth_dn;
char *ldap_auth_pw;
char *ldap_userbase;
+int ldap_userscope;
char *ldap_groupbase;
+int ldap_groupscope;
char *ldap_uuid_attr;
char *ldap_name_attr;
char *ldap_group_attr;
{&ldap_auth_dn, "ldap_auth_dn", 0, 0, 0},
{&ldap_auth_pw, "ldap_auth_pw", 0, 0, 0},
{&ldap_userbase, "ldap_userbase", 0, 0, -1},
+ {&ldap_userscope, "ldap_userscope", 1 ,1, -1},
{&ldap_groupbase, "ldap_groupbase", 0, 0, -1},
+ {&ldap_groupscope, "ldap_groupscope", 1 ,1, -1},
{&ldap_uuid_attr, "ldap_uuid_attr", 0, 0, -1},
{&ldap_name_attr, "ldap_name_attr", 0, 0, -1},
{&ldap_group_attr, "ldap_group_attr", 0, 0, -1},
{"ldap_auth_method", "none", LDAP_AUTH_NONE},
{"ldap_auth_method", "simple", LDAP_AUTH_SIMPLE},
{"ldap_auth_method", "sasl", LDAP_AUTH_SASL},
+ {"ldap_userscope", "base", LDAP_SCOPE_BASE},
+ {"ldap_userscope", "one", LDAP_SCOPE_ONELEVEL},
+ {"ldap_userscope", "sub", LDAP_SCOPE_SUBTREE},
+ {"ldap_groupscope", "base", LDAP_SCOPE_BASE},
+ {"ldap_groupscope", "one", LDAP_SCOPE_ONELEVEL},
+ {"ldap_groupscope", "sub", LDAP_SCOPE_SUBTREE},
{NULL, NULL, 0}
};
* Static helper function
********************************************************/
-/*
+/*
* ldap_getattr_fromfilter_withbase_scope():
* conflags: KEEPALIVE
* scope: LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
* you will be dispatching more than one search in a row, then don't set it with the last search.
* You MUST dispatch the queries timely, otherwise the LDAP handle might timeout.
*/
-static int ldap_getattr_fromfilter_withbase_scope( const char *searchbase,
- const char *filter,
- char *attributes[],
- int scope,
- ldapcon_t conflags,
- char **result) {
+static int ldap_getattr_fromfilter_withbase_scope( const char *searchbase,
+ const char *filter,
+ char *attributes[],
+ int scope,
+ ldapcon_t conflags,
+ char **result) {
int ret = 0;
int ldaperr;
+ int retrycount = 0;
int desired_version = LDAP_VERSION3;
static int ldapconnected = 0;
static LDAP *ld = NULL;
char **attribute_values;
struct timeval timeout;
-// LOG(log_debug, logtype_afpd,"ldap_getattr_fromfilter_withbase_scope: BEGIN");
+ LOG(log_maxdebug, logtype_afpd,"ldap_getattr_fromfilter_withbase_scope: BEGIN");
timeout.tv_sec = 3;
timeout.tv_usec = 0;
/* init LDAP if necessary */
+retry:
if (!ldapconnected) {
-// LOG(log_debug, logtype_default, "ldap_getattr_fromfilter_withbase_scope: LDAP server: \'%s\'", ldap_server);
- if ((ld = ldap_init(ldap_server, LDAP_PORT)) == NULL ) {
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_init error");
- return -1;
- }
- if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != 0) {
- /* LDAP_OPT_SUCCESS is not in the proposed standard, so we check for 0
- http://tools.ietf.org/id/draft-ietf-ldapext-ldap-c-api-05.txt */
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_set_option failed!");
- ret = -1;
- goto cleanup;
- }
+ LOG(log_maxdebug, logtype_default, "ldap_getattr_fromfilter_withbase_scope: LDAP server: \"%s\"",
+ ldap_server);
+ if ((ld = ldap_init(ldap_server, LDAP_PORT)) == NULL ) {
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_init error");
+ return -1;
+ }
+ if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != 0) {
+ /* LDAP_OPT_SUCCESS is not in the proposed standard, so we check for 0
+ http://tools.ietf.org/id/draft-ietf-ldapext-ldap-c-api-05.txt */
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_set_option failed!");
+ ret = -1;
+ goto cleanup;
+ }
}
/* connect */
if (!ldapconnected) {
- if (LDAP_AUTH_NONE == ldap_auth_method) {
- if (ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != LDAP_SUCCESS ) {
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_bind failed!");
- LOG(log_error, logtype_default, "ldap_auth_method: \'%d\'", ldap_auth_method);
- return -1;
- }
- ldapconnected = 1;
-
- } else if (LDAP_AUTH_SIMPLE == ldap_auth_method) {
- if (ldap_bind_s(ld, ldap_auth_dn, ldap_auth_pw, ldap_auth_method) != LDAP_SUCCESS ) {
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_bind failed!");
- LOG(log_error, logtype_default, "ldap_auth_dn: \'%s\', ldap_auth_pw: \'%s\', ldap_auth_method: \'%d\'",
- ldap_auth_dn, ldap_auth_pw, ldap_auth_method);
- return -1;
- }
- ldapconnected = 1;
- }
+ if (LDAP_AUTH_NONE == ldap_auth_method) {
+ if (ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != LDAP_SUCCESS ) {
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_bind failed!");
+ LOG(log_error, logtype_default, "ldap_auth_method: \'%d\'", ldap_auth_method);
+ return -1;
+ }
+ ldapconnected = 1;
+
+ } else if (LDAP_AUTH_SIMPLE == ldap_auth_method) {
+ if (ldap_bind_s(ld, ldap_auth_dn, ldap_auth_pw, ldap_auth_method) != LDAP_SUCCESS ) {
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_bind failed!");
+ LOG(log_error, logtype_default, "ldap_auth_dn: \'%s\', ldap_auth_pw: \'%s\', ldap_auth_method: \'%d\'",
+ ldap_auth_dn, ldap_auth_pw, ldap_auth_method);
+ return -1;
+ }
+ ldapconnected = 1;
+ }
}
-// LOG(log_debug, logtype_afpd,"LDAP start search: base: %s, filter: %s, attr: %s", searchbase, filter, attributes[0]);
+ LOG(log_maxdebug, logtype_afpd, "LDAP start search: base: %s, filter: %s, attr: %s",
+ searchbase, filter, attributes[0]);
/* start LDAP search */
ldaperr = ldap_search_st(ld, searchbase, scope, filter, attributes, 0, &timeout, &msg);
+ LOG(log_maxdebug, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_search_st returned: %s, %u",
+ ldap_err2string(ldaperr), ldaperr);
if (ldaperr != LDAP_SUCCESS) {
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_search_st failed: %s", ldap_err2string(ldaperr));
+ if (retrycount ==1)
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: ldap_search_st failed: %s", ldap_err2string(ldaperr));
ret = -1;
goto cleanup;
}
/* parse search result */
-// LOG(log_debug, logtype_default, "ldap_getuuidfromname: got %d entries from ldap search", ldap_count_entries(ld, msg));
+ LOG(log_maxdebug, logtype_default, "ldap_getuuidfromname: got %d entries from ldap search",
+ ldap_count_entries(ld, msg));
if (ldap_count_entries(ld, msg) != 1) {
ret = -1;
goto cleanup;
}
+
entry = ldap_first_entry(ld, msg);
if (entry == NULL) {
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: error in ldap_first_entry");
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: error in ldap_first_entry");
ret = -1;
goto cleanup;
}
attribute_values = ldap_get_values(ld, entry, attributes[0]);
if (attribute_values == NULL) {
- LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: error in ldap_get_values");
+ LOG(log_error, logtype_default, "ldap_getattr_fromfilter_withbase_scope: error in ldap_get_values");
ret = -1;
goto cleanup;
}
-// LOG(log_debug, logtype_afpd,"LDAP Search result: %s: %s", attributes[0], attribute_values[0]);
+ LOG(log_maxdebug, logtype_afpd,"LDAP Search result: %s: %s",
+ attributes[0], attribute_values[0]);
/* allocate place for uuid as string */
*result = calloc( 1, strlen(attribute_values[0]) + 1);
/* FIXME: is there another way to free entry ? */
while (entry != NULL)
- entry = ldap_next_entry(ld, entry);
+ entry = ldap_next_entry(ld, entry);
cleanup:
- if(msg)
- ldap_msgfree(msg);
- if(ld) {
- if ((ldapconnected && !(conflags & KEEPALIVE)) || (*result != NULL)) {
- ldapconnected = 0; /* regardless of unbind errors */
-// LOG(log_debug, logtype_default,"LDAP unbind!");
- if (ldap_unbind_s(ld) != 0) {
- LOG(log_error, logtype_default, "ldap_unbind_s: %s\n", ldap_err2string(ldaperr));
- return -1;
- }
- }
+ if (msg)
+ ldap_msgfree(msg);
+ if (ld) {
+ if (ldapconnected
+ && ( !(conflags & KEEPALIVE)
+ ||
+ ((ret == -1) && (ldaperr != LDAP_SUCCESS))) /* ie ldapsearch got 0 results */
+ ) {
+
+ ldapconnected = 0; /* regardless of unbind errors */
+ LOG(log_maxdebug, logtype_default,"LDAP unbind");
+ if (ldap_unbind_s(ld) != 0) {
+ LOG(log_error, logtype_default, "ldap_unbind_s: %s\n", ldap_err2string(ldaperr));
+ return -1;
+ }
+ retrycount++;
+ if (retrycount < 2)
+ goto retry;
+ }
}
return ret;
}
-/********************************************************
+/********************************************************
* Interface
********************************************************/
/* make filter */
if (type == UUID_GROUP)
- ldap_attr = ldap_group_attr;
+ ldap_attr = ldap_group_attr;
else /* type hopefully == UUID_USER */
- ldap_attr = ldap_name_attr;
+ ldap_attr = ldap_name_attr;
len = snprintf( filter, 256, "%s=%s", ldap_attr, name);
if (len >= 256 || len == -1) {
- LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter error:%d, \"%s\"", len, filter);
- return -1;
- }
-
+ LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter error:%d, \"%s\"", len, filter);
+ return -1;
+ }
if (type == UUID_GROUP) {
- ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, LDAP_SCOPE_ONELEVEL, KEEPALIVE, uuid_string);
+ ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, ldap_groupscope, KEEPALIVE, uuid_string);
} else { /* type hopefully == UUID_USER */
- ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, LDAP_SCOPE_ONELEVEL, 0, uuid_string);
+ ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, ldap_userscope, KEEPALIVE, uuid_string);
}
return ret;
}
int ldap_getnamefromuuid( char *uuidstr, char **name, uuidtype_t *type) {
int ret;
int len;
- char filter[256]; /* this should really be enough. we dont want to malloc everything! */
+ char filter[256]; /* this should really be enough. we dont want to malloc everything! */
char *attributes[] = { NULL, NULL};
/* make filter */
len = snprintf( filter, 256, "%s=%s", ldap_uuid_attr, uuidstr);
if (len >= 256 || len == -1) {
- LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter overflow:%d, \"%s\"", len, filter);
- return -1;
- }
+ LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter overflow:%d, \"%s\"", len, filter);
+ return -1;
+ }
/* search groups first. group acls are probably used more often */
attributes[0] = ldap_group_attr;
- ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, LDAP_SCOPE_ONELEVEL, KEEPALIVE, name);
+ ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, ldap_groupscope, KEEPALIVE, name);
if (ret == 0) {
- *type = UUID_GROUP;
- return 0;
+ *type = UUID_GROUP;
+ return 0;
}
attributes[0] = ldap_name_attr;
- ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, LDAP_SCOPE_ONELEVEL, 0, name);
+ ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, ldap_userscope, KEEPALIVE, name);
if (ret == 0) {
- *type = UUID_USER;
- return 0;
+ *type = UUID_USER;
+ return 0;
}
return ret;
}
-