Project

General

Profile

Feature #1248 » lighttpd_trunk.ldap.userdn.patch

The above patch is against the 1.4.x branch, this is the same patch applied to the trunk, adjusting for the one blocking change -- douglas - Anonymous, 2007-06-28 12:55

View differences:

lighttpd-trunk.patched/src/http_auth.c 2007-06-28 14:50:13.000000000 +0200
#ifdef USE_LDAP
LDAP *ldap;
LDAPMessage *lm, *first;
char *dn;
const char *dn;
int ret;
char *attrs[] = { LDAP_NO_ATTRS, NULL };
size_t i;
const char *username_token = username->ptr;
unsigned int token_length = 0;
/* If we don't allow empty passwords, and this one is empty, there's
* no point in continuing. */
if (p->conf.auth_ldap_allow_empty_pw != 1 && pw[0] == '\0')
return -1;
/* for now we stay synchronous */
/*
* 1. connect anonymously (done in plugin init)
* 2. get DN for uid = username
* 3. auth against ldap server
* 4. (optional) check a field
* 5. disconnect
* 1. If we need to find the user DN
* a. connect anonymously (or using configured bind) (done in plugin init)
* b. get DN for uid = username
* 2. auth against ldap server
* 3. disconnect
*
*/
/* check username
*
* we have to protect us againt username which modifies out filter in
* a unpleasant way
* we have to protect us againt usernames which modify our filter or
* user-dn in an unpleasant way. Filters need to have the following
* characters escaped: ['\\', '*', '(', ')']
* Custom DNs are tougher, because the escape list is longer, and
* there are specialized rules for characters at the beginning and
* end of the value. Escaped: [',', '+', '"', '\\', '<', '>', ';']
* Also at the beginning of the string: [' ', '#']
* At the end of the string: [' ']
*/
for (i = 0; i < username->used - 1; i++) {
char c = username->ptr[i];
if (!isalpha(c) &&
!isdigit(c)) {
buffer_copy_string(p->ldap_username, "");
log_error_write(srv, __FILE__, __LINE__, "sbd",
"ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
/* Create a username escaped for the filter first. */
/* LDAP filter escape rules */
for (i = 0; i < username->used - 1; ++i) {
char c = username->ptr[i];
char s[3] = {'\\',c,0};
return -1;
if (('\\' != c) &&
('*' != c) &&
('(' != c) &&
(')' != c)) {
++token_length;
} else {
if (token_length) {
buffer_append_string_len(p->ldap_username, username_token, token_length);
token_length = 0;
}
buffer_append_string(p->ldap_username, s);
username_token = username->ptr + i + 1;
}
}
if (p->conf.auth_ldap_allow_empty_pw != 1 && pw[0] == '\0')
return -1;
/* If there's a token we never added to the buffer */
if (token_length) {
buffer_append_string_len(p->ldap_username, username_token, token_length);
token_length = 0;
}
/* build filter */
buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
buffer_append_string_buffer(p->ldap_filter, username);
buffer_append_string_buffer(p->ldap_filter, p->ldap_username);
buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
if (p->conf.auth_ldap_userdn->used) {
buffer_copy_string(p->ldap_username, "");
/* User-DN escape rules */
for (i = 0; i < username->used - 1; ++i) {
char c = username->ptr[i];
char s[3] = {'\\',c,0};
if ((0 == i) &&
((' ' == c) ||
('#' == c))) {
buffer_copy_string(p->ldap_username, s);
username_token = username->ptr + i + 1;
} else if (((username->used - 2) == i) &&
(' ' == c)) {
if (token_length) {
buffer_append_string_len(p->ldap_username, username_token, token_length);
token_length = 0;
}
buffer_append_string(p->ldap_username, s);
username_token = username->ptr + i + 1;
} else if ((',' != c) &&
('+' != c) &&
('"' != c) &&
('\\' != c) &&
('<' != c) &&
('>' != c) &&
(';' != c)) {
/* 2. */
if (p->conf.ldap == NULL ||
LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
if (auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON)
return -1;
if (LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
++token_length;
} else {
log_error_write(srv, __FILE__, __LINE__, "sssb",
"ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
if (token_length) {
buffer_append_string_len(p->ldap_username, username_token, token_length);
token_length = 0;
}
buffer_append_string(p->ldap_username, s);
username_token = username->ptr + i + 1;
}
}
return -1;
/* If there's a token we never added to the buffer */
if (token_length) {
buffer_append_string_len(p->ldap_username, username_token, token_length);
token_length = 0;
}
/* build userdn */
buffer_copy_string_buffer(p->ldap_userdn, p->conf.ldap_userdn_pre);
buffer_append_string_buffer(p->ldap_userdn, p->ldap_username);
buffer_append_string_buffer(p->ldap_userdn, p->conf.ldap_userdn_post);
dn = p->ldap_userdn->ptr;
}
if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
if (!p->conf.auth_ldap_userdn->used) {
ldap_msgfree(lm);
/* 1b. */
if (p->conf.ldap == NULL ||
LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
if (auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON)
return -1;
if (LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) {
return -1;
}
log_error_write(srv, __FILE__, __LINE__, "sssb",
"ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
return -1;
}
}
if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
ldap_msgfree(lm);
ldap_msgfree(lm);
return -1;
}
return -1;
}
ldap_msgfree(lm);
if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
ldap_msgfree(lm);
/* 3. */
return -1;
}
ldap_msgfree(lm);
}
/* 2. */
if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
return -1;
......
return -1;
}
/* 5. */
/* If we're using the userdn, we haven't applied the filter previously, so
* we'll do it now. */
if (p->conf.auth_ldap_userdn->used) {
if (LDAP_SUCCESS != (ret = ldap_search_s(ldap, dn, LDAP_SCOPE_BASE, p->ldap_filter->ptr, attrs, 0, &lm))) {
log_error_write(srv, __FILE__, __LINE__, "sssb",
"ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
return -1;
}
if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
ldap_msgfree(lm);
return -1;
}
ldap_msgfree(lm);
}
/* 3. */
ldap_unbind_s(ldap);
/* everything worked, good, access granted */
lighttpd-trunk.patched/src/http_auth.h 2007-06-28 14:50:13.000000000 +0200
buffer *auth_ldap_basedn;
buffer *auth_ldap_binddn;
buffer *auth_ldap_bindpw;
buffer *auth_ldap_userdn;
buffer *auth_ldap_filter;
buffer *auth_ldap_cafile;
buffer *auth_ldap_cert;
......
buffer *ldap_filter_pre;
buffer *ldap_filter_post;
buffer *ldap_userdn_pre;
buffer *ldap_userdn_post;
#endif
} mod_auth_plugin_config;
......
#ifdef USE_LDAP
buffer *ldap_filter;
buffer *ldap_username;
buffer *ldap_userdn;
#endif
mod_auth_plugin_config **config_storage;
lighttpd-trunk.patched/src/mod_auth.c 2007-06-28 14:59:39.000000000 +0200
p->auth_user = buffer_init();
#ifdef USE_LDAP
p->ldap_filter = buffer_init();
p->ldap_username = buffer_init();
p->ldap_userdn = buffer_init();
#endif
return p;
......
buffer_free(p->auth_user);
#ifdef USE_LDAP
buffer_free(p->ldap_filter);
buffer_free(p->ldap_username);
buffer_free(p->ldap_userdn);
#endif
if (p->config_storage) {
......
buffer_free(s->auth_ldap_basedn);
buffer_free(s->auth_ldap_binddn);
buffer_free(s->auth_ldap_bindpw);
buffer_free(s->auth_ldap_userdn);
buffer_free(s->auth_ldap_filter);
buffer_free(s->auth_ldap_cafile);
buffer_free(s->auth_ldap_cert);
......
#ifdef USE_LDAP
buffer_free(s->ldap_filter_pre);
buffer_free(s->ldap_filter_post);
buffer_free(s->ldap_userdn_pre);
buffer_free(s->ldap_userdn_post);
if (s->ldap) ldap_unbind_s(s->ldap);
#endif
......
PATCH_OPTION(auth_ldap_basedn);
PATCH_OPTION(auth_ldap_binddn);
PATCH_OPTION(auth_ldap_bindpw);
PATCH_OPTION(auth_ldap_userdn);
PATCH_OPTION(auth_ldap_filter);
PATCH_OPTION(auth_ldap_cafile);
PATCH_OPTION(auth_ldap_cert);
......
PATCH_OPTION(ldap);
PATCH_OPTION(ldap_filter_pre);
PATCH_OPTION(ldap_filter_post);
PATCH_OPTION(ldap_userdn_pre);
PATCH_OPTION(ldap_userdn_post);
#endif
/* skip the first, the global context */
......
PATCH_OPTION(ldap);
PATCH_OPTION(ldap_filter_pre);
PATCH_OPTION(ldap_filter_post);
PATCH_OPTION(ldap_userdn_pre);
PATCH_OPTION(ldap_userdn_post);
#endif
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
PATCH_OPTION(auth_ldap_basedn);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-dn"))) {
PATCH_OPTION(auth_ldap_binddn);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-pw"))) {
PATCH_OPTION(auth_ldap_bindpw);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.user-dn"))) {
PATCH_OPTION(auth_ldap_userdn);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
PATCH_OPTION(auth_ldap_filter);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
......
{ "auth.backend.ldap.starttls", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
{ "auth.backend.ldap.bind-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
{ "auth.backend.ldap.bind-pw", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
{ "auth.backend.ldap.allow-empty-pw", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
{ "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
{ "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
{ "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
{ "auth.backend.ldap.user-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
{ "auth.backend.ldap.allow-empty-pw", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
{ "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
{ "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
{ "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
......
s->auth_ldap_basedn = buffer_init();
s->auth_ldap_binddn = buffer_init();
s->auth_ldap_bindpw = buffer_init();
s->auth_ldap_userdn = buffer_init();
s->auth_ldap_filter = buffer_init();
s->auth_ldap_cafile = buffer_init();
s->auth_ldap_cert = buffer_init();
......
#ifdef USE_LDAP
s->ldap_filter_pre = buffer_init();
s->ldap_filter_post = buffer_init();
s->ldap_userdn_pre = buffer_init();
s->ldap_userdn_post = buffer_init();
s->ldap = NULL;
#endif
......
cv[10].destination = &(s->auth_ldap_starttls);
cv[11].destination = s->auth_ldap_binddn;
cv[12].destination = s->auth_ldap_bindpw;
cv[13].destination = &(s->auth_ldap_allow_empty_pw);
cv[14].destination = s->auth_htdigest_userfile;
cv[15].destination = s->auth_htpasswd_userfile;
cv[16].destination = &(s->auth_debug);
cv[13].destination = s->auth_ldap_userdn;
cv[14].destination = &(s->auth_ldap_allow_empty_pw);
cv[15].destination = s->auth_htdigest_userfile;
cv[16].destination = s->auth_htpasswd_userfile;
cv[17].destination = &(s->auth_debug);
p->config_storage[i] = s;
ca = ((data_config *)srv->config_context->data[i])->value;
......
}
/* 1. */
if (s->auth_ldap_binddn->used) {
if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
/* If the user DN is supplied, we don't need to do an initial bind
* to find it. */
if (s->auth_ldap_userdn->used) {
char *dollar;
/* parse userdn */
if (NULL == (dollar = strchr(s->auth_ldap_userdn->ptr, '$'))) {
log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.user-dn is missing a replace-operator '$'");
return HANDLER_ERROR;
}
} else {
if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
return HANDLER_ERROR;
buffer_copy_string_len(s->ldap_userdn_pre, s->auth_ldap_userdn->ptr, dollar - s->auth_ldap_userdn->ptr);
buffer_copy_string(s->ldap_userdn_post, dollar+1);
} else {
/* 1. */
if (s->auth_ldap_binddn->used) {
if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
return HANDLER_ERROR;
}
} else {
if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
return HANDLER_ERROR;
}
}
}
}
(3-3/4)