@ -155,6 +155,8 @@ typedef struct {
int error_code ;
int error_code ;
ngx_str_t error_msg ;
ngx_str_t error_msg ;
ngx_str_t dn ;
ngx_str_t dn ;
ngx_str_t user_dn ;
ngx_str_t group_dn ;
ngx_http_auth_ldap_cache_elt_t * cache_bucket ;
ngx_http_auth_ldap_cache_elt_t * cache_bucket ;
u_char cache_big_hash [ 16 ] ;
u_char cache_big_hash [ 16 ] ;
@ -1884,7 +1886,7 @@ ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t
if ( ctx - > server - > require_valid_user_dn . value . data ! = NULL ) {
if ( ctx - > server - > require_valid_user_dn . value . data ! = NULL ) {
/* Construct user DN */
/* Construct user DN */
if ( ngx_http_complex_value ( r , & ctx - > server - > require_valid_user_dn , & ctx - > dn ) ! = NGX_OK ) {
if ( ngx_http_complex_value ( r , & ctx - > server - > require_valid_user_dn , & ctx - > user_ dn) ! = NGX_OK ) {
ngx_del_timer ( r - > connection - > write ) ;
ngx_del_timer ( r - > connection - > write ) ;
return NGX_ERROR ;
return NGX_ERROR ;
}
}
@ -1915,12 +1917,12 @@ ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t
case PHASE_CHECK_USER :
case PHASE_CHECK_USER :
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: User DN is \" %V \" " ,
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: User DN is \" %V \" " ,
& ctx - > dn ) ;
& ctx - > user_ dn) ;
if ( ctx - > server - > require_user ! = NULL ) {
if ( ctx - > server - > require_user ! = NULL ) {
rc = ngx_http_auth_ldap_check_user ( r , ctx ) ;
rc = ngx_http_auth_ldap_check_user ( r , ctx ) ;
if ( rc ! = NGX_OK ) {
if ( rc ! = NGX_OK ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Not ok " , & ctx - > dn ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Not ok " , & ctx - > user_ dn) ;
/* User check failed, try next server */
/* User check failed, try next server */
ctx - > phase = PHASE_NEXT ;
ctx - > phase = PHASE_NEXT ;
break ;
break ;
@ -1930,7 +1932,7 @@ ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t
/* User not yet fully authenticated, check group next */
/* User not yet fully authenticated, check group next */
if ( ( ctx - > outcome = = OUTCOME_UNCERTAIN ) & &
if ( ( ctx - > outcome = = OUTCOME_UNCERTAIN ) & &
( ctx - > server - > require_group ! = NULL ) ) {
( ctx - > server - > require_group ! = NULL ) ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Moving to group check " , & ctx - > dn ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Moving to group check " , & ctx - > user_ dn) ;
ctx - > phase = PHASE_CHECK_GROUP ;
ctx - > phase = PHASE_CHECK_GROUP ;
ctx - > iteration = 0 ;
ctx - > iteration = 0 ;
break ;
break ;
@ -1942,7 +1944,7 @@ ngx_http_auth_ldap_authenticate(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t
break ;
break ;
case PHASE_CHECK_GROUP :
case PHASE_CHECK_GROUP :
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " Checking group " , & ctx - > dn ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " Checking group " , & ctx - > user_ dn) ;
rc = ngx_http_auth_ldap_check_group ( r , ctx ) ;
rc = ngx_http_auth_ldap_check_group ( r , ctx ) ;
if ( rc = = NGX_AGAIN ) {
if ( rc = = NGX_AGAIN ) {
/* LDAP operation in progress, wait for the results */
/* LDAP operation in progress, wait for the results */
@ -2087,6 +2089,12 @@ ngx_http_auth_ldap_search(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t *ctx)
if ( ctx - > dn . data = = NULL ) {
if ( ctx - > dn . data = = NULL ) {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: Could not find user DN " ) ;
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: Could not find user DN " ) ;
return NGX_ERROR ;
return NGX_ERROR ;
} else {
ctx - > user_dn . len = ngx_strlen ( ctx - > dn . data ) ;
ctx - > user_dn . data = ( u_char * ) ngx_palloc ( ctx - > r - > pool , ctx - > user_dn . len + 1 ) ;
ngx_memcpy ( ctx - > user_dn . data , ctx - > dn . data , ctx - > user_dn . len + 1 ) ;
ctx - > dn . data = NULL ;
ctx - > dn . len = 0 ;
}
}
return NGX_OK ;
return NGX_OK ;
@ -2107,7 +2115,7 @@ ngx_http_auth_ldap_check_user(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t *c
}
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Comparing user DN with \" %V \" " , & val ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Comparing user DN with \" %V \" " , & val ) ;
if ( val . len = = ctx - > dn . len & & ngx_memcmp ( val . data , ctx - > dn . data , val . len ) = = 0 ) {
if ( val . len = = ctx - > user_ dn. len & & ngx_memcmp ( val . data , ctx - > user_ dn. data , val . len ) = = 0 ) {
if ( ctx - > server - > satisfy_all = = 0 ) {
if ( ctx - > server - > satisfy_all = = 0 ) {
ctx - > outcome = OUTCOME_ALLOW ;
ctx - > outcome = OUTCOME_ALLOW ;
return NGX_OK ;
return NGX_OK ;
@ -2127,25 +2135,33 @@ static ngx_int_t
ngx_http_auth_ldap_check_group ( ngx_http_request_t * r , ngx_http_auth_ldap_ctx_t * ctx )
ngx_http_auth_ldap_check_group ( ngx_http_request_t * r , ngx_http_auth_ldap_ctx_t * ctx )
{
{
ngx_http_complex_value_t * values ;
ngx_http_complex_value_t * values ;
struct berval bvalue ;
ngx_int_t rc ;
ngx_int_t rc ;
u_char * filter ;
char * user_val ;
char * attrs [ 2 ] ;
size_t for_filter ;
/* Handle result of the comparison started during previous call */
/* Handle result of the search started during previous call */
if ( ctx - > iteration > 0 ) {
if ( ctx - > iteration > 0 ) {
if ( ctx - > error_code = = LDAP_COMPARE_TRUE ) {
ctx - > group_dn . data = ctx - > dn . data ;
if ( ctx - > server - > satisfy_all = = 0 ) {
if ( ctx - > group_dn . data ! = NULL ) {
ctx - > outcome = OUTCOME_ALLOW ;
if ( ctx - > error_code = = LDAP_SUCCESS ) {
return NGX_OK ;
if ( ctx - > server - > satisfy_all = = 0 ) {
}
ctx - > outcome = OUTCOME_ALLOW ;
} else if ( ctx - > error_code = = LDAP_COMPARE_FALSE | | ctx - > error_code = = LDAP_NO_SUCH_ATTRIBUTE | | ctx - > error_code = = LDAP_NO_SUCH_OBJECT ) {
return NGX_OK ;
if ( ctx - > server - > satisfy_all = = 1 ) {
}
ctx - > outcome = OUTCOME_DENY ;
} else if ( ctx - > error_code = = LDAP_NO_RESULTS_RETURNED ) {
return NGX_DECLINED ;
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_search_ext() request failed (%d: %s) " ,
ctx - > error_code , ldap_err2string ( ctx - > error_code ) ) ;
if ( ctx - > server - > satisfy_all = = 1 ) {
ctx - > outcome = OUTCOME_DENY ;
return NGX_DECLINED ;
}
} else {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_search_ext() request failed (%d: %s) " ,
ctx - > error_code , ldap_err2string ( ctx - > error_code ) ) ;
return NGX_ERROR ;
}
}
} else {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_compare_ext() request failed (%d: %s) " ,
ctx - > error_code , ldap_err2string ( ctx - > error_code ) ) ;
return NGX_ERROR ;
}
}
}
}
@ -2167,34 +2183,64 @@ ngx_http_auth_ldap_check_group(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t *
return NGX_ERROR ;
return NGX_ERROR ;
}
}
char * gr ;
char * cn_gr ;
char * tail_gr ;
gr = ngx_pcalloc ( r - > pool , val . len + 1 ) ;
ngx_memcpy ( gr , val . data , val . len ) ;
gr [ val . len ] = ' \0 ' ;
tail_gr = ngx_strchr ( gr , ' , ' ) ;
if ( tail_gr = = NULL ) {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: Incorrect group DN: \" %s \" " , gr ) ;
ctx - > outcome = OUTCOME_ERROR ;
ngx_http_auth_ldap_return_connection ( ctx - > c ) ;
return NGX_ERROR ;
}
* tail_gr = ' \0 ' ;
tail_gr + + ;
cn_gr = gr ;
if ( ctx - > server - > group_attribute_dn = = 1 ) {
if ( ctx - > server - > group_attribute_dn = = 1 ) {
bvalue . bv_val = ( char * ) ctx - > dn . data ;
user_val = ngx_pcalloc (
bvalue . bv_len = ctx - > dn . len ;
r - > pool ,
ctx - > user_dn . len + 1 ) ;
ngx_memcpy ( user_val , ctx - > user_dn . data , ctx - > user_dn . len ) ;
user_val [ ctx - > user_dn . len ] = ' \0 ' ;
} else {
} else {
bvalue . bv_val = ( char * ) r - > headers_in . user . data ;
user_val = ngx_pcalloc (
bvalue . bv_len = r - > headers_in . user . len ;
r - > pool ,
r - > headers_in . user . len + 1 ) ;
ngx_memcpy ( user_val , r - > headers_in . user . data , r - > headers_in . user . len ) ;
user_val [ r - > headers_in . user . len ] = ' \0 ' ;
}
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Comparing user group with \" %V \" " , & val ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Search user in group \" %V \" " , & val ) ;
if ( ctx - > server - > group_attribute . data = = NULL ) {
if ( ctx - > server - > group_attribute . data = = NULL ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: group_attribute.data is \" %V \" so calling a failure here " , & ctx - > server - > group_attribute . data ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: group_attribute.data is \" %V \" so calling a failure here " , ctx - > server - > group_attribute . data ) ;
rc = ! LDAP_SUCCESS ;
rc = ! LDAP_SUCCESS ;
} else {
} else {
rc = ldap_compare_ext ( ctx - > c - > ld , ( const char * ) val . data , ( const char * ) ctx - > server - > group_attribute . data ,
for_filter = ngx_strlen ( cn_gr ) + ctx - > server - > group_attribute . len + ngx_strlen ( ( const char * ) user_val ) + ngx_strlen ( " (&()(=)) " ) + 1 ;
& bvalue , NULL , NULL , & ctx - > c - > msgid ) ;
filter = ngx_pcalloc (
r - > pool ,
for_filter ) ;
ngx_sprintf ( filter , " (&(%s)(%s=%s)) " , cn_gr , ctx - > server - > group_attribute . data , user_val ) ;
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: Search group filter is \" %s \" " , ( const char * ) filter ) ;
attrs [ 0 ] = LDAP_NO_ATTRS ;
attrs [ 1 ] = NULL ;
rc = ldap_search_ext ( ctx - > c - > ld , tail_gr , LDAP_SCOPE_ONELEVEL , ( const char * ) filter , attrs , 0 , NULL , NULL , NULL , 0 , & ctx - > c - > msgid ) ;
}
}
if ( rc ! = LDAP_SUCCESS ) {
if ( rc ! = LDAP_SUCCESS ) {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_compare_ext() failed (%d: %s) " ,
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_search _ext() failed (%d: %s) " ,
rc , ldap_err2string ( rc ) ) ;
rc , ldap_err2string ( rc ) ) ;
ctx - > outcome = OUTCOME_ERROR ;
ctx - > outcome = OUTCOME_ERROR ;
ngx_http_auth_ldap_return_connection ( ctx - > c ) ;
ngx_http_auth_ldap_return_connection ( ctx - > c ) ;
return NGX_ERROR ;
return NGX_ERROR ;
}
}
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: ldap_compare _ext() -> msgid=%d " ,
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 , " http_auth_ldap: ldap_search _ext() -> msgid=%d " ,
ctx - > c - > msgid ) ;
ctx - > c - > msgid ) ;
ctx - > c - > state = STATE_COMPAR ING ;
ctx - > c - > state = STATE_SEARCH ING ;
ctx - > iteration + + ;
ctx - > iteration + + ;
return NGX_AGAIN ;
return NGX_AGAIN ;
}
}
@ -2216,7 +2262,7 @@ ngx_http_auth_ldap_check_bind(ngx_http_request_t *r, ngx_http_auth_ldap_ctx_t *c
cred . bv_val = ( char * ) r - > headers_in . passwd . data ;
cred . bv_val = ( char * ) r - > headers_in . passwd . data ;
cred . bv_len = r - > headers_in . passwd . len ;
cred . bv_len = r - > headers_in . passwd . len ;
rc = ldap_sasl_bind ( ctx - > c - > ld , ( const char * ) ctx - > dn . data , LDAP_SASL_SIMPLE , & cred , NULL , NULL , & ctx - > c - > msgid ) ;
rc = ldap_sasl_bind ( ctx - > c - > ld , ( const char * ) ctx - > user_ dn. data , LDAP_SASL_SIMPLE , & cred , NULL , NULL , & ctx - > c - > msgid ) ;
if ( rc ! = LDAP_SUCCESS ) {
if ( rc ! = LDAP_SUCCESS ) {
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_sasl_bind() failed (%d: %s) " ,
ngx_log_error ( NGX_LOG_ERR , r - > connection - > log , 0 , " http_auth_ldap: ldap_sasl_bind() failed (%d: %s) " ,
rc , ldap_err2string ( rc ) ) ;
rc , ldap_err2string ( rc ) ) ;