@ -29,10 +29,6 @@
# include <ngx_http.h>
# include <ldap.h>
typedef struct {
ngx_str_t passwd ;
} ngx_http_auth_ldap_ctx_t ;
typedef struct {
ngx_str_t username ;
ngx_str_t password ;
@ -47,7 +43,7 @@ typedef struct {
typedef struct {
LDAPURLDesc * ludpp ;
ngx_str_t url ;
ngx_str_t realm ;
ngx_str_t alias ;
ngx_str_t bind_dn ;
ngx_str_t bind_dn_passwd ;
@ -59,89 +55,73 @@ typedef struct {
ngx_array_t * require_user ; /* array of ngx_ldap_require_t */
ngx_flag_t require_valid_user ;
ngx_flag_t satisfy_all ;
} ngx_http_auth_ldap_loc_conf_t ;
} ngx_ldap_server ;
static char * ngx_http_auth_ldap_url ( ngx_conf_t * , ngx_command_t * , void * ) ;
static char * ngx_http_auth_ldap_satisfy ( ngx_conf_t * , ngx_command_t * , void * ) ;
static char * ngx_http_auth_ldap_require ( ngx_conf_t * , ngx_command_t * , void * ) ;
typedef struct {
ngx_str_t realm ;
ngx_array_t * servers ;
} ngx_http_auth_ldap_loc_conf_t ;
typedef struct {
ngx_array_t * servers ; /* array of ngx_ldap_server */
ngx_hash_t srv ;
} ngx_http_auth_ldap_conf_t ;
static void * ngx_http_auth_ldap_create_conf ( ngx_conf_t * cf ) ;
static char * ngx_http_auth_ldap_ldap_server_block ( ngx_conf_t * cf , ngx_command_t * cmd , void * conf ) ;
static char * ngx_http_auth_ldap_parse_url ( ngx_conf_t * cf , ngx_ldap_server * server ) ;
static char * ngx_http_auth_ldap_parse_require ( ngx_conf_t * cf , ngx_ldap_server * server ) ;
static char * ngx_http_auth_ldap_parse_satisfy ( ngx_conf_t * cf , ngx_ldap_server * server ) ;
static char * ngx_http_auth_ldap_ldap_server ( ngx_conf_t * cf , ngx_command_t * dummy , void * conf ) ;
static ngx_int_t ngx_http_auth_ldap_handler ( ngx_http_request_t * r ) ;
static ngx_int_t ngx_http_auth_ldap_init ( ngx_conf_t * cf ) ;
static void * ngx_http_auth_basic_create_loc_conf ( ngx_conf_t * ) ;
static char * ngx_http_auth_ldap_merge_loc_conf ( ngx_conf_t * , void * , void * ) ;
static ngx_int_t ngx_http_auth_ldap_authenticate_against_server ( ngx_http_request_t * r , ngx_ldap_server * server ,
ngx_ldap_userinfo * uinfo , ngx_http_auth_ldap_loc_conf_t * conf ) ;
static ngx_int_t ngx_http_auth_ldap_set_realm ( ngx_http_request_t * r , ngx_str_t * realm ) ;
static ngx_ldap_userinfo * ngx_http_auth_ldap_get_user_info ( ngx_http_request_t * ) ;
static ngx_int_t ngx_http_auth_ldap_authenticate ( ngx_http_request_t * , ngx_http_auth_ldap_ctx_t * , ngx_str_t * ,
ngx_http_auth_ldap_loc_conf_t * ) ;
static ngx_int_t ngx_http_auth_ldap_authenticate ( ngx_http_request_t * r , ngx_http_auth_ldap_loc_conf_t * conf ,
ngx_http_auth_ldap_conf_t * mconf ) ;
static char * ngx_http_auth_ldap ( ngx_conf_t * cf , void * post , void * data ) ;
static ngx_conf_post_handler_pt ngx_http_auth_ldap_p = ngx_http_auth_ldap ;
static ngx_command_t ngx_http_auth_ldap_commands [ ] = {
{
ngx_string ( " auth_ldap " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1 ,
ngx_conf_set_str_slot ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , realm ) ,
& ngx_http_auth_ldap_p } ,
{
ngx_string ( " auth_ldap_url " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1 ,
ngx_http_auth_ldap_url ,
NGX_HTTP_LOC_CONF_OFFSET ,
ngx_string ( " ldap_server " ) ,
NGX_HTTP_MAIN_CONF | NGX_CONF_BLOCK | NGX_CONF_TAKE1 ,
ngx_http_auth_ldap_ldap_server_block ,
NGX_HTTP_MAIN_CONF_OFFSET ,
0 ,
NULL } ,
NULL
} ,
{
ngx_string ( " auth_ldap_binddn " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1 ,
ngx_conf_set_str_slot ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , bind_dn ) ,
NULL } ,
{
ngx_string ( " auth_ldap_binddn_passwd " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1 ,
ngx_conf_set_str_slot ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , bind_dn_passwd ) ,
NULL } ,
{
ngx_string ( " auth_ldap_require " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE12 ,
ngx_http_auth_ldap_require ,
NGX_HTTP_LOC_CONF_OFFSET ,
0 ,
NULL } ,
{
ngx_string ( " auth_ldap_satisfy " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1 ,
ngx_http_auth_ldap_satisfy ,
NGX_HTTP_LOC_CONF_OFFSET ,
0 ,
NULL } ,
{
ngx_string ( " auth_ldap_group_attribute " ) ,
ngx_string ( " auth_ldap " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1 ,
ngx_conf_set_str_slot ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , group_attribute ) ,
NULL } ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , realm ) ,
& ngx_http_auth_ldap_p
} ,
{
ngx_string ( " auth_ldap_group_attribute_is_dn " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_FLAG ,
ngx_conf_set_flag _slot ,
ngx_string ( " auth_ldap_servers " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_TAKE1234 | NGX_CONF_TAKE5 | NGX_CONF_TAKE6 | NGX_CONF_TAKE7 ,
ngx_conf_set_str_array_slot ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , group_attribute_dn ) ,
NULL } ,
offsetof ( ngx_http_auth_ldap_loc_conf_t , servers ) ,
NULL
} ,
ngx_null_command
} ;
static ngx_http_module_t ngx_http_auth_ldap_module_ctx = {
NULL , /* preconfiguration */
ngx_http_auth_ldap_init , /* postconfiguration */
NULL , /* create main configuration */
ngx_http_auth_ldap_create_conf , /* create main configuration */
NULL , /* init main configuration */
NULL , /* create server configuration */
NULL , /* merge server configuration */
NULL , //ngx_http_auth_ldap_create_server_conf, /* create server configuration */
NULL , //ngx_http_auth_ldap_merge_server_conf, /* merge server configuration */
ngx_http_auth_basic_create_loc_conf , /* create location configuration */
ngx_http_auth_ldap_merge_loc_conf /* merge location configuration */
} ;
@ -161,15 +141,142 @@ ngx_module_t ngx_http_auth_ldap_module = {
NGX_MODULE_V1_PADDING /**/
} ;
/**
* Reads ldap_server block and sets ngx_http_auth_ldap_ldap_server as a handler of each conf value
*/
static char *
ngx_http_auth_ldap_ldap_server_block ( ngx_conf_t * cf , ngx_command_t * cmd , void * conf )
{
char * rv ;
ngx_str_t * value , name ;
ngx_conf_t save ;
ngx_ldap_server server , * s ;
ngx_http_auth_ldap_conf_t * cnf = conf ;
value = cf - > args - > elts ;
name = value [ 1 ] ;
if ( ngx_strlen ( name . data ) = = 0 ) {
ngx_conf_log_error ( NGX_LOG_EMERG , cf , 0 , " Error: no name of ldap server specified " ) ;
return NGX_CONF_ERROR ;
}
server . alias = name ;
if ( cnf - > servers = = NULL ) {
cnf - > servers = ngx_array_create ( cf - > pool , 7 , sizeof ( ngx_ldap_server ) ) ;
if ( cnf - > servers = = NULL ) {
return NGX_CONF_ERROR ;
}
}
s = ngx_array_push ( cnf - > servers ) ;
if ( s = = NULL ) {
return NGX_CONF_ERROR ;
}
* s = server ;
save = * cf ;
cf - > handler = ngx_http_auth_ldap_ldap_server ;
cf - > handler_conf = conf ;
rv = ngx_conf_parse ( cf , NULL ) ;
* cf = save ;
if ( rv ! = NGX_CONF_OK ) {
return rv ;
}
return NGX_CONF_OK ;
}
/**
* Called for every variable inside ldap_server block
*/
static char *
ngx_http_auth_ldap_url ( ngx_conf_t * cf , ngx_command_t * cmd , void * conf ) {
ngx_http_auth_ldap_loc_conf_t * alcf = conf ;
ngx_http_auth_ldap_ldap_server ( ngx_conf_t * cf , ngx_command_t * dummy , void * conf )
{
char * rv ;
ngx_str_t * value ;
u_char * p ;
ngx_ldap_server * server ;
ngx_http_auth_ldap_conf_t * cnf = conf ;
// It should be safe to just use latest server from array
server = ( ( ngx_ldap_server * ) cnf - > servers - > elts + ( cnf - > servers - > nelts - 1 ) ) ;
value = cf - > args - > elts ;
// TODO: Add more validation
if ( ngx_strcmp ( value [ 0 ] . data , " url " ) = = 0 ) {
return ngx_http_auth_ldap_parse_url ( cf , server ) ;
} else if ( ngx_strcmp ( value [ 0 ] . data , " binddn " ) = = 0 ) {
server - > bind_dn = value [ 1 ] ;
} else if ( ngx_strcmp ( value [ 0 ] . data , " binddn_passwd " ) = = 0 ) {
server - > bind_dn_passwd = value [ 1 ] ;
} else if ( ngx_strcmp ( value [ 0 ] . data , " group_attribute " ) = = 0 ) {
server - > group_attribute = value [ 1 ] ;
} else if ( ngx_strcmp ( value [ 0 ] . data , " group_attribute_is_dn " ) = = 0 & & ngx_strcmp ( value [ 1 ] . data , " on " ) ) {
server - > group_attribute_dn = 1 ;
} else if ( ngx_strcmp ( value [ 0 ] . data , " require " ) = = 0 ) {
return ngx_http_auth_ldap_parse_require ( cf , server ) ;
} else if ( ngx_strcmp ( value [ 0 ] . data , " satisfy " ) = = 0 ) {
return ngx_http_auth_ldap_parse_satisfy ( cf , server ) ;
}
rv = NGX_CONF_OK ;
return rv ;
}
/**
* Parse auth_ldap directive
*/
static char *
ngx_http_auth_ldap ( ngx_conf_t * cf , void * post , void * data ) {
ngx_str_t * realm = data ;
size_t len ;
u_char * basic , * p ;
if ( ngx_strcmp ( realm - > data , " off " ) = = 0 ) {
realm - > len = 0 ;
realm - > data = ( u_char * ) " " ;
return NGX_CONF_OK ;
}
len = sizeof ( " Basic realm= \" " ) - 1 + realm - > len + 1 ;
basic = ngx_pcalloc ( cf - > pool , len ) ;
if ( basic = = NULL ) {
return NGX_CONF_ERROR ;
}
p = ngx_cpymem ( basic , " Basic realm= \" " , sizeof ( " Basic realm= \" " ) - 1 ) ;
p = ngx_cpymem ( p , realm - > data , realm - > len ) ;
* p = ' " ' ;
realm - > len = len ;
realm - > data = basic ;
return NGX_CONF_OK ;
}
/**
* Parse URL conf parameter
*/
static char *
ngx_http_auth_ldap_parse_url ( ngx_conf_t * cf , ngx_ldap_server * server ) {
ngx_str_t * value ;
u_char * p ;
value = cf - > args - > elts ;
int rc = ldap_url_parse ( ( const char * ) value [ 1 ] . data , & alcf - > ludpp ) ;
server - > url = * value ;
int rc = ldap_url_parse ( ( const char * ) value [ 1 ] . data , & server - > ludpp ) ;
if ( rc ! = LDAP_SUCCESS ) {
switch ( rc ) {
case LDAP_URL_ERR_MEM :
@ -215,65 +322,47 @@ ngx_http_auth_ldap_url(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
return NGX_CONF_ERROR ;
}
if ( alcf - > ludpp - > lud_attrs = = NULL ) {
if ( server - > ludpp - > lud_attrs = = NULL ) {
ngx_conf_log_error ( NGX_LOG_EMERG , cf , 0 , " LDAP: No attrs in auth_ldap_url. " ) ;
return NGX_CONF_ERROR ;
}
alcf - > url . len = ngx_strlen ( alcf - > ludpp - > lud_scheme ) + ngx_strlen ( alcf - > ludpp - > lud_host ) + 11 ; // 11 = len("://:/") + len("65535") + len("\0")
alcf - > url . data = ngx_pcalloc ( cf - > pool , alcf - > url . len ) ;
p = ngx_sprintf ( alcf - > url . data , " %s://%s:%d/ " , ( const char * ) alcf - > ludpp - > lud_scheme ,
( const char * ) alcf - > ludpp - > lud_host , alcf - > ludpp - > lud_port ) ;
server - > url . len = ngx_strlen ( server - > ludpp - > lud_scheme ) + ngx_strlen ( server - > ludpp - > lud_host ) + 11 ; // 11 = len("://:/") + len("65535") + len("\0")
server - > url . data = ngx_pcalloc ( cf - > pool , server - > url . len ) ;
p = ngx_sprintf ( server - > url . data , " %s://%s:%d/ " , ( const char * ) server - > ludpp - > lud_scheme ,
( const char * ) server - > ludpp - > lud_host , server - > ludpp - > lud_port ) ;
* p = 0 ;
return NGX_CONF_OK ;
}
/**
* Parse " require " conf parameter
*/
static char *
ngx_http_auth_ldap_satisfy ( ngx_conf_t * cf , ngx_command_t * cmd , void * conf ) {
ngx_http_auth_ldap_loc_conf_t * alcf = conf ;
ngx_str_t * value ;
value = cf - > args - > elts ;
if ( ngx_strcmp ( value [ 1 ] . data , " all " ) = = 0 ) {
alcf - > satisfy_all = 1 ;
return NGX_CONF_OK ;
}
if ( ngx_strcmp ( value [ 1 ] . data , " any " ) = = 0 ) {
alcf - > satisfy_all = 0 ;
return NGX_CONF_OK ;
}
ngx_conf_log_error ( NGX_LOG_EMERG , cf , 0 , " Incorrect value for auth_ldap_satisfy " ) ;
return NGX_CONF_ERROR ;
}
static char *
ngx_http_auth_ldap_require ( ngx_conf_t * cf , ngx_command_t * cmd , void * conf ) {
ngx_http_auth_ldap_parse_require ( ngx_conf_t * cf , ngx_ldap_server * server ) {
ngx_http_script_compile_t sc ;
ngx_http_auth_ldap_loc_conf_t * alcf = conf ;
ngx_str_t * value ;
value = cf - > args - > elts ;
if ( alcf - > require_user = = NULL ) {
alcf - > require_user = ngx_array_create ( cf - > pool , 4 , sizeof ( ngx_ldap_require_t ) ) ;
if ( alcf - > require_user = = NULL ) {
if ( server - > require_user = = NULL ) {
server - > require_user = ngx_array_create ( cf - > pool , 4 , sizeof ( ngx_ldap_require_t ) ) ;
if ( server - > require_user = = NULL ) {
return NGX_CONF_ERROR ;
}
}
if ( alcf - > require_group = = NULL ) {
alcf - > require_group = ngx_array_create ( cf - > pool , 4 , sizeof ( ngx_ldap_require_t ) ) ;
if ( alcf - > require_group = = NULL ) {
if ( server - > require_group = = NULL ) {
server - > require_group = ngx_array_create ( cf - > pool , 4 , sizeof ( ngx_ldap_require_t ) ) ;
if ( server - > require_group = = NULL ) {
return NGX_CONF_ERROR ;
}
}
if ( ngx_strcmp ( value [ 1 ] . data , " valid_user " ) = = 0 ) {
alcf - > require_valid_user = 1 ;
server - > require_valid_user = 1 ;
}
if ( ngx_strcmp ( value [ 1 ] . data , " user " ) = = 0 | | ngx_strcmp ( value [ 1 ] . data , " group " ) = = 0 )
@ -282,11 +371,11 @@ ngx_http_auth_ldap_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
ngx_ldap_require_t * rule = NULL ;
if ( ngx_strcmp ( value [ 1 ] . data , " user " ) = = 0 ) {
rule = ngx_array_push ( alcf - > require_user ) ;
rule = ngx_array_push ( server - > require_user ) ;
}
if ( ngx_strcmp ( value [ 1 ] . data , " group " ) = = 0 ) {
rule = ngx_array_push ( alcf - > require_group ) ;
rule = ngx_array_push ( server - > require_group ) ;
}
if ( rule = = NULL ) {
@ -317,6 +406,47 @@ ngx_http_auth_ldap_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
return NGX_CONF_OK ;
}
/**
* Parse " satisfy " conf parameter
*/
static char *
ngx_http_auth_ldap_parse_satisfy ( ngx_conf_t * cf , ngx_ldap_server * server ) {
ngx_str_t * value ;
value = cf - > args - > elts ;
if ( ngx_strcmp ( value [ 1 ] . data , " all " ) = = 0 ) {
server - > satisfy_all = 1 ;
return NGX_CONF_OK ;
}
if ( ngx_strcmp ( value [ 1 ] . data , " any " ) = = 0 ) {
server - > satisfy_all = 0 ;
return NGX_CONF_OK ;
}
ngx_conf_log_error ( NGX_LOG_EMERG , cf , 0 , " Incorrect value for auth_ldap_satisfy " ) ;
return NGX_CONF_ERROR ;
}
/**
* Create main config which will store ldap_servers array
*/
static void *
ngx_http_auth_ldap_create_conf ( ngx_conf_t * cf )
{
ngx_http_auth_ldap_conf_t * conf ;
conf = ngx_pcalloc ( cf - > pool , sizeof ( ngx_http_auth_ldap_conf_t ) ) ;
if ( conf = = NULL ) {
return NULL ;
}
return conf ;
}
/**
* Create location conf
*/
static void *
ngx_http_auth_basic_create_loc_conf ( ngx_conf_t * cf ) {
ngx_http_auth_ldap_loc_conf_t * conf ;
@ -324,12 +454,14 @@ ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf) {
if ( conf = = NULL ) {
return NULL ;
}
conf - > satisfy_all = NGX_CONF_UNSET ;
conf - > require_valid_user = NGX_CONF_UNSET ;
conf - > group_attribute_dn = NGX_CONF_UNSET ;
conf - > servers = NGX_CONF_UNSET_PTR ;
return conf ;
}
/**
* Merge location conf
*/
static char *
ngx_http_auth_ldap_merge_loc_conf ( ngx_conf_t * cf , void * parent , void * child ) {
ngx_http_auth_ldap_loc_conf_t * prev = parent ;
@ -338,34 +470,16 @@ ngx_http_auth_ldap_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) {
if ( conf - > realm . data = = NULL ) {
conf - > realm = prev - > realm ;
}
ngx_conf_merge_str_value ( conf - > url , prev - > url , " ldap://localhost/ " ) ;
ngx_conf_merge_str_value ( conf - > bind_dn , prev - > bind_dn , " " ) ;
ngx_conf_merge_str_value ( conf - > bind_dn_passwd , prev - > bind_dn_passwd , " " ) ;
ngx_conf_merge_str_value ( conf - > group_attribute , prev - > group_attribute , " member " ) ;
ngx_conf_merge_value ( conf - > require_valid_user , prev - > require_valid_user , 0 ) ;
ngx_conf_merge_value ( conf - > satisfy_all , prev - > satisfy_all , 0 ) ;
ngx_conf_merge_value ( conf - > group_attribute_dn , prev - > group_attribute_dn , 1 ) ;
if ( conf - > require_user = = NULL ) {
conf - > require_user = prev - > require_user ;
}
if ( conf - > require_group = = NULL ) {
conf - > require_group = prev - > require_group ;
}
if ( conf - > ludpp = = NULL ) {
conf - > ludpp = prev - > ludpp ;
}
ngx_conf_merge_ptr_value ( conf - > servers , prev - > servers , NULL ) ;
return NGX_CONF_OK ;
}
/**
* LDAP Authentication handler
*/
static ngx_int_t ngx_http_auth_ldap_handler ( ngx_http_request_t * r ) {
int rc ;
ngx_http_auth_ldap_ctx_t * ctx ;
ngx_http_auth_ldap_loc_conf_t * alcf ;
alcf = ngx_http_get_module_loc_conf ( r , ngx_http_auth_ldap_module ) ;
@ -374,11 +488,9 @@ static ngx_int_t ngx_http_auth_ldap_handler(ngx_http_request_t *r) {
return NGX_DECLINED ;
}
ctx = ngx_http_get_module_ctx ( r , ngx_http_auth_ldap_module ) ;
ngx_http_auth_ldap_conf_t * cnf ;
if ( ctx ) {
return ngx_http_auth_ldap_authenticate ( r , ctx , & ctx - > passwd , alcf ) ;
}
cnf = ngx_http_get_module_main_conf ( r , ngx_http_auth_ldap_module ) ;
rc = ngx_http_auth_basic_user ( r ) ;
@ -390,7 +502,7 @@ static ngx_int_t ngx_http_auth_ldap_handler(ngx_http_request_t *r) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
return ngx_http_auth_ldap_authenticate ( r , ctx , & ctx - > passwd , alc f) ;
return ngx_http_auth_ldap_authenticate ( r , alcf , cn f) ;
}
/**
@ -425,32 +537,27 @@ ngx_http_auth_ldap_get_user_info(ngx_http_request_t *r) {
return uinfo ;
}
static ngx_int_t ngx_http_auth_ldap_authenticate ( ngx_http_request_t * r , ngx_http_auth_ldap_ctx_t * ctx ,
ngx_str_t * passwd , ngx_http_auth_ldap_loc_conf_t * conf ) {
/**
* Read user credentials from request , set LDAP parameters and call authentication against required servers
*/
static ngx_int_t ngx_http_auth_ldap_authenticate ( ngx_http_request_t * r , ngx_http_auth_ldap_loc_conf_t * conf ,
ngx_http_auth_ldap_conf_t * mconf ) {
ngx_ldap_server * server , * servers ;
servers = mconf - > servers - > elts ;
int rc ;
ngx_uint_t i , k ;
ngx_str_t * alias ;
LDAP * ld ;
LDAPMessage * searchResult ;
LDAPURLDesc * ludpp = conf - > ludpp ;
int version = LDAP_VERSION3 ;
struct berval bvalue ;
struct timeval timeOut = { 10 , 0 } ;
int reqcert = LDAP_OPT_X_TLS_ALLOW ;
int rc ;
ngx_uint_t i ;
ngx_ldap_require_t * value ;
ngx_ldap_userinfo * uinfo ;
struct timeval timeOut = { 10 , 0 } ;
ngx_flag_t pass = NGX_CONF_UNSET ;
char * dn ;
u_char * p , * filter ;
if ( conf - > ludpp = = NULL ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
uinfo = ngx_http_auth_ldap_get_user_info ( r ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP username: %s " , uinfo - > username . data ) ;
if ( uinfo = = NULL ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
@ -470,23 +577,72 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
ldap_err2string ( rc ) ) ;
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: URL: %s " , conf - > url . data ) ;
// TODO: We might be using hash here, cause this loops is quite ugly, but it is simple and it works
int found ;
for ( k = 0 ; k < conf - > servers - > nelts ; k + + ) {
alias = ( ( ngx_str_t * ) conf - > servers - > elts + k ) ;
found = 0 ;
for ( i = 0 ; i < mconf - > servers - > nelts ; i + + ) {
server = & servers [ i ] ;
if ( server - > alias . len = = alias - > len & & ngx_strncmp ( server - > alias . data , alias - > data , server - > alias . len ) = = 0 ) {
found = 1 ;
pass = ngx_http_auth_ldap_authenticate_against_server ( r , server , uinfo , conf ) ;
if ( pass = = 1 ) {
return NGX_OK ;
} else if ( pass = = NGX_HTTP_INTERNAL_SERVER_ERROR ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
}
}
// If requested ldap server is not found, return 500 and write to log
if ( found = = 0 ) {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " LDAP: Server \" %s \" is not defined! " , alias - > data ) ;
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
}
return ngx_http_auth_ldap_set_realm ( r , & conf - > realm ) ;
}
/**
* Actual authentication against LDAP server
*/
static ngx_int_t ngx_http_auth_ldap_authenticate_against_server ( ngx_http_request_t * r , ngx_ldap_server * server , ngx_ldap_userinfo * uinfo , ngx_http_auth_ldap_loc_conf_t * conf ) {
LDAPURLDesc * ludpp = server - > ludpp ;
int rc ;
LDAP * ld ;
LDAPMessage * searchResult ;
char * dn ;
u_char * p , * filter ;
ngx_ldap_require_t * value ;
ngx_uint_t i ;
struct berval bvalue ;
ngx_flag_t pass = NGX_CONF_UNSET ;
struct timeval timeOut = { 10 , 0 } ;
if ( server - > ludpp = = NULL ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: URL: %s " , server - > url . data ) ;
rc = ldap_initialize ( & ld , ( const char * ) conf - > url . data ) ;
rc = ldap_initialize ( & ld , ( const char * ) server - > url . data ) ;
if ( rc ! = LDAP_SUCCESS ) {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " LDAP: Session initializing failed: %d, %s, (%s) " , rc ,
ldap_err2string ( rc ) , ( const char * ) conf - > url . data ) ;
ldap_err2string ( rc ) , ( const char * ) server - > url . data ) ;
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: Session initialized " , NULL ) ;
/// Bind to the server
rc = ldap_simple_bind_s ( ld , ( const char * ) conf - > bind_dn . data , ( const char * ) conf - > bind_dn_passwd . data ) ;
rc = ldap_simple_bind_s ( ld , ( const char * ) server - > bind_dn . data , ( const char * ) server - > bind_dn_passwd . data ) ;
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 [%s] : ldap_simple_bind_s error: %d, %s " , server - > url . data , rc ,
ldap_err2string ( rc ) ) ;
ldap_unbind_s ( ld ) ;
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
// Do not throw 500 in case connection failure, multiple servers might be used for failover scenario
return 0 ;
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: Bind successful " , NULL ) ;
@ -495,6 +651,7 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
r - > pool ,
( ludpp - > lud_filter ! = NULL ? ngx_strlen ( ludpp - > lud_filter ) : ngx_strlen ( " (objectClass=*) " ) ) + ngx_strlen ( " (&(=)) " ) + ngx_strlen ( ludpp - > lud_attrs [ 0 ] )
+ uinfo - > username . len + 1 ) ;
p = ngx_sprintf ( filter , " (&%s(%s=%s)) " , ludpp - > lud_filter ! = NULL ? ludpp - > lud_filter : " (objectClass=*) " , ludpp - > lud_attrs [ 0 ] , uinfo - > username . data ) ;
* p = 0 ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: filter %s " , ( const char * ) filter ) ;
@ -516,16 +673,13 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: result DN %s " , dn ) ;
/// Check require user
if ( conf - > require_user ! = NULL ) {
value = conf - > require_user - > elts ;
for ( i = 0 ; i < conf - > require_user - > nelts ; i + + ) {
if ( server - > require_user ! = NULL ) {
value = server - > require_user - > elts ;
for ( i = 0 ; i < server - > require_user - > nelts ; i + + ) {
ngx_str_t val ;
if ( value [ i ] . lengths = = NULL )
{
if ( value [ i ] . lengths = = NULL ) {
val = value [ i ] . value ;
}
else
{
} else {
if ( ngx_http_script_run ( r , & val , value [ i ] . lengths - > elts , 0 ,
value [ i ] . values - > elts ) = = NULL )
{
@ -540,23 +694,23 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: compare with: %s " , val . data ) ;
if ( ngx_strncmp ( val . data , dn , val . len ) = = 0 ) {
pass = 1 ;
if ( conf - > satisfy_all = = 0 ) {
if ( server - > satisfy_all = = 0 ) {
break ;
}
} else {
if ( conf - > satisfy_all = = 1 ) {
if ( server - > satisfy_all = = 1 ) {
ldap_memfree ( dn ) ;
ldap_msgfree ( searchResult ) ;
ldap_unbind_s ( ld ) ;
return ngx_http_auth_ldap_set_realm ( r , & conf - > realm ) ;
return 0 ;
}
}
}
}
/// Check require group
if ( conf - > require_group ! = NULL ) {
if ( conf - > group_attribute_dn = = 1 ) {
if ( server - > require_group ! = NULL ) {
if ( server - > group_attribute_dn = = 1 ) {
bvalue . bv_val = dn ;
bvalue . bv_len = ngx_strlen ( dn ) ;
} else {
@ -564,16 +718,13 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
bvalue . bv_len = uinfo - > username . len ;
}
value = conf - > require_group - > elts ;
value = server - > require_group - > elts ;
for ( i = 0 ; i < conf - > require_group - > nelts ; i + + ) {
for ( i = 0 ; i < server - > require_group - > nelts ; i + + ) {
ngx_str_t val ;
if ( value [ i ] . lengths = = NULL )
{
if ( value [ i ] . lengths = = NULL ) {
val = value [ i ] . value ;
}
else
{
} else {
if ( ngx_http_script_run ( r , & val , value [ i ] . lengths - > elts , 0 ,
value [ i ] . values - > elts ) = = NULL )
{
@ -587,7 +738,7 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: group compare with: %s " , val . data ) ;
rc = ldap_compare_ext_s ( ld , ( const char * ) val . data , ( const char * ) conf - > group_attribute . data ,
rc = ldap_compare_ext_s ( ld , ( const char * ) val . data , ( const char * ) server - > group_attribute . data ,
& bvalue , NULL , NULL ) ;
/*if (rc != LDAP_COMPARE_TRUE && rc != LDAP_COMPARE_FALSE && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
@ -601,11 +752,11 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
if ( rc = = LDAP_COMPARE_TRUE ) {
pass = 1 ;
if ( conf - > satisfy_all = = 0 ) {
if ( server - > satisfy_all = = 0 ) {
break ;
}
} else {
if ( conf - > satisfy_all = = 1 ) {
if ( server - > satisfy_all = = 1 ) {
pass = 0 ;
break ;
}
@ -614,7 +765,7 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
}
/// Check valid user
if ( pass ! = 0 | | ( conf - > require_valid_user = = 1 & & conf - > satisfy_all = = 0 & & pass = = 0 ) ) {
if ( pass ! = 0 | | ( server - > require_valid_user = = 1 & & server - > satisfy_all = = 0 & & pass = = 0 ) ) {
/// Bind user to the server
rc = ldap_simple_bind_s ( ld , dn , ( const char * ) uinfo - > password . data ) ;
if ( rc ! = LDAP_SUCCESS ) {
@ -623,8 +774,7 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
pass = 0 ;
} else {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " LDAP: User bind successful " , NULL ) ;
if ( conf - > require_valid_user = = 1 )
pass = 1 ;
if ( server - > require_valid_user = = 1 ) pass = 1 ;
}
}
@ -635,13 +785,12 @@ static ngx_int_t ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http
ldap_msgfree ( searchResult ) ;
ldap_unbind_s ( ld ) ;
if ( pass = = 1 ) {
return NGX_OK ;
}
return ngx_http_auth_ldap_set_realm ( r , & conf - > realm ) ;
return pass ;
}
/**
* Respond with forbidden and add correct headers
*/
static ngx_int_t ngx_http_auth_ldap_set_realm ( ngx_http_request_t * r , ngx_str_t * realm ) {
r - > headers_out . www_authenticate = ngx_list_push ( & r - > headers_out . headers ) ;
if ( r - > headers_out . www_authenticate = = NULL ) {
@ -656,37 +805,9 @@ static ngx_int_t ngx_http_auth_ldap_set_realm(ngx_http_request_t *r, ngx_str_t *
return NGX_HTTP_UNAUTHORIZED ;
}
static char *
ngx_http_auth_ldap ( ngx_conf_t * cf , void * post , void * data ) {
ngx_str_t * realm = data ;
size_t len ;
u_char * basic , * p ;
if ( ngx_strcmp ( realm - > data , " off " ) = = 0 ) {
realm - > len = 0 ;
realm - > data = ( u_char * ) " " ;
return NGX_CONF_OK ;
}
len = sizeof ( " Basic realm= \" " ) - 1 + realm - > len + 1 ;
basic = ngx_pcalloc ( cf - > pool , len ) ;
if ( basic = = NULL ) {
return NGX_CONF_ERROR ;
}
p = ngx_cpymem ( basic , " Basic realm= \" " , sizeof ( " Basic realm= \" " ) - 1 ) ;
p = ngx_cpymem ( p , realm - > data , realm - > len ) ;
* p = ' " ' ;
realm - > len = len ;
realm - > data = basic ;
return NGX_CONF_OK ;
}
/**
* Init module and add ldap auth handler to NGX_HTTP_ACCESS_PHASE
*/
static ngx_int_t ngx_http_auth_ldap_init ( ngx_conf_t * cf ) {
ngx_http_handler_pt * h ;
ngx_http_core_main_conf_t * cmcf ;