Changeset 2062

Show
Ignore:
Timestamp:
01/27/2008 12:00:24 AM (4 months ago)
Author:
glen
Message:

- mod_auth ldap rework, most important change is being able to startup if ldap server is down (#1535)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/NEWS

    r2059 r2062  
    1515  * add IdleServers and Scoreboard directives in ?auto mode for mod_status (#1507) 
    1616  * support letterhomes in mod_userdir (#1473) 
     17  * mod_auth ldap rework, most important change is being able to startup if ldap server is down (#1535) 
    1718 
    1819- 1.5.0-r19.. - 
  • trunk/src/http_auth.c

    r2048 r2062  
    5555 
    5656handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s); 
     57void auth_ldap_cleanup(ldap_plugin_config *p); 
    5758 
    5859static const char base64_pad = '='; 
     
    698699        } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { 
    699700#ifdef USE_LDAP 
    700                 LDAP *ldap; 
    701                 LDAPMessage *lm, *first; 
    702                 char *dn; 
    703                 int ret; 
     701                LDAP *ldap = NULL; 
     702                LDAPMessage *lm = NULL, *first = NULL; 
     703                struct berval credentials; 
     704                char *dn = NULL; 
     705                int ret = 0; 
    704706                char *attrs[] = { LDAP_NO_ATTRS, NULL }; 
    705                 size_t i
     707                size_t i = 0
    706708 
    707709                /* for now we stay synchronous */ 
     
    738740                        return -1; 
    739741 
     742                /* 2. */ 
     743 
     744                if (p->conf.ldap->ldap == NULL) { 
     745                        if(auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON) 
     746                                return -1; 
     747                } 
     748 
    740749                /* build filter */ 
    741                 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre); 
     750                buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap->ldap_filter_pre); 
    742751                buffer_append_string_buffer(p->ldap_filter, username); 
    743                 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post); 
    744  
    745  
    746                 /* 2. */ 
    747                 if (p->conf.ldap == NULL || 
    748                     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))) { 
    749                         if (auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON) 
     752                buffer_append_string_buffer(p->ldap_filter, p->conf.ldap->ldap_filter_post); 
     753 
     754                ret = ldap_search_ext_s(p->conf.ldap->ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, NULL, NULL, NULL, 0, &lm); 
     755 
     756                if (ret == LDAP_SERVER_DOWN) { 
     757                        log_error_write(srv, __FILE__, __LINE__, "s", 
     758                                "ldap: server down, try to reconnect"); 
     759 
     760                        auth_ldap_cleanup(p->conf.ldap); 
     761 
     762                        if(auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON) 
    750763                                return -1; 
    751                         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))) { 
    752  
     764 
     765                        log_error_write(srv, __FILE__, __LINE__, "s", 
     766                                "ldap: successfully reconnected"); 
     767                } 
     768 
     769                if (ret != LDAP_SUCCESS) { 
    753770                        log_error_write(srv, __FILE__, __LINE__, "sssb", 
    754                                         "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter); 
    755  
    756                         return -1; 
    757                         } 
    758                 } 
    759  
    760                 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) { 
    761                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ..."); 
     771                                        "ldap:", ldap_err2string(ret), ", filter:", p->ldap_filter); 
     772 
     773                        return -1; 
     774                } 
     775 
     776                if (ldap_count_entries(p->conf.ldap->ldap, lm) > 1) { 
     777                        log_error_write(srv, __FILE__, __LINE__, "ssb", 
     778                                "ldap:", "more than one record returned, you might have to refine the filter:", p->ldap_filter); 
     779                } 
     780 
     781                first = ldap_first_entry(p->conf.ldap->ldap, lm); 
     782                if (first == NULL) { 
     783                        ldap_get_option(p->conf.ldap->ldap, LDAP_OPT_ERROR_NUMBER, &ret); 
     784                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    762785 
    763786                        ldap_msgfree(lm); 
     
    766789                } 
    767790 
    768                 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) { 
    769                         log_error_write(srv, __FILE__, __LINE__, "s", "ldap ..."); 
     791                dn = ldap_get_dn(p->conf.ldap->ldap, first); 
     792                if (dn == NULL) { 
     793                        ldap_get_option(p->conf.ldap->ldap, LDAP_OPT_ERROR_NUMBER, &ret); 
     794                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    770795 
    771796                        ldap_msgfree(lm); 
     
    776801                ldap_msgfree(lm); 
    777802 
    778  
    779803                /* 3. */ 
    780                 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) { 
    781                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno)); 
    782                         return -1; 
    783                 } 
    784  
    785                 ret = LDAP_VERSION3; 
    786                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) { 
     804                ret = ldap_initialize(&ldap, p->conf.auth_ldap_url->ptr); 
     805                if (ret) { 
    787806                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    788807 
    789                         ldap_unbind_s(ldap); 
     808                        ldap_memfree(dn); 
     809 
     810                        return -1; 
     811                } 
     812 
     813                const int ldap_version = LDAP_VERSION3; 
     814                ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); 
     815                if (ret != LDAP_OPT_SUCCESS) { 
     816                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
     817 
     818                        ldap_memfree(ldap); 
     819                        ldap_memfree(dn); 
    790820 
    791821                        return -1; 
     
    793823 
    794824                if (p->conf.auth_ldap_starttls == 1) { 
    795                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL,  NULL))) { 
     825                        ret = ldap_start_tls_s(ldap, NULL,  NULL); 
     826                        if (ret != LDAP_OPT_SUCCESS) { 
    796827                                log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret)); 
    797828 
    798                                 ldap_unbind_s(ldap); 
     829                                ldap_memfree(ldap); 
     830                                ldap_memfree(dn); 
    799831 
    800832                                return -1; 
     
    802834                } 
    803835 
    804  
    805                 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) { 
     836                /* Don't initialize it using " = {...}" since upstream doesn't 
     837                 * guarantee an order and the compiler only issues a warning when 
     838                 * passing an int as the pointer and vice-versa. 
     839                 * We have to cast away the const since berval is a general struct, 
     840                 * but ldap_sasl_bind_s doesn't write to the *pw location 
     841                 */ 
     842                credentials.bv_val = (char*)pw; 
     843                credentials.bv_len = strlen(pw); 
     844 
     845                /* TODO: add funtionality to specify LDAP_SASL_EXTERNAL (or GSS-SPNEGO, etc.) */ 
     846                ret = ldap_sasl_bind_s(ldap, dn, LDAP_SASL_SIMPLE, &credentials, NULL, NULL, NULL); 
     847                if (ret != LDAP_SUCCESS) { 
    806848                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    807849 
    808                         ldap_unbind_s(ldap); 
     850                        ldap_memfree(ldap); 
     851                        ldap_memfree(dn); 
    809852 
    810853                        return -1; 
     
    812855 
    813856                /* 5. */ 
    814                 ldap_unbind_s(ldap); 
     857                ldap_unbind_ext_s(ldap, NULL, NULL); 
     858                ldap_memfree(dn); 
    815859 
    816860                /* everything worked, good, access granted */ 
  • trunk/src/http_auth.h

    r1675 r2062  
    1818} auth_backend_t; 
    1919 
     20#ifdef USE_LDAP 
     21typedef struct { 
     22        LDAP *ldap; 
     23 
     24        buffer *ldap_filter_pre; 
     25        buffer *ldap_filter_post; 
     26} ldap_plugin_config; 
     27#endif 
     28 
    2029typedef struct { 
    2130        /* auth */ 
     
    3039        buffer *auth_backend_conf; 
    3140 
    32         buffer *auth_ldap_hostname
     41        buffer *auth_ldap_url
    3342        buffer *auth_ldap_basedn; 
    3443        buffer *auth_ldap_binddn; 
     
    4756 
    4857#ifdef USE_LDAP 
    49         LDAP *ldap; 
    50  
    51         buffer *ldap_filter_pre; 
    52         buffer *ldap_filter_post; 
     58        ldap_plugin_config *ldap; 
    5359#endif 
    5460} mod_auth_plugin_config; 
  • trunk/src/mod_auth.c

    r1939 r2062  
    1717 
    1818handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s); 
    19  
     19void auth_ldap_cleanup(ldap_plugin_config* p); 
    2020 
    2121/** 
     
    7575                        buffer_free(s->auth_backend_conf); 
    7676 
    77                         buffer_free(s->auth_ldap_hostname); 
     77                        buffer_free(s->auth_ldap_url); 
    7878                        buffer_free(s->auth_ldap_basedn); 
    7979                        buffer_free(s->auth_ldap_binddn); 
     
    8585 
    8686#ifdef USE_LDAP 
    87                         buffer_free(s->ldap_filter_pre); 
    88                         buffer_free(s->ldap_filter_post); 
    89  
    90                         if (s->ldap) ldap_unbind_s(s->ldap); 
     87                        buffer_free(s->ldap->ldap_filter_pre); 
     88                        buffer_free(s->ldap->ldap_filter_post); 
     89 
     90                        auth_ldap_cleanup(s->ldap); 
     91                        free(s->ldap); 
    9192#endif 
    9293 
     
    112113        PATCH_OPTION(auth_require); 
    113114        PATCH_OPTION(auth_debug); 
    114         PATCH_OPTION(auth_ldap_hostname); 
     115        PATCH_OPTION(auth_ldap_url); 
    115116        PATCH_OPTION(auth_ldap_basedn); 
    116117        PATCH_OPTION(auth_ldap_binddn); 
     
    124125#ifdef USE_LDAP 
    125126        PATCH_OPTION(ldap); 
    126         PATCH_OPTION(ldap_filter_pre); 
    127         PATCH_OPTION(ldap_filter_post); 
    128127#endif 
    129128 
     
    154153                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) { 
    155154                                PATCH_OPTION(auth_debug); 
    156                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) { 
    157                                 PATCH_OPTION(auth_ldap_hostname); 
     155                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.url"))) { 
     156                                PATCH_OPTION(auth_ldap_url); 
    158157#ifdef USE_LDAP 
    159158                                PATCH_OPTION(ldap); 
    160                                 PATCH_OPTION(ldap_filter_pre); 
    161                                 PATCH_OPTION(ldap_filter_post); 
    162159#endif 
    163160                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) { 
    164161                                PATCH_OPTION(auth_ldap_basedn); 
     162                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-dn"))) { 
     163                                PATCH_OPTION(auth_ldap_binddn); 
     164                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-pw"))) { 
     165                                PATCH_OPTION(auth_ldap_bindpw); 
    165166                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) { 
    166167                                PATCH_OPTION(auth_ldap_filter); 
     
    319320                { "auth.backend.plain.userfile",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ 
    320321                { "auth.require",                   NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },  /* 3 */ 
    321                 { "auth.backend.ldap.hostname",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ 
     322                { "auth.backend.ldap.url"     ,     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ 
    322323                { "auth.backend.ldap.base-dn",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 5 */ 
    323324                { "auth.backend.ldap.filter",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 6 */ 
     
    350351                s->auth_backend_conf = buffer_init(); 
    351352 
    352                 s->auth_ldap_hostname = buffer_init(); 
     353                s->auth_ldap_url    = buffer_init(); 
    353354                s->auth_ldap_basedn = buffer_init(); 
    354355                s->auth_ldap_binddn = buffer_init(); 
     
    364365 
    365366#ifdef USE_LDAP 
    366                 s->ldap_filter_pre = buffer_init(); 
    367                 s->ldap_filter_post = buffer_init(); 
    368                 s->ldap = NULL; 
     367                s->ldap = malloc (sizeof(ldap_plugin_config)); 
     368                s->ldap->ldap_filter_pre = buffer_init(); 
     369                s->ldap->ldap_filter_post = buffer_init(); 
     370                s->ldap->ldap = NULL; 
    369371#endif 
    370372 
     
    373375                cv[2].destination = s->auth_plain_userfile; 
    374376                cv[3].destination = s->auth_require; 
    375                 cv[4].destination = s->auth_ldap_hostname
     377                cv[4].destination = s->auth_ldap_url
    376378                cv[5].destination = s->auth_ldap_basedn; 
    377379                cv[6].destination = s->auth_ldap_filter; 
     
    520522                        } 
    521523                } 
    522  
    523                 switch(s->auth_backend) { 
    524                 case AUTH_BACKEND_LDAP: { 
    525                         handler_t ret = auth_ldap_init(srv, s); 
    526                         if (ret == HANDLER_ERROR) 
    527                                 return (ret); 
    528                         break; 
    529                 } 
    530                 default: 
    531                         break; 
    532                 } 
    533         } 
    534  
    535         return HANDLER_GO_ON; 
     524        } 
     525 
     526        return HANDLER_GO_ON; 
    536527} 
    537528 
     
    539530#ifdef USE_LDAP 
    540531                        int ret; 
    541 #if 0 
    542                         if (s->auth_ldap_basedn->used == 0) { 
    543                                 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set"); 
    544  
    545                                 return HANDLER_ERROR; 
    546                         } 
    547 #endif 
     532                        struct berval credentials; 
     533                        char *binddn_ptr = NULL; 
    548534 
    549535                        if (s->auth_ldap_filter->used) { 
     
    558544                                } 
    559545 
    560                                 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr); 
    561                                 buffer_copy_string(s->ldap_filter_post, dollar+1); 
    562                         } 
    563  
    564                         if (s->auth_ldap_hostname->used) { 
    565                                 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) { 
    566                                         log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno)); 
     546                                buffer_copy_string_len(s->ldap->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr); 
     547                                buffer_copy_string(s->ldap->ldap_filter_post, dollar+1); 
     548                        } 
     549 
     550                        if (s->auth_ldap_url->used) { 
     551                                if ((ret = ldap_initialize(&s->ldap->ldap, s->auth_ldap_url->ptr))) { 
     552                                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    567553 
    568554                                        return HANDLER_ERROR; 
    569555                                } 
    570556 
    571                                 ret = LDAP_VERSION3; 
    572                                 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) { 
     557                                const int ldap_version = LDAP_VERSION3; 
     558                                ret = ldap_set_option(s->ldap->ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); 
     559                                if (ret != LDAP_OPT_SUCCESS) { 
    573560                                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    574561 
     562                                        ldap_memfree(s->ldap->ldap); 
     563                                        s->ldap->ldap = NULL; 
     564 
    575565                                        return HANDLER_ERROR; 
    576566                                } 
    577567 
    578                                 if (s->auth_ldap_starttls) { 
     568                                if (s->auth_ldap_starttls == 1) { 
    579569                                        /* if no CA file is given, it is ok, as we will use encryption 
    580570                                         * if the server requires a CAfile it will tell us */ 
     
    585575                                                                        "Loading CA certificate failed:", ldap_err2string(ret)); 
    586576 
     577                                                        ldap_memfree(s->ldap->ldap); 
     578                                                        s->ldap->ldap = NULL; 
     579 
    587580                                                        return HANDLER_ERROR; 
    588581                                                } 
     
    595588                                                                        "Loading TLS certificate failed:", ldap_err2string(ret)); 
    596589 
     590                                                        ldap_memfree(s->ldap->ldap); 
     591                                                        s->ldap->ldap = NULL; 
     592 
    597593                                                        return HANDLER_ERROR; 
    598594                                                } 
     
    605601                                                                        "Loading TLS key certificate failed:", ldap_err2string(ret)); 
    606602 
     603                                                        ldap_memfree(s->ldap->ldap); 
     604                                                        s->ldap->ldap = NULL; 
     605 
    607606                                                        return HANDLER_ERROR; 
    608607                                                } 
    609608                                        } 
    610609 
    611                                         if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL,  NULL))) { 
     610                                        if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap->ldap, NULL,  NULL))) { 
    612611                                                log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret)); 
     612 
     613                                                ldap_memfree(s->ldap->ldap); 
     614                                                s->ldap->ldap = NULL; 
    613615 
    614616                                                return HANDLER_ERROR; 
     
    619621                                /* 1. */ 
    620622                                if (s->auth_ldap_binddn->used) { 
    621                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) { 
    622                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    623  
    624                                                 return HANDLER_ERROR; 
    625                                         } 
     623                                        credentials.bv_val = s->auth_ldap_bindpw->ptr; 
     624                                        credentials.bv_len = s->auth_ldap_bindpw->used; 
     625                                        binddn_ptr = s->auth_ldap_binddn->ptr; 
    626626                                } else { 
    627                                         if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) { 
    628                                                 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
    629  
    630                                                 return HANDLER_ERROR; 
    631                                         } 
     627                                        credentials.bv_val = NULL; 
     628                                        credentials.bv_len = 0; 
     629                                        binddn_ptr = NULL; 
     630                                } 
     631                                ret = ldap_sasl_bind_s(s->ldap->ldap, s->auth_ldap_binddn->ptr, LDAP_SASL_SIMPLE, &credentials, NULL, NULL, NULL); 
     632                                if(ret != LDAP_SUCCESS) { 
     633                                        log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); 
     634 
     635                                        ldap_memfree(s->ldap->ldap); 
     636                                        s->ldap->ldap = NULL; 
     637                                        return HANDLER_ERROR; 
    632638                                } 
    633639                        } 
     
    638644#endif 
    639645                return HANDLER_GO_ON; 
     646} 
     647 
     648void auth_ldap_cleanup(ldap_plugin_config *p) { 
     649        if (p->ldap != NULL) 
     650                ldap_unbind_ext_s(p->ldap, NULL, NULL); 
     651        p->ldap = NULL; 
    640652} 
    641653