LCOV - code coverage report
Current view: top level - lib - tls.c (source / functions) Hit Total Coverage
Test: smtpd.info Lines: 33 89 37.1 %
Date: 2015-11-25 19:06:20 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /* This file is part of the cmail project (http://cmail.rocks/)
       2             :  * (c) 2015 Fabian "cbdev" Stumpf
       3             :  * License: Simplified BSD (2-Clause)
       4             :  * For further information, consult LICENSE.txt
       5             :  */
       6             : 
       7             : #ifndef CMAIL_NO_TLS
       8             : 
       9           1 : char* tls_modestring(TLSMODE mode){
      10           1 :         switch(mode){
      11             :                 case TLS_NONE:
      12           1 :                         return "TLS_NONE";
      13             :                 case TLS_NEGOTIATE:
      14           0 :                         return "TLS_NEGOTIATE";
      15             :                 case TLS_ONLY:
      16           0 :                         return "TLS_ONLY";
      17             :         }
      18           0 :         return "Unknown";
      19             : }
      20             : 
      21           0 : int tls_handshake(LOGGER log, CONNECTION* conn){
      22             :         int status;
      23             : 
      24             :         do{
      25           0 :                 status=gnutls_handshake(conn->tls_session);
      26           0 :                 if(status){
      27           0 :                         if(gnutls_error_is_fatal(status)){
      28           0 :                                 logprintf(log, LOG_WARNING, "Handshake failed: %s\n", gnutls_strerror(status));
      29           0 :                                 return -1;
      30             :                         }
      31           0 :                         logprintf(log, LOG_WARNING, "Handshake nonfatal: %s\n", gnutls_strerror(status));
      32             :                 }
      33             :         }
      34           0 :         while(status && !gnutls_error_is_fatal(status));
      35           0 :         logprintf(log, LOG_INFO, "TLS Handshake succeeded\n");
      36             : 
      37           0 :         conn->tls_mode=TLS_ONLY;
      38           0 :         return 0;
      39             : }
      40             : 
      41           0 : int tls_init_clientpeer(LOGGER log, CONNECTION* conn, char* remote, gnutls_certificate_credentials_t credentials){
      42             :         int status;
      43             : 
      44           0 :         status=gnutls_init(&(conn->tls_session), GNUTLS_CLIENT);
      45           0 :         if(status){
      46           0 :                 logprintf(log, LOG_WARNING, "Failed to initialize TLS session for client: %s\n", gnutls_strerror(status));
      47           0 :                 return -1;
      48             :         }
      49             : 
      50           0 :         status=gnutls_server_name_set(conn->tls_session, GNUTLS_NAME_DNS, remote, strlen(remote));
      51           0 :         if(status){
      52           0 :                 logprintf(log, LOG_WARNING, "Failed to update TLS server name: %s\n", gnutls_strerror(status));
      53           0 :                 return -1;
      54             :         }
      55             : 
      56           0 :         status=gnutls_credentials_set(conn->tls_session, GNUTLS_CRD_CERTIFICATE, credentials);
      57           0 :         if(status){
      58           0 :                 logprintf(log, LOG_WARNING, "Failed to update TLS credentials: %s\n", gnutls_strerror(status));
      59           0 :                 return -1;
      60             :         }
      61             : 
      62           0 :         status=gnutls_set_default_priority(conn->tls_session); //FIXME this should probably be configurable
      63           0 :         if(status){
      64           0 :                 logprintf(log, LOG_WARNING, "Failed to update client TLS priorities: %s\n", gnutls_strerror(status));
      65           0 :                 return -1;
      66             :         }
      67             : 
      68           0 :         gnutls_handshake_set_timeout(conn->tls_session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
      69           0 :         gnutls_transport_set_int(conn->tls_session, conn->fd);
      70           0 :         gnutls_session_set_ptr(conn->tls_session, (void*)remote);
      71             : 
      72           0 :         return 0;
      73             : }
      74             : 
      75           6 : int tls_init_serverpeer(LOGGER log, CONNECTION* client, gnutls_priority_t tls_priorities, gnutls_certificate_credentials_t tls_cert){
      76             :         int status;
      77             : 
      78           6 :         status=gnutls_init(&(client->tls_session), GNUTLS_SERVER);
      79           6 :         if(status){
      80           0 :                 logprintf(log, LOG_WARNING, "Failed to initialize TLS session for client: %s\n", gnutls_strerror(status));
      81           0 :                 return -1;
      82             :         }
      83             : 
      84           6 :         status=gnutls_priority_set(client->tls_session, tls_priorities);
      85           6 :         if(status){
      86           0 :                 logprintf(log, LOG_WARNING, "Failed to update priority set for client: %s\n", gnutls_strerror(status));
      87             :         }
      88             : 
      89           6 :         status=gnutls_credentials_set(client->tls_session, GNUTLS_CRD_CERTIFICATE, tls_cert);
      90           6 :         if(status){
      91           0 :                 logprintf(log, LOG_WARNING, "Failed to set credentials for client: %s\n", gnutls_strerror(status));
      92           0 :                 return -1;
      93             :         }
      94             : 
      95           6 :         gnutls_certificate_server_set_request(client->tls_session, GNUTLS_CERT_IGNORE);
      96           6 :         gnutls_transport_set_int(client->tls_session, client->fd);
      97             : 
      98           6 :         return 0;
      99             : }
     100             : 
     101             : #ifdef CMAIL_HAVE_LISTENER_TYPE
     102           6 : int tls_init_listener(LOGGER log, LISTENER* listener, char* cert, char* key, char* dh_params_file, char* priorities){
     103           6 :                 ssize_t file_size = 0;
     104           6 :                 uint8_t* file_buffer = NULL;
     105             : 
     106           6 :                 logprintf(log, LOG_DEBUG, "Initializing TLS priorities\n");
     107           6 :                 if(gnutls_priority_init(&(listener->tls_priorities), (priorities)?priorities:"NORMAL", NULL)){
     108           0 :                         logprintf(log, LOG_ERROR, "Failed to initialize TLS priorities\n");
     109           0 :                         return -1;
     110             :                 }
     111             : 
     112           6 :                 logprintf(log, LOG_DEBUG, "Initializing TLS certificate structure\n");
     113           6 :                 if(gnutls_certificate_allocate_credentials(&(listener->tls_cert))){
     114           0 :                         logprintf(log, LOG_ERROR, "Failed to allocate storage for TLS cert structure\n");
     115           0 :                         return -1;
     116             :                 }
     117             : 
     118           6 :                 logprintf(log, LOG_DEBUG, "Initializing TLS certificate\n");
     119           6 :                 if(gnutls_certificate_set_x509_key_file(listener->tls_cert, cert, key, GNUTLS_X509_FMT_PEM)){
     120           0 :                         logprintf(log, LOG_ERROR, "Failed to find key or certificate files\n");
     121           0 :                         return -1;
     122             :                 }
     123             : 
     124           6 :                 logprintf(log, LOG_DEBUG, "Initializing DH parameter structure\n");
     125           6 :                 if(gnutls_dh_params_init(&(listener->tls_dhparams))){
     126           0 :                         logprintf(log, LOG_ERROR, "Failed to initialize Diffie-Hellman parameters\n");
     127           0 :                         return -1;
     128             :                 }
     129             : 
     130           6 :                 if(dh_params_file){
     131             :                         //read dhparams from file
     132           6 :                         logprintf(log, LOG_DEBUG, "Reading Diffie-Hellman parameters from %s\n", dh_params_file);
     133           6 :                         file_size = common_read_file(dh_params_file, &file_buffer);
     134           6 :                         gnutls_datum_t dh_param_data = {
     135             :                                 .data = file_buffer,
     136             :                                 .size = file_size
     137             :                         };
     138             : 
     139           6 :                         if(file_size < 0 || !file_buffer){
     140           0 :                                 logprintf(log, LOG_ERROR, "Failed to read Diffie-Hellman parameters from file\n");
     141           0 :                                 return -1;
     142             :                         }
     143             : 
     144           6 :                         if(gnutls_dh_params_import_pkcs3(listener->tls_dhparams, &dh_param_data, GNUTLS_X509_FMT_PEM)){
     145           0 :                                 logprintf(log, LOG_ERROR, "Failed to import Diffie-Hellman parameters, check file format (should be PEM)\n");
     146           0 :                                 return -1;
     147             :                         }
     148             : 
     149           6 :                         free(file_buffer);
     150             :                 }
     151             :                 else{
     152             :                         //generate new diffie-hellman parameters (kind of slow)
     153           0 :                         logprintf(log, LOG_DEBUG, "Generating Diffie-Hellman parameters\n");
     154           0 :                         if(gnutls_dh_params_generate2(listener->tls_dhparams, gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, TLS_PARAM_STRENGTH))){
     155           0 :                                 logprintf(log, LOG_ERROR, "Failed to generate Diffie-Hellman parameters\n");
     156           0 :                                 return -1;
     157             :                         }
     158             :                 }
     159             : 
     160           6 :                 gnutls_certificate_set_dh_params(listener->tls_cert, listener->tls_dhparams);
     161           6 :                 return 0;
     162             : }
     163             : //CMAIL_LISTENER_TYPE
     164             : #endif
     165             : //CMAIL_NO_TLS
     166             : #endif

Generated by: LCOV version 1.11