|
|
@ -62,6 +62,10 @@ typedef struct { |
|
|
|
ngx_str_t group_attribute; |
|
|
|
ngx_str_t group_attribute; |
|
|
|
ngx_flag_t group_attribute_dn; |
|
|
|
ngx_flag_t group_attribute_dn; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ngx_flag_t ssl_check_cert; |
|
|
|
|
|
|
|
ngx_str_t ssl_ca_dir; |
|
|
|
|
|
|
|
ngx_str_t ssl_ca_file; |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
@ -378,7 +382,13 @@ ngx_http_auth_ldap_ldap_server(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
|
|
|
return NGX_CONF_ERROR; |
|
|
|
return NGX_CONF_ERROR; |
|
|
|
} |
|
|
|
} |
|
|
|
server->connections = i; |
|
|
|
server->connections = i; |
|
|
|
}
|
|
|
|
} else if (ngx_strcmp(value[0].data, "ssl_check_cert") == 0 && ngx_strcmp(value[1].data, "on") == 0) { |
|
|
|
|
|
|
|
server->ssl_check_cert = 1; |
|
|
|
|
|
|
|
} else if (ngx_strcmp(value[0].data, "ssl_ca_dir") == 0) { |
|
|
|
|
|
|
|
server->ssl_ca_dir = value[1]; |
|
|
|
|
|
|
|
} else if (ngx_strcmp(value[0].data, "ssl_ca_file") == 0) { |
|
|
|
|
|
|
|
server->ssl_ca_file = value[1]; |
|
|
|
|
|
|
|
} |
|
|
|
else CONF_MSEC_VALUE(cf,value,server,connect_timeout) |
|
|
|
else CONF_MSEC_VALUE(cf,value,server,connect_timeout) |
|
|
|
else CONF_MSEC_VALUE(cf,value,server,reconnect_timeout) |
|
|
|
else CONF_MSEC_VALUE(cf,value,server,reconnect_timeout) |
|
|
|
else CONF_MSEC_VALUE(cf,value,server,bind_timeout) |
|
|
|
else CONF_MSEC_VALUE(cf,value,server,bind_timeout) |
|
|
@ -1026,7 +1036,7 @@ ngx_http_auth_ldap_close_connection(ngx_http_auth_ldap_connection_t *c) |
|
|
|
c->rctx = NULL; |
|
|
|
c->rctx = NULL; |
|
|
|
if (c->state != STATE_DISCONNECTED) { |
|
|
|
if (c->state != STATE_DISCONNECTED) { |
|
|
|
c->state = STATE_DISCONNECTED; |
|
|
|
c->state = STATE_DISCONNECTED; |
|
|
|
ngx_add_timer(&c->reconnect_event, c->server->reconnect_timeout);
|
|
|
|
ngx_add_timer(&c->reconnect_event, c->server->reconnect_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: Connection scheduled for reconnection in %d ms", c->server->reconnect_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: Connection scheduled for reconnection in %d ms", c->server->reconnect_timeout); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1129,7 +1139,7 @@ ngx_http_auth_ldap_dummy_write_handler(ngx_event_t *wev) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (NGX_OPENSSL) |
|
|
|
#if (NGX_OPENSSL) |
|
|
|
/* Make sure the event hendlers are activated. */ |
|
|
|
/* Make sure the event handlers are activated. */ |
|
|
|
static ngx_int_t |
|
|
|
static ngx_int_t |
|
|
|
ngx_http_auth_ldap_restore_handlers(ngx_connection_t *conn) |
|
|
|
ngx_http_auth_ldap_restore_handlers(ngx_connection_t *conn) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1206,29 +1216,51 @@ ngx_http_auth_ldap_connection_established(ngx_http_auth_ldap_connection_t *c) |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: ldap_sasl_bind() -> msgid=%d", c->msgid); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: ldap_sasl_bind() -> msgid=%d", c->msgid); |
|
|
|
|
|
|
|
|
|
|
|
c->state = STATE_INITIAL_BINDING; |
|
|
|
c->state = STATE_INITIAL_BINDING; |
|
|
|
ngx_add_timer(c->conn.connection->read, c->server->bind_timeout);
|
|
|
|
ngx_add_timer(c->conn.connection->read, c->server->bind_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: bind_timeout=%d", c->server->bind_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: bind_timeout=%d", c->server->bind_timeout); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if (NGX_OPENSSL) |
|
|
|
#if (NGX_OPENSSL) |
|
|
|
static void |
|
|
|
static void |
|
|
|
ngx_http_auth_ldap_ssl_handshake_handler(ngx_connection_t *conn) |
|
|
|
ngx_http_auth_ldap_ssl_handshake_handler(ngx_connection_t *conn, ngx_flag_t validate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ngx_http_auth_ldap_connection_t *c; |
|
|
|
ngx_http_auth_ldap_connection_t *c; |
|
|
|
|
|
|
|
|
|
|
|
c = conn->data; |
|
|
|
c = conn->data; |
|
|
|
|
|
|
|
|
|
|
|
if (conn->ssl->handshaked) { |
|
|
|
if (conn->ssl->handshaked) { |
|
|
|
conn->read->handler = &ngx_http_auth_ldap_read_handler; |
|
|
|
// verify remote certificate
|
|
|
|
ngx_http_auth_ldap_restore_handlers(conn); |
|
|
|
X509 *cert = SSL_get_peer_certificate(conn->ssl->connection); |
|
|
|
ngx_http_auth_ldap_connection_established(c); |
|
|
|
long verified = SSL_get_verify_result(conn->ssl->connection); |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (!validate || (cert && verified == X509_V_OK) ) { // everything fine
|
|
|
|
|
|
|
|
conn->read->handler = &ngx_http_auth_ldap_read_handler; |
|
|
|
|
|
|
|
ngx_http_auth_ldap_restore_handlers(conn); |
|
|
|
|
|
|
|
ngx_http_auth_ldap_connection_established(c); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} else { // smells fishy
|
|
|
|
|
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, |
|
|
|
|
|
|
|
"http_auth_ldap: Remote side presented invalid SSL certificate: error %l, %s", |
|
|
|
|
|
|
|
verified, X509_verify_cert_error_string(verified)); |
|
|
|
|
|
|
|
ngx_http_auth_ldap_close_connection(c); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_auth_ldap: SSL handshake failed"); |
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_auth_ldap: SSL handshake failed"); |
|
|
|
ngx_http_auth_ldap_close_connection(c); |
|
|
|
ngx_http_auth_ldap_close_connection(c); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
|
|
|
ngx_http_auth_ldap_ssl_handshake_validating_handler(ngx_connection_t *conn) |
|
|
|
|
|
|
|
{ ngx_http_auth_ldap_ssl_handshake_handler(conn, 1); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
|
|
|
ngx_http_auth_ldap_ssl_handshake_non_validating_handler(ngx_connection_t *conn) |
|
|
|
|
|
|
|
{ ngx_http_auth_ldap_ssl_handshake_handler(conn, 0); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*ngx_http_auth_ldap_ssl_callback)(ngx_connection_t *conn); |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
static void |
|
|
|
ngx_http_auth_ldap_ssl_handshake(ngx_http_auth_ldap_connection_t *c) |
|
|
|
ngx_http_auth_ldap_ssl_handshake(ngx_http_auth_ldap_connection_t *c) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1243,14 +1275,45 @@ ngx_http_auth_ldap_ssl_handshake(ngx_http_auth_ldap_connection_t *c) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
c->log->action = "SSL handshaking to LDAP server"; |
|
|
|
c->log->action = "SSL handshaking to LDAP server"; |
|
|
|
|
|
|
|
ngx_connection_t *transport = c->conn.connection; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ngx_http_auth_ldap_ssl_callback callback; |
|
|
|
|
|
|
|
if (c->server->ssl_check_cert) { |
|
|
|
|
|
|
|
// load CA certificates: custom ones if specified, default ones instead
|
|
|
|
|
|
|
|
if (c->server->ssl_ca_file.data || c->server->ssl_ca_dir.data) { |
|
|
|
|
|
|
|
int setcode = SSL_CTX_load_verify_locations(transport->ssl->connection->ctx, |
|
|
|
|
|
|
|
(char*)(c->server->ssl_ca_file.data), (char*)(c->server->ssl_ca_dir.data)); |
|
|
|
|
|
|
|
if (setcode != 1) { |
|
|
|
|
|
|
|
unsigned long error_code = ERR_get_error(); |
|
|
|
|
|
|
|
char *error_msg = ERR_error_string(error_code, NULL); |
|
|
|
|
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, |
|
|
|
|
|
|
|
"http_auth_ldap: SSL initialization failed. Could not set custom CA certificate location. " |
|
|
|
|
|
|
|
"Error: %lu, %s", error_code, error_msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int setcode = SSL_CTX_set_default_verify_paths(transport->ssl->connection->ctx); |
|
|
|
|
|
|
|
if (setcode != 1) { |
|
|
|
|
|
|
|
unsigned long error_code = ERR_get_error(); |
|
|
|
|
|
|
|
char *error_msg = ERR_error_string(error_code, NULL); |
|
|
|
|
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, |
|
|
|
|
|
|
|
"http_auth_ldap: SSL initialization failed. Could not use default CA certificate location. " |
|
|
|
|
|
|
|
"Error: %lu, %s", error_code, error_msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// use validating version of next function
|
|
|
|
|
|
|
|
callback = &ngx_http_auth_ldap_ssl_handshake_validating_handler; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// use non-validating version of next function
|
|
|
|
|
|
|
|
callback = &ngx_http_auth_ldap_ssl_handshake_non_validating_handler; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
rc = ngx_ssl_handshake(c->conn.connection); |
|
|
|
rc = ngx_ssl_handshake(transport); |
|
|
|
if (rc == NGX_AGAIN) { |
|
|
|
if (rc == NGX_AGAIN) { |
|
|
|
c->conn.connection->ssl->handler = &ngx_http_auth_ldap_ssl_handshake_handler; |
|
|
|
transport->ssl->handler = callback; |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ngx_http_auth_ldap_ssl_handshake_handler(c->conn.connection); |
|
|
|
(*callback)(transport); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -1451,7 +1514,7 @@ ngx_http_auth_ldap_connect(ngx_http_auth_ldap_connection_t *c) |
|
|
|
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { |
|
|
|
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { |
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_auth_ldap: Unable to connect to LDAP server \"%V\".", |
|
|
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "http_auth_ldap: Unable to connect to LDAP server \"%V\".", |
|
|
|
&addr->name); |
|
|
|
&addr->name); |
|
|
|
ngx_add_timer(&c->reconnect_event, c->server->reconnect_timeout);
|
|
|
|
ngx_add_timer(&c->reconnect_event, c->server->reconnect_timeout); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1462,7 +1525,7 @@ ngx_http_auth_ldap_connect(ngx_http_auth_ldap_connection_t *c) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
conn->write->handler = ngx_http_auth_ldap_connect_handler; |
|
|
|
conn->write->handler = ngx_http_auth_ldap_connect_handler; |
|
|
|
conn->read->handler = ngx_http_auth_ldap_read_handler; |
|
|
|
conn->read->handler = ngx_http_auth_ldap_read_handler; |
|
|
|
ngx_add_timer(conn->read, c->server->connect_timeout);
|
|
|
|
ngx_add_timer(conn->read, c->server->connect_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: connect_timeout=%d.", c->server->connect_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http_auth_ldap: connect_timeout=%d.", c->server->connect_timeout); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1632,7 +1695,7 @@ ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* If we are not starting up a request (ctx->phase != PHASE_START) and we actually already |
|
|
|
* If we are not starting up a request (ctx->phase != PHASE_START) and we actually already |
|
|
|
* sent a request (ctx->iteration > 0) and didn't receive a reply yet (!ctx->replied) we
|
|
|
|
* sent a request (ctx->iteration > 0) and didn't receive a reply yet (!ctx->replied) we |
|
|
|
* ask to be called again at a later time when we hopefully have received a reply. |
|
|
|
* ask to be called again at a later time when we hopefully have received a reply. |
|
|
|
* |
|
|
|
* |
|
|
|
* It is quite possible that we reach this if while not having sent a request yet (ctx->iteration == 0) - |
|
|
|
* It is quite possible that we reach this if while not having sent a request yet (ctx->iteration == 0) - |
|
|
@ -1652,7 +1715,7 @@ ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t |
|
|
|
ctx->server = ((ngx_http_auth_ldap_server_t **) conf->servers->elts)[ctx->server_index]; |
|
|
|
ctx->server = ((ngx_http_auth_ldap_server_t **) conf->servers->elts)[ctx->server_index]; |
|
|
|
ctx->outcome = OUTCOME_UNCERTAIN; |
|
|
|
ctx->outcome = OUTCOME_UNCERTAIN; |
|
|
|
|
|
|
|
|
|
|
|
ngx_add_timer(r->connection->write, ctx->server->request_timeout);
|
|
|
|
ngx_add_timer(r->connection->write, ctx->server->request_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http_auth_ldap: request_timeout=%d",ctx->server->request_timeout); |
|
|
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http_auth_ldap: request_timeout=%d",ctx->server->request_timeout); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -2014,7 +2077,7 @@ ngx_http_auth_ldap_check_bind(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t *c |
|
|
|
ctx->c->msgid); |
|
|
|
ctx->c->msgid); |
|
|
|
ctx->c->state = STATE_BINDING; |
|
|
|
ctx->c->state = STATE_BINDING; |
|
|
|
ctx->iteration++; |
|
|
|
ctx->iteration++; |
|
|
|
|
|
|
|
|
|
|
|
return NGX_AGAIN; |
|
|
|
return NGX_AGAIN; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|