Changeset 1893

Show
Ignore:
Timestamp:
08/22/08 01:17:09 (3 months ago)
Author:
alo
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • cherokee/trunk/ChangeLog

    r1890 r1893  
    112008-08-21  Alvaro Lopez Ortega  <alvaro@alobbs.com> 
     2 
     3        * cherokee/virtual_server.c, cherokee/virtual_server.h, 
     4        cherokee/socket.c: Adds TLS SNI support to the GNUTLS backend. 
    25 
    36        * cherokee/virtual_server.c, cherokee/socket.c, cherokee/socket.h, 
  • cherokee/trunk/cherokee/socket.c

    r1890 r1893  
    344344 
    345345static ret_t 
    346 initialize_tls_session (cherokee_socket_t *socket, cherokee_virtual_server_t *vserver) 
    347 
     346initialize_tls_session (cherokee_socket_t         *socket,  
     347                        cherokee_virtual_server_t *vserver) 
     348
     349# if defined(HAVE_GNUTLS) 
    348350        int re; 
    349  
     351         
    350352        /* Set the virtual server object reference 
    351353         */ 
    352354        socket->vserver_ref = vserver; 
    353355 
    354 # if defined(HAVE_GNUTLS) 
    355356        /* Init the TLS session 
    356357         */ 
    357358        re = gnutls_init (&socket->session, GNUTLS_SERVER); 
    358         if (unlikely (re != GNUTLS_E_SUCCESS)) return ret_error; 
     359        if (unlikely (re != GNUTLS_E_SUCCESS)) 
     360                return ret_error; 
     361 
     362        gnutls_session_set_ptr (socket->session, socket); 
    359363 
    360364        /* Set the socket file descriptor 
    361365         */ 
    362       gnutls_transport_set_ptr (socket->session, (gnutls_transport_ptr)socket->socket); 
     366      gnutls_transport_set_ptr (socket->session, (gnutls_transport_ptr)socket->socket); 
    363367 
    364368        /* Load the credentials 
     
    380384        gnutls_credentials_set (socket->session, GNUTLS_CRD_CERTIFICATE, vserver->credentials); 
    381385         
    382         /* Request client certificate if any. 
    383          */ 
    384         gnutls_certificate_server_set_request (socket->session, GNUTLS_CERT_REQUEST); 
    385  
    386386        /* Set the number of bits, for use in an Diffie Hellman key 
    387387         * exchange: minimum size of the prime that will be used for 
     
    397397        gnutls_db_set_ptr               (socket->session, socket); 
    398398 
     399        /* Request client certificate if any. 
     400         */ 
     401        gnutls_certificate_server_set_request (socket->session, GNUTLS_CERT_REQUEST); 
     402        gnutls_handshake_set_private_extensions (socket->session, 1); 
     403 
    399404# elif defined (HAVE_OPENSSL) 
     405        int re; 
     406 
     407        /* Set the virtual server object reference 
     408         */ 
     409        socket->vserver_ref = vserver; 
    400410 
    401411        /* New session 
  • cherokee/trunk/cherokee/virtual_server.c

    r1890 r1893  
    3636 
    3737#define ENTRIES "vserver" 
     38#define MAX_HOST_LEN 255 
    3839 
    3940 
     
    8485# ifdef HAVE_GNUTLS 
    8586        n->credentials     = NULL; 
     87        n->privkey_x509    = NULL; 
     88        n->certs_x509      = NULL; 
    8689# endif 
    8790# ifdef HAVE_OPENSSL 
     
    137140                vserver->credentials = NULL; 
    138141        } 
     142        if (vserver->privkey_x509 != NULL) { 
     143                gnutls_x509_privkey_deinit (vserver->privkey_x509); 
     144        } 
     145        if (vserver->certs_x509 != NULL) { 
     146                gnutls_x509_crt_deinit (vserver->certs_x509); 
     147        } 
     148 
    139149# endif 
    140150# ifdef HAVE_OPENSSL 
     
    220230 
    221231 
    222 #ifndef OPENSSL_NO_TLSEXT  
     232#if defined(HAVE_OPENSSL) && !defined(OPENSSL_NO_TLSEXT) 
    223233static int 
    224234openssl_sni_servername_cb (SSL *ssl, int *ad, void *arg) 
     
    274284 
    275285 
     286#ifdef HAVE_TLS 
     287static int 
     288gnutls_sni_servername_cb (gnutls_session_t  session,  
     289                          gnutls_retr_st   *retr) 
     290{ 
     291        int                        re; 
     292        ret_t                      ret; 
     293        cherokee_buffer_t          tmp; 
     294        cherokee_socket_t         *socket; 
     295        cherokee_server_t         *srv; 
     296        char                       name[MAX_HOST_LEN]; 
     297        size_t                     data_len             = MAX_HOST_LEN; 
     298        unsigned int               type                 = 0; 
     299        cherokee_virtual_server_t *vsrv                 = NULL; 
     300 
     301        re = gnutls_server_name_get (session, name, &data_len, &type, 0); 
     302        if (re != 0) { 
     303                TRACE (ENTRIES, "No SNI: Did not provide a server name%s", "\n"); 
     304                return 0; 
     305        } 
     306         
     307        if (type != GNUTLS_NAME_DNS) { 
     308                TRACE (ENTRIES, "SNI: Not a name entry: '%s'\n", name); 
     309                return 0; 
     310        } 
     311 
     312        TRACE (ENTRIES, "SNI: Switching to servername='%s'\n", name); 
     313 
     314        socket = gnutls_session_get_ptr (session); 
     315        if (socket == NULL) { 
     316                PRINT_ERROR ("Could not access the socket struct: %s\n", name); 
     317                return -1; 
     318        } 
     319 
     320        srv = VSERVER_SRV(socket->vserver_ref); 
     321         
     322        cherokee_buffer_fake (&tmp, name, data_len); 
     323        ret = cherokee_server_get_vserver (srv, &tmp, &vsrv); 
     324        if ((ret != ret_ok) || (vsrv == NULL)) { 
     325                PRINT_ERROR ("Servername did not match: '%s'\n", name); 
     326                return -1;  
     327        } 
     328 
     329        TRACE (ENTRIES, "SNI: Setting new TLS context. Virtual host='%s'\n", 
     330               vsrv->name.buf); 
     331             
     332        retr->deinit_all = 0; 
     333        retr->type       = GNUTLS_CRT_X509; 
     334        retr->ncerts     = 1; 
     335        retr->cert.x509  = &vsrv->certs_x509; 
     336        retr->key.x509   = vsrv->privkey_x509; 
     337 
     338        return 0; 
     339} 
     340#endif 
     341 
     342# ifdef HAVE_GNUTLS 
     343static int 
     344set_x509_key_file (cherokee_virtual_server_t *vsrv) 
     345{ 
     346        int               rc; 
     347        gnutls_datum_t    data; 
     348        unsigned int      max = 1; 
     349        cherokee_buffer_t tmp = CHEROKEE_BUF_INIT; 
     350 
     351        /* This function does basically the same as the previous call to: 
     352         * 
     353         *  rc = gnutls_certificate_set_x509_key_file (vsrv->credentials, 
     354         *                                         vsrv->server_cert.buf, 
     355         *                                         vsrv->server_key.buf, 
     356         *                                         GNUTLS_X509_FMT_PEM); 
     357         * 
     358         * but it keeps pointers to the X509 certs and privkey, which 
     359         * was needed for the SNI callback function. 
     360         */ 
     361 
     362        /* X509 private key 
     363         */ 
     364        cherokee_buffer_read_file (&tmp, vsrv->server_key.buf); 
     365        data.data = (unsigned char *)tmp.buf; 
     366        data.size = tmp.len; 
     367 
     368        rc = gnutls_x509_privkey_init (&vsrv->privkey_x509); 
     369        if (rc < 0) 
     370                goto error; 
     371 
     372        rc = gnutls_x509_privkey_import (vsrv->privkey_x509, &data, GNUTLS_X509_FMT_PEM); 
     373        if (rc < 0) 
     374                goto error; 
     375 
     376        /* X509 Certificate 
     377         */ 
     378        cherokee_buffer_clean (&tmp); 
     379        cherokee_buffer_read_file (&tmp, vsrv->server_cert.buf); 
     380        data.data = (unsigned char *)tmp.buf; 
     381        data.size = tmp.len; 
     382         
     383        gnutls_x509_crt_list_import (&vsrv->certs_x509, &max, &data, GNUTLS_X509_FMT_PEM, 0); 
     384 
     385        /* Update the credentials 
     386         */ 
     387        rc = gnutls_certificate_set_x509_key (vsrv->credentials, 
     388                                              &vsrv->certs_x509, 1, 
     389                                              vsrv->privkey_x509); 
     390        if (rc < 0) 
     391                goto error; 
     392 
     393        /* Clean up  
     394         */ 
     395        cherokee_buffer_mrproper (&tmp); 
     396        return 0; 
     397 
     398error: 
     399        cherokee_buffer_mrproper (&tmp); 
     400        return rc; 
     401} 
     402#endif 
     403 
     404 
    276405ret_t  
    277406cherokee_virtual_server_init_tls (cherokee_virtual_server_t *vsrv) 
     
    290419        /* Check one or more are empty 
    291420         */ 
    292         if (cherokee_buffer_is_empty (&vsrv->ca_cert)    || 
    293             cherokee_buffer_is_empty (&vsrv->server_key) || 
     421        if (cherokee_buffer_is_empty (&vsrv->server_key) || 
    294422            cherokee_buffer_is_empty (&vsrv->server_cert)) 
    295423                return ret_error; 
     
    304432        /* CA file 
    305433         */ 
    306         rc = gnutls_certificate_set_x509_trust_file (vsrv->credentials, 
    307                                                      vsrv->ca_cert.buf, 
    308                                                      GNUTLS_X509_FMT_PEM); 
    309         if (rc < 0) { 
    310                 PRINT_ERROR ("ERROR: reading X.509 CA Certificate: '%s'\n", vsrv->ca_cert.buf); 
    311                 return ret_error; 
     434        if (! cherokee_buffer_is_empty (&vsrv->ca_cert)) 
     435        { 
     436                rc = gnutls_certificate_set_x509_trust_file (vsrv->credentials, 
     437                                                             vsrv->ca_cert.buf, 
     438                                                             GNUTLS_X509_FMT_PEM); 
     439                if (rc < 0) { 
     440                        PRINT_ERROR ("ERROR: reading X.509 CA Certificate: '%s'\n",  
     441                                     vsrv->ca_cert.buf); 
     442                        return ret_error; 
     443                } 
    312444        } 
    313445 
    314446        /* Key file 
    315447         */ 
    316         rc = gnutls_certificate_set_x509_key_file (vsrv->credentials, 
    317                                                    vsrv->server_cert.buf, 
    318                                                    vsrv->server_key.buf, 
    319                                                    GNUTLS_X509_FMT_PEM);         
     448        rc = set_x509_key_file (vsrv); 
    320449        if (rc < 0) { 
    321450                PRINT_ERROR ("ERROR: reading X.509 key '%s' or certificate '%s' file\n",  
     
    324453        } 
    325454 
     455        /* SNI  
     456         */ 
     457        gnutls_certificate_server_set_retrieve_function (vsrv->credentials, 
     458                                                         gnutls_sni_servername_cb); 
     459 
     460 
     461        /* Ciphers 
     462         */ 
    326463        generate_dh_params (&vsrv->dh_params); 
    327464        generate_rsa_params (&vsrv->rsa_params); 
  • cherokee/trunk/cherokee/virtual_server.h

    r1715 r1893  
    3232# include <gnutls/extra.h> 
    3333# include <gnutls/gnutls.h> 
     34# include <gnutls/x509.h> 
    3435#endif 
    3536 
     
    8384        cherokee_avl_r_t             session_cache; 
    8485 
    85 # ifdef HAVE_GNUTLS 
     86# ifdef HAVE_GNUTLS    
    8687        gnutls_certificate_server_credentials credentials; 
     88        gnutls_x509_privkey_t                 privkey_x509; 
     89        gnutls_x509_crt_t                     certs_x509; 
     90 
    8791        gnutls_dh_params             dh_params; 
    8892        gnutls_rsa_params            rsa_params;