Allow specifying the full user DN to avoid searching the LDAP

The configuration can now contain a directive like this
  require valid_user cn=$remote_user,dc=example,dc=com
which will result in the bind as the respective user to be the
only command sent to the server, skipping the search request.
main
Jiri Hruska 12 years ago
parent a043544e2d
commit bd4959918c
  1. 84
      ngx_http_auth_ldap_module.c

@ -43,6 +43,7 @@ typedef struct {
ngx_array_t *require_group; /* array of ngx_http_complex_value_t */ ngx_array_t *require_group; /* array of ngx_http_complex_value_t */
ngx_array_t *require_user; /* array of ngx_http_complex_value_t */ ngx_array_t *require_user; /* array of ngx_http_complex_value_t */
ngx_flag_t require_valid_user; ngx_flag_t require_valid_user;
ngx_http_complex_value_t require_valid_user_dn;
ngx_flag_t satisfy_all; ngx_flag_t satisfy_all;
} ngx_http_auth_ldap_server_t; } ngx_http_auth_ldap_server_t;
@ -373,14 +374,20 @@ static char *
ngx_http_auth_ldap_parse_require(ngx_conf_t *cf, ngx_http_auth_ldap_server_t *server) { ngx_http_auth_ldap_parse_require(ngx_conf_t *cf, ngx_http_auth_ldap_server_t *server) {
ngx_str_t *value; ngx_str_t *value;
ngx_http_complex_value_t* rule = NULL; ngx_http_complex_value_t* target = NULL;
ngx_http_compile_complex_value_t ccv; ngx_http_compile_complex_value_t ccv;
value = cf->args->elts; value = cf->args->elts;
if (ngx_strcmp(value[1].data, "valid_user") == 0) { if (ngx_strcmp(value[1].data, "valid_user") == 0) {
server->require_valid_user = 1; server->require_valid_user = 1;
if (cf->args->nelts < 3) {
return NGX_CONF_OK; return NGX_CONF_OK;
}
if (server->require_valid_user_dn.value.data != NULL) {
return "is duplicate";
}
target = &server->require_valid_user_dn;
} else if (ngx_strcmp(value[1].data, "user") == 0) { } else if (ngx_strcmp(value[1].data, "user") == 0) {
if (server->require_user == NULL) { if (server->require_user == NULL) {
server->require_user = ngx_array_create(cf->pool, 4, sizeof(ngx_http_complex_value_t)); server->require_user = ngx_array_create(cf->pool, 4, sizeof(ngx_http_complex_value_t));
@ -388,7 +395,7 @@ ngx_http_auth_ldap_parse_require(ngx_conf_t *cf, ngx_http_auth_ldap_server_t *se
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
} }
rule = ngx_array_push(server->require_user); target = ngx_array_push(server->require_user);
} else if (ngx_strcmp(value[1].data, "group") == 0) { } else if (ngx_strcmp(value[1].data, "group") == 0) {
if (server->require_group == NULL) { if (server->require_group == NULL) {
server->require_group = ngx_array_create(cf->pool, 4, sizeof(ngx_http_complex_value_t)); server->require_group = ngx_array_create(cf->pool, 4, sizeof(ngx_http_complex_value_t));
@ -396,17 +403,17 @@ ngx_http_auth_ldap_parse_require(ngx_conf_t *cf, ngx_http_auth_ldap_server_t *se
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
} }
rule = ngx_array_push(server->require_group); target = ngx_array_push(server->require_group);
} }
if (rule == NULL) { if (target == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf; ccv.cf = cf;
ccv.value = &value[2]; ccv.value = &value[2];
ccv.complex_value = rule; ccv.complex_value = target;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
@ -560,7 +567,8 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
int rc; int rc;
LDAP *ld; LDAP *ld;
LDAPMessage *searchResult; LDAPMessage *searchResult;
char *dn; char* ldn = NULL;
ngx_str_t dn;
u_char *p, *filter; u_char *p, *filter;
ngx_http_complex_value_t *value; ngx_http_complex_value_t *value;
ngx_uint_t i; ngx_uint_t i;
@ -593,13 +601,22 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
} }
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: Bind successful", NULL); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: Bind successful", NULL);
if (server->require_valid_user_dn.value.data != NULL) {
// Construct user DN
if (ngx_http_complex_value(r, &server->require_valid_user_dn, &dn) != NGX_OK) {
ldap_unbind_s(ld);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
} else {
/// Create filter for search users by uid /// Create filter for search users by uid
filter = ngx_pcalloc( filter = ngx_pcalloc(
r->pool, r->pool,
(ludpp->lud_filter != NULL ? ngx_strlen(ludpp->lud_filter) : ngx_strlen("(objectClass=*)")) + ngx_strlen("(&(=))") + ngx_strlen(ludpp->lud_attrs[0]) (ludpp->lud_filter != NULL ? ngx_strlen(ludpp->lud_filter) : ngx_strlen("(objectClass=*)")) +
+ r->headers_in.user.len + 1); ngx_strlen("(&(=))") + ngx_strlen(ludpp->lud_attrs[0]) + r->headers_in.user.len + 1);
p = ngx_sprintf(filter, "(&%s(%s=%V))", ludpp->lud_filter != NULL ? ludpp->lud_filter : "(objectClass=*)", ludpp->lud_attrs[0], &r->headers_in.user); p = ngx_sprintf(filter, "(&%s(%s=%V))",
ludpp->lud_filter != NULL ? ludpp->lud_filter : "(objectClass=*)",
ludpp->lud_attrs[0], &r->headers_in.user);
*p = 0; *p = 0;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: filter %s", (const char*) filter); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: filter %s", (const char*) filter);
@ -615,9 +632,20 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
} }
if (ldap_count_entries(ld, searchResult) > 0) { if (ldap_count_entries(ld, searchResult) > 0) {
dn = ldap_get_dn(ld, searchResult); ldn = ldap_get_dn(ld, searchResult);
if (dn != NULL) { }
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: result DN %s", dn); ldap_msgfree(searchResult);
if (!ldn) {
ldap_unbind_s(ld);
return 0;
}
dn.data = (u_char*) ldn;
dn.len = ngx_strlen(ldn);
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: result DN %V", &dn);
/// Check require user /// Check require user
if (server->require_user != NULL) { if (server->require_user != NULL) {
@ -625,22 +653,20 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
for (i = 0; i < server->require_user->nelts; i++) { for (i = 0; i < server->require_user->nelts; i++) {
ngx_str_t val; ngx_str_t val;
if (ngx_http_complex_value(r, &value[i], &val) != NGX_OK) { if (ngx_http_complex_value(r, &value[i], &val) != NGX_OK) {
ldap_memfree(dn); ldap_memfree(ldn);
ldap_msgfree(searchResult);
ldap_unbind_s(ld); ldap_unbind_s(ld);
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: compare with: %V", &val); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: compare with: %V", &val);
if (ngx_strncmp(val.data, dn, val.len) == 0) { if (val.len == dn.len && ngx_memcmp(val.data, dn.data, val.len) == 0) {
pass = 1; pass = 1;
if (server->satisfy_all == 0) { if (server->satisfy_all == 0) {
break; break;
} }
} else { } else {
if (server->satisfy_all == 1) { if (server->satisfy_all == 1) {
ldap_memfree(dn); ldap_memfree(ldn);
ldap_msgfree(searchResult);
ldap_unbind_s(ld); ldap_unbind_s(ld);
return 0; return 0;
} }
@ -651,34 +677,30 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
/// Check require group /// Check require group
if (server->require_group != NULL) { if (server->require_group != NULL) {
if (server->group_attribute_dn == 1) { if (server->group_attribute_dn == 1) {
bvalue.bv_val = dn; bvalue.bv_val = (char*) dn.data;
bvalue.bv_len = ngx_strlen(dn); bvalue.bv_len = dn.len;
} else { } else {
bvalue.bv_val = (char*) r->headers_in.user.data; bvalue.bv_val = (char*) r->headers_in.user.data;
bvalue.bv_len = r->headers_in.user.len; bvalue.bv_len = r->headers_in.user.len;
} }
value = server->require_group->elts; value = server->require_group->elts;
for (i = 0; i < server->require_group->nelts; i++) { for (i = 0; i < server->require_group->nelts; i++) {
ngx_str_t val; ngx_str_t val;
if (ngx_http_complex_value(r, &value[i], &val) != NGX_OK) { if (ngx_http_complex_value(r, &value[i], &val) != NGX_OK) {
ldap_memfree(dn); ldap_memfree(ldn);
ldap_msgfree(searchResult);
ldap_unbind_s(ld); ldap_unbind_s(ld);
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: group compare with: %V", &val); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "LDAP: group compare with: %V", &val);
rc = ldap_compare_ext_s(ld, (const char*) val.data, (const char*) server->group_attribute.data, rc = ldap_compare_ext_s(ld, (const char*) val.data, (const char*) server->group_attribute.data,
&bvalue, NULL, NULL); &bvalue, NULL, NULL);
/*if (rc != LDAP_COMPARE_TRUE && rc != LDAP_COMPARE_FALSE && rc != LDAP_NO_SUCH_ATTRIBUTE ) { /*if (rc != LDAP_COMPARE_TRUE && rc != LDAP_COMPARE_FALSE && rc != LDAP_NO_SUCH_ATTRIBUTE) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_search_ext_s: %d, %s", rc, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_search_ext_s: %d, %s", rc,
ldap_err2string(rc)); ldap_err2string(rc));
ldap_memfree(dn); ldap_memfree(ldn);
ldap_msgfree(searchResult);
ldap_unbind_s(ld); ldap_unbind_s(ld);
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
}*/ }*/
@ -698,9 +720,9 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
} }
/// Check valid user /// Check valid user
if ( pass != 0 || (server->require_valid_user == 1 && server->satisfy_all == 0 && pass == 0)) { if (pass != 0 || (server->require_valid_user == 1 && server->satisfy_all == 0 && pass == 0)) {
/// Bind user to the server /// Bind user to the server
rc = ldap_simple_bind_s(ld, dn, (const char *) r->headers_in.passwd.data); rc = ldap_simple_bind_s(ld, (const char *) dn.data, (const char *) r->headers_in.passwd.data);
if (rc != LDAP_SUCCESS) { if (rc != LDAP_SUCCESS) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_simple_bind_s error: %d, %s", rc, ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "LDAP: ldap_simple_bind_s error: %d, %s", rc,
ldap_err2string(rc)); ldap_err2string(rc));
@ -711,11 +733,7 @@ static ngx_int_t ngx_http_auth_ldap_authenticate_against_server(ngx_http_request
} }
} }
} ldap_memfree(ldn);
ldap_memfree(dn);
}
ldap_msgfree(searchResult);
ldap_unbind_s(ld); ldap_unbind_s(ld);
return pass; return pass;

Loading…
Cancel
Save