Home | History | Annotate | Line # | Download | only in dist
      1  1.1  christos /*
      2  1.1  christos  * Copyright (c) 2002 - 2003
      3  1.1  christos  * NetGroup, Politecnico di Torino (Italy)
      4  1.1  christos  * All rights reserved.
      5  1.1  christos  *
      6  1.1  christos  * Redistribution and use in source and binary forms, with or without
      7  1.1  christos  * modification, are permitted provided that the following conditions
      8  1.1  christos  * are met:
      9  1.1  christos  *
     10  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11  1.1  christos  * notice, this list of conditions and the following disclaimer.
     12  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  christos  * notice, this list of conditions and the following disclaimer in the
     14  1.1  christos  * documentation and/or other materials provided with the distribution.
     15  1.1  christos  * 3. Neither the name of the Politecnico di Torino nor the names of its
     16  1.1  christos  * contributors may be used to endorse or promote products derived from
     17  1.1  christos  * this software without specific prior written permission.
     18  1.1  christos  *
     19  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  1.1  christos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  1.1  christos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  1.1  christos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  1.1  christos  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  1.1  christos  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  1.1  christos  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  1.1  christos  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  1.1  christos  *
     31  1.1  christos  */
     32  1.1  christos 
     33  1.1  christos #include <config.h>
     34  1.1  christos 
     35  1.1  christos #ifdef HAVE_OPENSSL
     36  1.1  christos #include <stdlib.h>
     37  1.1  christos 
     38  1.2  christos #include "sslutils.h"
     39  1.1  christos #include "portability.h"
     40  1.1  christos 
     41  1.1  christos 
     42  1.1  christos static const char *ssl_keyfile = "";   //!< file containing the private key in PEM format
     43  1.1  christos static const char *ssl_certfile = "";  //!< file containing the server's certificate in PEM format
     44  1.1  christos static const char *ssl_rootfile = "";  //!< file containing the list of CAs trusted by the client
     45  1.1  christos // TODO: a way to set ssl_rootfile from the command line, or an envvar?
     46  1.1  christos 
     47  1.1  christos // TODO: lock?
     48  1.1  christos static SSL_CTX *ctx;
     49  1.1  christos 
     50  1.1  christos void ssl_set_certfile(const char *certfile)
     51  1.1  christos {
     52  1.1  christos 	ssl_certfile = certfile;
     53  1.1  christos }
     54  1.1  christos 
     55  1.1  christos void ssl_set_keyfile(const char *keyfile)
     56  1.1  christos {
     57  1.1  christos 	ssl_keyfile = keyfile;
     58  1.1  christos }
     59  1.1  christos 
     60  1.1  christos int ssl_init_once(int is_server, int enable_compression, char *errbuf, size_t errbuflen)
     61  1.1  christos {
     62  1.1  christos 	static int inited = 0;
     63  1.1  christos 	if (inited) return 0;
     64  1.1  christos 
     65  1.1  christos 	SSL_library_init();
     66  1.1  christos 	SSL_load_error_strings();
     67  1.1  christos 	OpenSSL_add_ssl_algorithms();
     68  1.1  christos 	if (enable_compression)
     69  1.1  christos 		SSL_COMP_get_compression_methods();
     70  1.1  christos 
     71  1.1  christos 	SSL_METHOD const *meth =
     72  1.1  christos 	    is_server ? SSLv23_server_method() : SSLv23_client_method();
     73  1.1  christos 	ctx = SSL_CTX_new(meth);
     74  1.1  christos 	if (! ctx)
     75  1.1  christos 	{
     76  1.1  christos 		snprintf(errbuf, errbuflen, "Cannot get a new SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
     77  1.1  christos 		goto die;
     78  1.1  christos 	}
     79  1.1  christos 
     80  1.1  christos 	SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
     81  1.1  christos 
     82  1.1  christos 	if (is_server)
     83  1.1  christos 	{
     84  1.1  christos 		char const *certfile = ssl_certfile[0] ? ssl_certfile : "cert.pem";
     85  1.1  christos 		if (1 != SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
     86  1.1  christos 		{
     87  1.1  christos 			snprintf(errbuf, errbuflen, "Cannot read certificate file %s: %s", certfile, ERR_error_string(ERR_get_error(), NULL));
     88  1.1  christos 			goto die;
     89  1.1  christos 		}
     90  1.1  christos 
     91  1.1  christos 		char const *keyfile = ssl_keyfile[0] ? ssl_keyfile : "key.pem";
     92  1.1  christos 		if (1 != SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
     93  1.1  christos 		{
     94  1.1  christos 			snprintf(errbuf, errbuflen, "Cannot read private key file %s: %s", keyfile, ERR_error_string(ERR_get_error(), NULL));
     95  1.1  christos 			goto die;
     96  1.1  christos 		}
     97  1.1  christos 	}
     98  1.1  christos 	else
     99  1.1  christos 	{
    100  1.1  christos 		if (ssl_rootfile[0])
    101  1.1  christos 		{
    102  1.1  christos 			if (! SSL_CTX_load_verify_locations(ctx, ssl_rootfile, 0))
    103  1.1  christos 			{
    104  1.1  christos 				snprintf(errbuf, errbuflen, "Cannot read CA list from %s", ssl_rootfile);
    105  1.1  christos 				goto die;
    106  1.1  christos 			}
    107  1.1  christos 		}
    108  1.1  christos 		else
    109  1.1  christos 		{
    110  1.1  christos 			SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
    111  1.1  christos 		}
    112  1.1  christos 	}
    113  1.1  christos 
    114  1.1  christos #if 0
    115  1.1  christos 	if (! RAND_load_file(RANDOM, 1024*1024))
    116  1.1  christos 	{
    117  1.1  christos 		snprintf(errbuf, errbuflen, "Cannot init random");
    118  1.1  christos 		goto die;
    119  1.1  christos 	}
    120  1.1  christos 
    121  1.1  christos 	if (is_server)
    122  1.1  christos 	{
    123  1.1  christos 		SSL_CTX_set_session_id_context(ctx, (void *)&s_server_session_id_context, sizeof(s_server_session_id_context));
    124  1.1  christos 	}
    125  1.1  christos #endif
    126  1.1  christos 
    127  1.1  christos 	inited = 1;
    128  1.1  christos 	return 0;
    129  1.1  christos 
    130  1.1  christos die:
    131  1.1  christos 	return -1;
    132  1.1  christos }
    133  1.1  christos 
    134  1.3  christos SSL *ssl_promotion(int is_server, PCAP_SOCKET s, char *errbuf, size_t errbuflen)
    135  1.1  christos {
    136  1.1  christos 	if (ssl_init_once(is_server, 1, errbuf, errbuflen) < 0) {
    137  1.1  christos 		return NULL;
    138  1.1  christos 	}
    139  1.1  christos 
    140  1.1  christos 	SSL *ssl = SSL_new(ctx); // TODO: also a DTLS context
    141  1.1  christos 	SSL_set_fd(ssl, (int)s);
    142  1.1  christos 
    143  1.1  christos 	if (is_server) {
    144  1.1  christos 		if (SSL_accept(ssl) <= 0) {
    145  1.1  christos 			snprintf(errbuf, errbuflen, "SSL_accept(): %s",
    146  1.1  christos 					ERR_error_string(ERR_get_error(), NULL));
    147  1.1  christos 			return NULL;
    148  1.1  christos 		}
    149  1.1  christos 	} else {
    150  1.1  christos 		if (SSL_connect(ssl) <= 0) {
    151  1.1  christos 			snprintf(errbuf, errbuflen, "SSL_connect(): %s",
    152  1.1  christos 					ERR_error_string(ERR_get_error(), NULL));
    153  1.1  christos 			return NULL;
    154  1.1  christos 		}
    155  1.1  christos 	}
    156  1.1  christos 
    157  1.1  christos 	return ssl;
    158  1.1  christos }
    159  1.1  christos 
    160  1.1  christos // Finish using an SSL handle; shut down the connection and free the
    161  1.1  christos // handle.
    162  1.1  christos void ssl_finish(SSL *ssl)
    163  1.1  christos {
    164  1.1  christos 	//
    165  1.1  christos 	// We won't be using this again, so we can just send the
    166  1.1  christos 	// shutdown alert and free up the handle, and have our
    167  1.1  christos 	// caller close the socket.
    168  1.1  christos 	//
    169  1.1  christos 	// XXX - presumably, if the connection is shut down on
    170  1.1  christos 	// our side, either our peer won't have a problem sending
    171  1.1  christos 	// their shutdown alert or will not treat such a problem
    172  1.1  christos 	// as an error.  If this causes errors to be reported,
    173  1.1  christos 	// fix that as appropriate.
    174  1.1  christos 	//
    175  1.1  christos 	SSL_shutdown(ssl);
    176  1.1  christos 	SSL_free(ssl);
    177  1.1  christos }
    178  1.1  christos 
    179  1.1  christos // Same return value as sock_send:
    180  1.1  christos // 0 on OK, -1 on error but closed connection (-2).
    181  1.1  christos int ssl_send(SSL *ssl, char const *buffer, int size, char *errbuf, size_t errbuflen)
    182  1.1  christos {
    183  1.1  christos 	int status = SSL_write(ssl, buffer, size);
    184  1.1  christos 	if (status > 0)
    185  1.1  christos 	{
    186  1.1  christos 		// "SSL_write() will only return with success, when the complete contents (...) has been written."
    187  1.1  christos 		return 0;
    188  1.1  christos 	}
    189  1.1  christos 	else
    190  1.1  christos 	{
    191  1.1  christos 		int ssl_err = SSL_get_error(ssl, status); // TODO: does it pop the error?
    192  1.1  christos 		if (ssl_err == SSL_ERROR_ZERO_RETURN)
    193  1.1  christos 		{
    194  1.1  christos 			return -2;
    195  1.1  christos 		}
    196  1.1  christos 		else if (ssl_err == SSL_ERROR_SYSCALL)
    197  1.1  christos 		{
    198  1.1  christos #ifndef _WIN32
    199  1.1  christos 			if (errno == ECONNRESET || errno == EPIPE) return -2;
    200  1.1  christos #endif
    201  1.1  christos 		}
    202  1.1  christos 		snprintf(errbuf, errbuflen, "SSL_write(): %s",
    203  1.1  christos 		    ERR_error_string(ERR_get_error(), NULL));
    204  1.1  christos 		return -1;
    205  1.1  christos 	}
    206  1.1  christos }
    207  1.1  christos 
    208  1.1  christos // Returns the number of bytes read, or -1 on syserror, or -2 on SSL error.
    209  1.1  christos int ssl_recv(SSL *ssl, char *buffer, int size, char *errbuf, size_t errbuflen)
    210  1.1  christos {
    211  1.1  christos 	int status = SSL_read(ssl, buffer, size);
    212  1.1  christos 	if (status <= 0)
    213  1.1  christos 	{
    214  1.1  christos 		int ssl_err = SSL_get_error(ssl, status);
    215  1.1  christos 		if (ssl_err == SSL_ERROR_ZERO_RETURN)
    216  1.1  christos 		{
    217  1.1  christos 			return 0;
    218  1.1  christos 		}
    219  1.1  christos 		else if (ssl_err == SSL_ERROR_SYSCALL)
    220  1.1  christos 		{
    221  1.1  christos 			return -1;
    222  1.1  christos 		}
    223  1.1  christos 		else
    224  1.1  christos 		{
    225  1.1  christos 			// Should not happen
    226  1.1  christos 			snprintf(errbuf, errbuflen, "SSL_read(): %s",
    227  1.1  christos 			    ERR_error_string(ERR_get_error(), NULL));
    228  1.1  christos 			return -2;
    229  1.1  christos 		}
    230  1.1  christos 	}
    231  1.1  christos 	else
    232  1.1  christos 	{
    233  1.1  christos 		return status;
    234  1.1  christos 	}
    235  1.1  christos }
    236  1.1  christos 
    237  1.1  christos #endif // HAVE_OPENSSL
    238