Ignore:
Timestamp:
05/09/07 08:48:00 (5 years ago)
Author:
ludovic.rousseau
Message:

ldap-patches from Sandro Wefel
http://www.opensc-project.org/pipermail/opensc-devel/2007-April/009764.html

which offers:

  • support for more than one LDAP server as fallback system
  • support of secure connection (SSL+TLS) because someone may use simple authentication with username and password
  • multiple certificates per attribute
  • LDAP-URI support
  • selection of base, one-level or subtree search
  • timeout support and a somewhat enhanced documentation.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/mappers/ldap_mapper.c

    r238 r268  
    2222 */ 
    2323 
     24/* 
     25 * Sandro Wefel (SaW) <sandro.wefel@informatik.uni-halle.de> added 
     26 *  TLS/SSL support (see autofs-ldap and libnss-ldap) 
     27 *  multiple LDAP-Server support 
     28 *  multi-value certificate entries 
     29 */ 
     30 
    2431#define __LDAP_MAPPER_C_ 
    2532 
     
    4956*/ 
    5057 
     58 
     59static const int LDAP_CONFIG_URI_MAX = 10; 
     60 
     61 
    5162/* 
    52 * TODO: Support for LDAPS Connection 
    53 */ 
     63 * TODO:  
     64 * - Support for SASL-AUTH not included yet, I can't test it 
     65 *   
     66 * - ldap_unbind (*ld) crash if you connect to a SSL port but have set TLS intead SSL 
     67 *   - no idea why!? 
     68 *   - you got no error-massage from your application 
     69 *   - believe skip ldap_unbind (*ld) for a bind handle isn't a good solution 
     70 *  
     71 * - implement searchtimeout 
     72 * - implement ignorecase 
     73 */ 
     74 
     75 
     76enum ldap_ssl_options 
     77{ 
     78  SSL_OFF, 
     79  SSL_LDAPS, 
     80  SSL_START_TLS 
     81}; 
     82 
     83typedef enum ldap_ssl_options ldap_ssl_options_t; 
     84 
     85#ifndef LDAPS_PORT 
     86#define LDAPS_PORT 636 
     87#endif  
     88 
    5489 
    5590/*** Internal vars *****************************************************/ 
    5691 
    57 static const char *ldaphost="localhost"; 
    58 static int ldapport=389; 
    59 static int scope=0; /* 0: LDAP_SCOPE_BASE, 1: LDAP_SCOPE_ONE, 2: LDAP_SCOPE_SUB */ 
     92/* Host and Port */ 
     93static const char *ldaphost=""; 
     94static int ldapport=0; 
     95/* or URI (allow multiple hosts) */ 
     96static const char *ldapURI=""; 
     97static int scope=1; /* 0: LDAP_SCOPE_BASE, 1: LDAP_SCOPE_ONE, 2: LDAP_SCOPE_SUB */ 
    6098static const char *binddn=""; 
    6199static const char *passwd=""; 
     
    65103static int searchtimeout=20; 
    66104static int ignorecase=0; 
    67 static const X509 *ldap_x509; 
     105static const X509 **ldap_x509; 
     106static int certcnt=0; 
     107 
     108static ldap_ssl_options_t ssl_on = SSL_OFF; 
     109#if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) 
     110/* TLS/SSL specific options */ 
     111static const char *tls_randfile=""; 
     112static const char *tls_cacertfile=""; 
     113static const char *tls_cacertdir=""; 
     114static int tls_checkpeer=-1; 
     115static const char *tls_ciphers=""; 
     116static const char *tls_cert="";  
     117static const char *tls_key=""; 
     118#endif 
     119 
     120static int ldapVersion = 3;              
     121#ifdef HAVE_LDAP_SET_OPTION 
     122static int timeout = 8;                 // 8 seconds        
     123#endif 
     124static int bind_timelimit = 2;  // Timelimit for BIND 
     125 
     126static const int sscope[] = { 
     127        LDAP_SCOPE_BASE,  
     128        LDAP_SCOPE_ONELEVEL,  
     129        LDAP_SCOPE_SUBTREE}; 
    68130 
    69131/*** Internal funcs ****************************************************/ 
     132 
     133 
     134static int do_init (LDAP ** ld, const char *uri, int ldapdefport) 
     135{ 
     136        int rc; 
     137        int ldaps; 
     138        char uribuf[512]; 
     139        char *p; 
     140         
     141        DBG("do_init():"); 
     142 
     143        ldaps = (strncasecmp (uri, "ldaps://", sizeof ("ldaps://") - 1) == 0); 
     144        p = strchr (uri, ':'); 
     145        /* we should be looking for the second instance to find the port number */ 
     146        if (p != NULL) 
     147        { 
     148                p = strchr (p, ':'); 
     149        } 
     150 
     151#ifdef HAVE_LDAP_INITIALIZE 
     152        if (p == NULL && 
     153                ((ldaps && ldapdefport != LDAPS_PORT) || (!ldaps && ldapdefport != LDAP_PORT))) 
     154        { 
     155                /* No port specified in URI and non-default port specified */ 
     156                snprintf (uribuf, sizeof (uribuf), "%s:%d", uri, ldapdefport); 
     157                uri = uribuf; 
     158        } 
     159        rc = ldap_initialize (ld, uri); 
     160#else 
     161        // TODO: !HAVE_LDAP_INITIALIZE => no ldaps:// possible? 
     162        if (strncasecmp (uri, "ldap://", sizeof ("ldap://") - 1) != 0) 
     163    { 
     164                return LDAP_UNAVAILABLE; 
     165    } 
     166 
     167        uri += sizeof ("ldap://") - 1; 
     168        p = strchr (uri, ':'); 
     169 
     170        if (p != NULL) 
     171    { 
     172                size_t urilen = (p - uri); 
     173                 
     174                if (urilen >= sizeof (uribuf)) 
     175                { 
     176                        return LDAP_UNAVAILABLE; 
     177                } 
     178                 
     179                memcpy (uribuf, uri, urilen); 
     180                uribuf[urilen] = '\0'; 
     181                 
     182                ldapdefport = atoi (p + 1); 
     183                uri = uribuf; 
     184        } 
     185 
     186# ifdef HAVE_LDAP_INIT 
     187        *ld = ldap_init (uri, defport); 
     188# else 
     189        *ld = ldap_open (uri, defport); 
     190# endif 
     191        rc = (*ld == NULL) ? LDAP_SERVER_DOWN : LDAP_SUCCESS; 
     192 
     193#endif /* HAVE_LDAP_INITIALIZE */ 
     194 
     195        if (rc == LDAP_SUCCESS && *ld == NULL) 
     196        { 
     197                rc = LDAP_UNAVAILABLE; 
     198        } 
     199        return rc; 
     200} 
     201 
     202 
     203#if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) 
     204/*  
     205 * Set the ssl option 
     206 */ 
     207static int do_ssl_options (LDAP *ldap_connection) 
     208{ 
     209        int rc; 
     210 
     211        DBG("do_ssl_options"); 
     212 
     213#ifdef LDAP_OPT_X_TLS_RANDOM_FILE 
     214        if (strncmp(tls_randfile,"",1)) 
     215        { 
     216 
     217                /* rand file */ 
     218                rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, 
     219                    tls_randfile); 
     220                if (rc != LDAP_SUCCESS) 
     221                { 
     222                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_RANDOM_FILE failed"); 
     223                        return LDAP_OPERATIONS_ERROR; 
     224                } 
     225        } 
     226#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ 
     227 
     228        if (strncmp(tls_cacertfile,"",1)) 
     229        { 
     230                /* ca cert file */ 
     231                rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, 
     232                        tls_cacertfile); 
     233                if (rc != LDAP_SUCCESS) 
     234                { 
     235                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_CACERTFILE failed"); 
     236                        return LDAP_OPERATIONS_ERROR; 
     237                } 
     238        } 
     239 
     240        if (strncmp(tls_cacertdir,"",1)) 
     241    { 
     242                /* ca cert directory */ 
     243                rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, 
     244                                    tls_cacertdir); 
     245                if (rc != LDAP_SUCCESS) 
     246                { 
     247                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_CACERTDIR failed"); 
     248                        return LDAP_OPERATIONS_ERROR; 
     249                } 
     250    } 
     251 
     252        /* the cert have to be checked ? */ 
     253        if (tls_checkpeer > -1) 
     254        { 
     255                rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, 
     256                        &tls_checkpeer); 
     257                if (rc != LDAP_SUCCESS) 
     258                { 
     259                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_REQUIRE_CERT failed"); 
     260                        return LDAP_OPERATIONS_ERROR; 
     261                } 
     262        } 
     263 
     264        if (strncmp(tls_ciphers,"",1)) 
     265    { 
     266                /* set cipher suite, certificate and private key: */ 
     267                rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, 
     268                        tls_ciphers); 
     269                if (rc != LDAP_SUCCESS) 
     270                { 
     271                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_CIPHER_SUITE failed"); 
     272                        return LDAP_OPERATIONS_ERROR; 
     273                } 
     274        } 
     275 
     276        /* where is the requiered cert */ 
     277        if (strncmp(tls_cert,"",1)) 
     278    { 
     279            rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE,  
     280                tls_cert); 
     281            if (rc != LDAP_SUCCESS) 
     282                { 
     283                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_CERTFILE failed"); 
     284                        return LDAP_OPERATIONS_ERROR; 
     285                } 
     286    } 
     287 
     288        /* where is the key */ 
     289        if (strncmp(tls_key,"",1)) 
     290        { 
     291                rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE,  
     292                        tls_key); 
     293                if (rc != LDAP_SUCCESS) 
     294                { 
     295                        DBG("do_ssl_options: Setting of LDAP_OPT_X_TLS_KEYFILE failed"); 
     296                        return LDAP_OPERATIONS_ERROR; 
     297                } 
     298        } 
     299        return LDAP_SUCCESS; 
     300} 
     301#endif 
     302 
     303 
     304static int 
     305do_bind (LDAP * ldap_connection, int timelimit) 
     306{ 
     307        int rc; 
     308        int rv; 
     309        struct timeval tv; 
     310        LDAPMessage *result; 
     311 
     312        /* 
     313         * set timelimit in ld for select() call in ldap_pvt_connect()  
     314         * function implemented in libldap2's os-ip.c 
     315         */ 
     316        tv.tv_sec = timelimit; 
     317        tv.tv_usec = 0; 
     318 
     319DBG2("do_bind(): bind DN=\"%s\" pass=\"%s\"",binddn,passwd); 
     320 
     321        /* LDAPv3 doesn't need bind at all,  
     322         * nevertheless, if no binddn is given than bind anonymous */ 
     323        if ( ! strncmp(binddn,"",1) ) { 
     324                rv = ldap_simple_bind(ldap_connection, NULL, NULL); 
     325        } else { 
     326                rv = ldap_simple_bind(ldap_connection, binddn, passwd); 
     327        } 
     328 
     329        if (rv < 0) 
     330        { 
     331DBG("do_bind: rv < 0"); 
     332                 
     333#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) 
     334                if (ldap_get_option (ldap_connection, LDAP_OPT_ERROR_NUMBER, &rc) != 
     335            LDAP_SUCCESS) 
     336                { 
     337                  rc = LDAP_UNAVAILABLE; 
     338                } 
     339#else 
     340                rc = ldap_connection->ld_errno; 
     341#endif /* LDAP_OPT_ERROR_NUMBER */ 
     342                /* Notify if we failed. */ 
     343                DBG3("could not connect to LDAP server as %s - %d - %s", 
     344                  binddn, rc, ldap_err2string (rc)); 
     345 
     346                return rc; 
     347        } 
     348 
     349        rc = ldap_result (ldap_connection, rv, 0, &tv, &result); 
     350        if (rc > 0) 
     351        { 
     352DBG1("do_bind rc=%d", rc); 
     353                //debug ("<== do_bind"); 
     354                return ldap_result2error (ldap_connection, result, 1); 
     355        } 
     356 
     357        /* took too long */ 
     358        if (rc == 0) 
     359        { 
     360DBG("do_bind rc=0"); 
     361                 
     362                ldap_abandon (ldap_connection, rv); 
     363        } 
     364 
     365DBG("do_bind return -1"); 
     366        return -1; 
     367} 
     368 
     369/* 
     370 * Opes connection to an LDAP server 
     371 * uri must be one URI 
     372 */ 
     373static int do_open (LDAP **ld, const char* uri, int defport, ldap_ssl_options_t ssl_on) 
     374{ 
     375         
     376#if defined(LDAP_OPT_NETWORK_TIMEOUT) || defined(HAVE_LDAP_START_TLS)    
     377        struct timeval tv; 
     378#endif 
     379#ifdef HAVE_LDAP_START_TLS 
     380        struct timeval *tvp; 
     381        LDAPMessage *res = NULL; 
     382        int msgid; 
     383#endif   
     384        int rc; 
     385 
     386        rc = do_init (ld, uri, defport); 
     387         
     388        if (rc != LDAP_SUCCESS) 
     389        { 
     390                DBG("do_open(): do_init failed"); 
     391                return rc; 
     392    } 
     393 
     394        if( ! *ld) 
     395        { 
     396                DBG("do_open(): internal error - assert (*ld != NULL)"); 
     397                return(-2); 
     398        } 
     399 
     400#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_PROTOCOL_VERSION) 
     401        ldap_set_option (*ld, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion); 
     402#endif /* LDAP_OPT_PROTOCOL_VERSION */ 
     403 
     404#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) 
     405//      ldap_set_option (*ld, LDAP_OPT_NETWORK_TIMEOUT, &timeout); 
     406 
     407        rc = ldap_set_option(*ld, LDAP_OPT_NETWORK_TIMEOUT, &timeout); 
     408        if ( rc != LDAP_SUCCESS ) { 
     409                DBG2("Warning: failed to set connection timeout to %d: %s", timeout, ldap_err2string(rc)); 
     410        } else 
     411                DBG1("Set connection timeout to %d", timeout); 
     412#endif /* LDAP_OPT_NETWORK_TIMEOUT */ 
     413 
     414#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) 
     415        tv.tv_sec = bind_timelimit; 
     416        tv.tv_usec = 0; 
     417        ldap_set_option (*ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); 
     418#endif /* LDAP_OPT_NETWORK_TIMEOUT */ 
     419 
     420 
     421#if defined(HAVE_LDAP_START_TLS_S) || defined(HAVE_LDAP_START_TLS) 
     422        if (ssl_on == SSL_START_TLS) 
     423    { 
     424                int version; 
     425 
     426                // we need V3 at least 
     427                if (ldap_get_option(*ld, LDAP_OPT_PROTOCOL_VERSION, 
     428                                                        &version) == LDAP_OPT_SUCCESS) 
     429                { 
     430                        if (ldapVersion < LDAP_VERSION3) 
     431                        { 
     432                                ldapVersion = LDAP_VERSION3; 
     433                                ldap_set_option (*ld, LDAP_OPT_PROTOCOL_VERSION, 
     434                                                &ldapVersion); 
     435                } 
     436                } 
     437 
     438                /* set up SSL context */ 
     439                if (do_ssl_options (*ld) != LDAP_SUCCESS) 
     440                { 
     441                        ldap_unbind (*ld); 
     442                        DBG("do_open(): SSL setup failed"); 
     443                        return LDAP_UNAVAILABLE; 
     444                } 
     445 
     446#ifdef HAVE_LDAP_START_TLS 
     447 
     448                DBG("do_open(): do_start_tls"); 
     449                rc = ldap_start_tls (*ld, NULL, NULL, &msgid); 
     450                if (rc != LDAP_SUCCESS) 
     451                { 
     452                  DBG1("do_open(): ldap_start_tls failed: %s", ldap_err2string (rc)); 
     453                  return rc; 
     454                } 
     455 
     456                if (bind_timelimit == LDAP_NO_LIMIT) 
     457                { 
     458                        tvp = NULL; 
     459        } 
     460                else 
     461        { 
     462                tv.tv_sec = bind_timelimit; 
     463                tv.tv_usec = 0; 
     464                tvp = &tv; 
     465        } 
     466 
     467                rc = ldap_result (*ld, msgid, 1, tvp, &res); 
     468                if (rc == -1) 
     469                { 
     470#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) 
     471                        if (ldap_get_option (*ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_SUCCESS) 
     472                        { 
     473                                rc = LDAP_UNAVAILABLE; 
     474                        } 
     475#else 
     476                        rc = ld->ld_errno; 
     477#endif /* LDAP_OPT_ERROR_NUMBER */ 
     478 
     479                        DBG1("do_open(): ldap_start_tls failed: %s", ldap_err2string (rc)); 
     480                        return rc; 
     481                } 
     482 
     483                rc = ldap_result2error (*ld, res, 1); 
     484                if (rc != LDAP_SUCCESS) 
     485                { 
     486                        DBG1("do_open(): ldap_result2error failed: %s)", ldap_err2string (rc)); 
     487                        return rc; 
     488                } 
     489 
     490                rc = ldap_install_tls (*ld); 
     491#else 
     492                rc = ldap_start_tls_s (*ld, NULL, NULL); 
     493#endif /* HAVE_LDAP_START_TLS */ 
     494 
     495                if (rc == LDAP_SUCCESS) 
     496                { 
     497                        DBG("do_open(): TLS startup succeeded"); 
     498                } 
     499                else 
     500                { 
     501                        ldap_unbind (*ld); 
     502                        DBG2("do_open(): TLS startup failed for LDAP server %s: %s", 
     503                             uri, ldap_err2string (rc)); 
     504                    return rc; 
     505                } 
     506        } 
     507        else 
     508#endif /* HAVE_LDAP_START_TLS_S || HAVE_LDAP_START_TLS */ 
     509 
     510        /* 
     511         * If SSL is desired, then enable it. 
     512         */ 
     513        if (ssl_on == SSL_LDAPS) 
     514    { 
     515#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS) 
     516                int tls = LDAP_OPT_X_TLS_HARD; 
     517                if (ldap_set_option (*ld, LDAP_OPT_X_TLS, &tls) != 
     518                        LDAP_SUCCESS) 
     519                { 
     520                        ldap_unbind (*ld); 
     521                        DBG("do_open(): TLS setup failed"); 
     522                        return LDAP_UNAVAILABLE; 
     523                } 
     524 
     525                /* set up SSL context */ 
     526                if (do_ssl_options (*ld) != LDAP_SUCCESS) 
     527                { 
     528                        ldap_unbind (*ld); 
     529                        DBG("do_open(): SSL setup failed"); 
     530                        return LDAP_UNAVAILABLE; 
     531                } 
     532#endif           
     533    } 
     534         
     535        rc = do_bind (*ld, bind_timelimit); 
     536        if (rc != LDAP_SUCCESS) 
     537        { 
     538                DBG2("do_open(): failed to bind to LDAP server %s: %s", 
     539                         uri, ldap_err2string (rc)); 
     540                ldap_unbind (*ld); 
     541        } 
     542        return rc; 
     543} 
     544 
     545/* 
     546 * add singe URI to array of uris 
     547 */ 
     548int ldap_add_uri (char **uris, const char *a_uri, char **buffer, size_t *buflen) 
     549{ 
     550        int i; 
     551        size_t uri_len; 
     552 
     553        for (i = 0; uris[i] != NULL; i++) 
     554    ; 
     555 
     556        if (i == LDAP_CONFIG_URI_MAX) 
     557        { 
     558                DBG("maximum number of URIs exceeded"); 
     559                return -1; 
     560        } 
     561 
     562        uri_len = strlen (a_uri); 
     563 
     564        if (*buflen < uri_len + 1) 
     565        { 
     566                DBG("buffer to small for URI"); 
     567                return -1; 
     568        } 
     569 
     570        memcpy (*buffer, a_uri, uri_len + 1); 
     571 
     572        uris[i] = *buffer; 
     573        uris[i + 1] = NULL; 
     574 
     575        *buffer += uri_len + 1; 
     576        *buflen -= uri_len + 1; 
     577 
     578        DBG1("added URI %s", a_uri); 
     579 
     580        return 0; 
     581} 
     582 
     583 
    70584 
    71585/** 
    72586* Get certificate from LDAP-Server. 
    73587*/ 
     588// not global then  
     589//  static int ldap_get_certificate(const char *login, X509*** ldap_x509) { 
    74590static int ldap_get_certificate(const char *login) { 
    75591        LDAP *ldap_connection; 
     
    82598        char filter_str[100]; 
    83599        char *attrs[2]; 
     600        int rv; 
     601        void *bv_val; 
     602 
     603        char uri[4096]; 
     604        char uribuf[4096]; 
     605        char *uris[LDAP_CONFIG_URI_MAX + 1]; 
     606        const char *p; 
     607        int current_uri = 0, start_uri = 0; 
     608 
     609        uris[0] = NULL; 
    84610 
    85611        attrs[0] = (char *)attribute; 
    86612        attrs[1] = NULL; 
    87          
    88613 
    89614        DBG1("ldap_get_certificate(): begin login = %s", login); 
    90615 
     616        // Put the login to the %s in Filterstring 
    91617        snprintf(filter_str, sizeof(filter_str), filter, login);  
    92618 
    93619        DBG1("ldap_get_certificate(): filter_str = %s", filter_str); 
    94620         
    95         ldap_connection = ldap_init(ldaphost, ldapport); 
    96         if ( NULL == ldap_connection) { 
    97                 DBG("ldap_init() failed"); 
     621        // parse and split URI config entry   
     622        char *buffer = uribuf; 
     623    size_t buflen = sizeof (uribuf); 
     624 
     625        strncpy(uri, ldapURI, sizeof (uri)-1); 
     626 
     627        /* Add a space separated list of URIs */ 
     628        // TODO: no spaces in one URI allowed => URL-encoding?  
     629        if(strncmp(ldapURI,"",1)) 
     630                for (p = uri; p != NULL; ) 
     631                { 
     632                        char *q = strchr (p, ' '); 
     633                        if (q != NULL) 
     634                                *q = '\0'; 
     635                         
     636                        if( strlen(p) > 1 ) // SAW: don't add spaces    
     637                                rv = ldap_add_uri (uris, p, &buffer, &buflen); 
     638                         
     639                        p = (q != NULL) ? ++q : NULL; 
     640                         
     641                        if (rv) 
     642                                break; 
     643                } 
     644    // set the default port if no port is given 
     645        if (ldapport == 0) 
     646    { 
     647                if (ssl_on == SSL_LDAPS) 
     648                { 
     649                  ldapport = LDAPS_PORT; 
     650                } 
     651                else 
     652                { 
     653                  ldapport = LDAP_PORT; 
     654                } 
     655        } 
     656 
     657        // add ldaphost to uris if set, nevermind "uri" is set in config 
     658        if( strlen(ldaphost) > 1 ) 
     659        { 
     660                /* No port specified in URI and non-default port specified */ 
     661                snprintf (uri, sizeof (uri), "%s%s:%d",  
     662                       ssl_on == SSL_LDAPS ? "ldaps://" : "ldap://", 
     663                       ldaphost, ldapport); 
     664                rv = ldap_add_uri (uris, uri, &buffer, &buflen); 
     665        } 
     666 
     667        if (uris[0] == NULL) 
     668    { 
     669                DBG("ldap_get_certificate(): Nor URI or useable Host entry found"); 
    98670                return(-1); 
    99         } 
    100  
    101         if ( 0 != ldap_simple_bind_s(ldap_connection, binddn, passwd)) { 
    102                 DBG("ldap_simple_bind_s() failed"); 
     671    } 
     672         
     673        /* Attempt to connect to specified URI in order until do_open succeed */ 
     674        start_uri = current_uri; 
     675        do 
     676        { 
     677                if(uris[current_uri] != NULL) 
     678                        DBG1("ldap_get_certificate(): try do_open for %s", uris[current_uri]); 
     679                rv = do_open(&ldap_connection, uris[current_uri], ldapport, ssl_on); 
     680                //  hot-fix, because in some circumstances an LDAP_SERVER_DOWN is returned   
     681                if (rv != LDAP_UNAVAILABLE && rv != LDAP_SERVER_DOWN) 
     682                        break; 
     683                current_uri++; 
     684                 
     685                if (uris[current_uri] == NULL) 
     686                        current_uri = 0; 
     687        } 
     688        while (current_uri != start_uri); 
     689         
     690        if( rv != LDAP_SUCCESS ) 
     691        { 
     692                DBG("ldap_get_certificate(): do_open failed"); 
    103693                return(-2); 
    104694        } 
    105695 
    106         if ( LDAP_SUCCESS != ldap_search_s(ldap_connection, base, LDAP_SCOPE_SUBTREE, filter_str, attrs, 0, &res)) { 
    107                 DBG("ldap_search_s() failed"); 
     696        /* TODO: (1) The problem: if an working uri is found it is used 
     697             and if there is an (SSL-)error, no other one is tried 
     698             (2) There is no session, so we don't know which LDAP_Server 
     699             is the last with a successful connection. So we try the same 
     700             server again. Perhaps create a state file/smem/etc. ? 
     701    */ 
     702 
     703        rv = ldap_search_s( 
     704                                ldap_connection,  
     705                                base,  
     706                                sscope[scope],  
     707                                filter_str,  
     708                                attrs,  
     709                                0,  
     710                                &res); 
     711        if ( rv != LDAP_SUCCESS ) { 
     712                DBG1("ldap_search_s() failed: %s", ldap_err2string(rv)); 
    108713                ldap_unbind_s(ldap_connection); 
    109714                return(-3); 
     
    112717                DBG1("ldap_get_certificate(): entries = %d", entries); 
    113718 
     719                if( entries > 1 ) { 
     720                        DBG("!  Warning, more than one entry found. Please choose \"filter\" and");  
     721                        DBG("!  \"attribute\" in ldap mapper config section of your config,"); 
     722                        DBG("!  that only one entry with one attribute is matched"); 
     723                        DBG("!  Maybe there is an other problem in ldap with not unique user"); 
     724                        DBG("!  entries in your LDAP server."); 
     725                } 
     726                                 
    114727                /* Only first entry is used. "filter" and "attribute"  
    115728                 *  should be choosen, so that only one entry with 
    116729                 * one attribute is returned */ 
    117730                if ( NULL == (entry = ldap_first_entry(ldap_connection, res))){ 
    118                         DBG("ldap_first_entry() failed"); 
     731                        DBG("ldap_first_entry() failed: %s"); 
    119732                        ldap_unbind_s(ldap_connection); 
    120733                        return(-4); 
     
    129742                DBG1("attribute name = %s", name); 
    130743 
    131                 /* TODO: Add support for multi-value attribute for usercertificate */ 
    132744                bvals = ldap_get_values_len(ldap_connection, entry, name); 
    133                 ldap_x509 = d2i_X509(NULL, (unsigned char **) &bvals[0]->bv_val, bvals[0]->bv_len); 
    134                 if (NULL == ldap_x509) { 
    135                         DBG("d2i_X509() failed"); 
    136                         ldap_msgfree(res); 
    137                         ldap_unbind_s(ldap_connection); 
    138                         return(-6); 
    139                 }else { 
    140                         DBG("d2i_X509(): success"); 
     745                certcnt = ldap_count_values_len(bvals); 
     746 
     747                DBG1("number auf usercertificates = %d", certcnt); 
     748         
     749                //*ldap_x509 = malloc(sizeof(X509*) * certcnt ); 
     750                ldap_x509 = malloc(sizeof(X509*) * certcnt ); 
     751                 
     752                rv = 0; 
     753                while(rv < certcnt ) 
     754                { 
     755                        // SaW: not nifty, but otherwise gcc doesn't optimize 
     756                        bv_val = &bvals[rv]->bv_val; 
     757                        ldap_x509[rv] = d2i_X509(NULL, ((const unsigned char **) bv_val), bvals[rv]->bv_len); 
     758                        if (NULL == ldap_x509) { 
     759                                DBG1("d2i_X509() failed for certificate %d", rv); 
     760                                free(ldap_x509);                                 
     761                                certcnt=0; 
     762                                ldap_msgfree(res); 
     763                                ldap_unbind_s(ldap_connection); 
     764                                return(-6); 
     765                        }else { 
     766                                DBG1("d2i_X509(): success for certificate %d", rv); 
     767                        } 
     768                        rv++; 
    141769                } 
    142770                ldap_msgfree(res); 
     771                // TODO: this leads to a segfault, but the doc said ... 
     772                //      ldap_value_free_len(bvals); 
    143773        } 
    144774        if ( 0 != (ret = ldap_unbind_s(ldap_connection))) { 
     
    156786        ldaphost = scconf_get_str(blk,"ldaphost",ldaphost); 
    157787        ldapport = scconf_get_int(blk,"ldapport",ldapport); 
     788        ldapURI = scconf_get_str(blk,"uri",ldapURI); 
    158789        scope = scconf_get_int(blk,"scope",scope); 
    159790        binddn = scconf_get_str(blk,"binddn",binddn); 
     
    165796        searchtimeout = scconf_get_int(blk,"searchtimeout",searchtimeout); 
    166797 
     798        const char *ssltls =  scconf_get_str(blk,"ssl","off"); 
     799        if (! strncasecmp (ssltls, "tls", 3))  
     800                ssl_on = SSL_START_TLS; 
     801        else if( ! strncasecmp (ssltls, "on", 2)) 
     802                ssl_on = SSL_LDAPS; 
     803        else if( ! strncasecmp (ssltls, "ssl", 3)) 
     804                ssl_on = SSL_LDAPS; 
     805                 
     806#if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) 
     807        /* TLS specific options */ 
     808        tls_randfile = scconf_get_str(blk,"tls_randfile",tls_randfile); 
     809        tls_cacertfile = scconf_get_str(blk,"tls_cacertfile",tls_cacertfile); 
     810        tls_cacertdir = scconf_get_str(blk,"tls_cacertdir",tls_cacertdir); 
     811        tls_checkpeer=scconf_get_int(blk,"tls_checkpeer",tls_checkpeer); 
     812        tls_ciphers = scconf_get_str(blk,"tls_ciphers",tls_ciphers); 
     813        tls_cert = scconf_get_str(blk,"tls_cert",tls_cert);  
     814        tls_key = scconf_get_str(blk,"tls_key",tls_key); 
     815#endif 
     816 
     817 
    167818        set_debug_level(debug); 
     819DBG1("test ssltls = %s", ssltls); 
    168820 
    169821        DBG("LDAP mapper started."); 
    170         DBG1("debug      = %d", debug); 
    171         DBG1("ignorecase = %d", ignorecase); 
    172         DBG1("ldaphost   = %s", ldaphost); 
    173         DBG1("ldapport   = %d", ldapport); 
    174         DBG1("scope      = %d", scope); 
    175         DBG1("binddn     = %s", binddn); 
    176         DBG1("passwd     = %s", passwd); 
    177         DBG1("base       = %s", base); 
    178         DBG1("attribute  = %s", attribute); 
    179         DBG1("filter     = %s", filter); 
     822        DBG1("debug         = %d", debug); 
     823        DBG1("ignorecase    = %d", ignorecase); 
     824        DBG1("ldaphost      = %s", ldaphost); 
     825        DBG1("ldapport      = %d", ldapport); 
     826        DBG1("ldapURI       = %s", ldapURI); 
     827        DBG1("scope         = %d", scope); 
     828        DBG1("binddn        = %s", binddn); 
     829        DBG1("passwd        = %s", passwd); 
     830        DBG1("base          = %s", base); 
     831        DBG1("attribute     = %s", attribute); 
     832        DBG1("filter        = %s", filter); 
     833        DBG1("searchtimeout = %d", searchtimeout); 
     834        DBG1("ssl_on        = %d", ssl_on); 
     835#if defined HAVE_LDAP_START_TLS_S || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) 
     836        DBG1("tls_randfile  = %s", tls_randfile); 
     837        DBG1("tls_cacertfile= %s", tls_cacertfile); 
     838        DBG1("tls_cacertdir = %s", tls_cacertdir); 
     839        DBG1("tls_checkpeer = %d", tls_checkpeer); 
     840        DBG1("tls_ciphers   = %s", tls_ciphers); 
     841        DBG1("tls_cert      = %s", tls_cert);  
     842        DBG1("tls_key       = %s", tls_key);     
     843#endif 
    180844        return 1; 
    181845 
     
    194858 
    195859static int ldap_mapper_match_user(X509 *x509, const char *login, void *context) { 
     860        //X509 **ldap_x509 = 0; 
    196861        int match_found = 0; 
    197  
     862        int i=0; 
     863 
     864        //if ( 1 != ldap_get_certificate(login, &ldap_x509)){ 
    198865        if ( 1 != ldap_get_certificate(login)){ 
    199866                DBG("ldap_get_certificate() failed"); 
     
    201868        } else { 
    202869                /* TODO: maybe compare public keys instead of hashes */ 
    203                 if ( 0 == X509_cmp(x509, ldap_x509)) { 
    204                         DBG("Certifcates matching"); 
    205                         match_found = 1; 
    206                 } else { 
    207                         DBG("Certifcates NOT matching"); 
    208                         match_found = 0; 
    209                 } 
     870                while( i<certcnt && !match_found ) { 
     871                        if ( 0 == X509_cmp(x509, ldap_x509[i])) { 
     872                                DBG1("Certificate %d is matching", i); 
     873                                match_found = 1; 
     874                        } else {  
     875                                DBG1("Certificate %d is NOT matching", i); 
     876                        } 
     877                        i++; 
     878                } 
     879                if (certcnt)  
     880                        free(ldap_x509); 
     881                certcnt=0; 
    210882        } 
    211883        return match_found; 
     
    229901        } 
    230902        endpwent(); 
     903 
     904#ifdef false 
     905        int res;         
     906        res= ldap_mapper_match_user(x509,"wefel",context); 
     907        if (res) { 
     908                        DBG("Certificate maps to user wefel"); 
     909                        found= clone_str("wefel"); 
     910        } else { 
     911                        DBG("Certificate map to user wefel failed"); 
     912        } 
     913#endif 
     914         
    231915        return found; 
    232916} 
     
    253937        mapper_module *pt; 
    254938 
    255         pt = init_mapper_st(blk,mapper_name); 
     939    pt = init_mapper_st(blk,mapper_name); 
    256940 
    257941        if (blk) { 
     
    261945                DBG1("No configuration entry for mapper '%s'. Assume defaults", mapper_name); 
    262946        } 
    263          
    264         return pt; 
    265 } 
     947    return pt; 
     948} 
Note: See TracChangeset for help on using the changeset viewer.