X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fssl.c;h=42385abd0b7f2cf34765a9609cdf0c83f7073a5a;hb=673cad207cccf829038ab1a4399ca302bb0cf078;hp=2204a3cc3996dc59eb6b15968fcf5713fe2350e9;hpb=35d4608d0e044df48ee8cea13d3cbeafbb33535d;p=umurmur.git diff --git a/src/ssl.c b/src/ssl.c index 2204a3c..42385ab 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2009-2012, Martin Johansson - Copyright (C) 2005-2012, Thorvald Natvig +/* Copyright (C) 2009-2014, Martin Johansson + Copyright (C) 2005-2014, Thorvald Natvig All rights reserved. @@ -30,6 +30,7 @@ */ #include #include +#include #include "conf.h" #include "log.h" @@ -40,31 +41,62 @@ * PolarSSL interface */ +#include #include #include #include #include #include +#ifdef POLARSSL_API_V1_2_ABOVE +int ciphers[] = +{ + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + 0 +}; +#else int ciphers[] = { SSL_EDH_RSA_AES_256_SHA, - SSL_EDH_RSA_CAMELLIA_256_SHA, - SSL_EDH_RSA_DES_168_SHA, SSL_RSA_AES_256_SHA, - SSL_RSA_CAMELLIA_256_SHA, SSL_RSA_AES_128_SHA, - SSL_RSA_CAMELLIA_128_SHA, - SSL_RSA_DES_168_SHA, - SSL_RSA_RC4_128_SHA, - SSL_RSA_RC4_128_MD5, 0 }; +#endif + +#ifdef POLARSSL_API_V1_3_ABOVE +static x509_crt certificate; +static inline int x509parse_keyfile(rsa_context *rsa, const char *path, + const char *pwd) +{ + int ret; + pk_context pk; + + pk_init(&pk); + ret = pk_parse_keyfile(&pk, path, pwd); + if (ret == 0 && !pk_can_do( &pk, POLARSSL_PK_RSA)) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if (ret == 0) + rsa_copy(rsa, pk_rsa(pk)); + else + rsa_free(rsa); + pk_free(&pk); + return ret; +} +#else static x509_cert certificate; +#endif + static rsa_context key; bool_t builtInTestCertificate; -havege_state hs; /* exported to crypt.c */ +#ifdef USE_POLARSSL_HAVEGE +havege_state hs; +#else +int urandom_fd; +#endif /* DH prime */ char *my_dhm_P = @@ -77,12 +109,18 @@ char *my_dhm_P = "DEF409C08E8AC24D1732A6128D2220DC53"; char *my_dhm_G = "4"; +#ifdef USE_POLARSSL_TESTCERT static void initTestCert() { int rc; builtInTestCertificate = true; +#ifdef POLARSSL_API_V1_3_ABOVE + rc = x509_crt_parse_rsa(&certificate, (unsigned char *)test_srv_crt, + strlen(test_srv_crt)); +#else rc = x509parse_crt(&certificate, (unsigned char *)test_srv_crt, - strlen(test_srv_crt)); + strlen(test_srv_crt)); +#endif if (rc != 0) Log_fatal("Could not parse built-in test certificate"); } @@ -91,11 +129,12 @@ static void initTestKey() { int rc; - rc = x509parse_key(&key, (unsigned char *)test_srv_key, - strlen(test_srv_key), NULL, 0); + rc = x509parse_key_rsa(&key, (unsigned char *)test_srv_key, + strlen(test_srv_key), NULL, 0); if (rc != 0) Log_fatal("Could not parse built-in test RSA key"); } +#endif /* * How to generate a self-signed cert with openssl: @@ -108,14 +147,26 @@ static void initCert() char *crtfile = (char *)getStrConf(CERTIFICATE); if (crtfile == NULL) { - Log_warn("No certificate file specified"); +#ifdef USE_POLARSSL_TESTCERT + Log_warn("No certificate file specified. Falling back to test certificate."); initTestCert(); +#else + Log_fatal("No certificate file specified"); +#endif return; } +#ifdef POLARSSL_API_V1_3_ABOVE + rc = x509_crt_parse_file(&certificate, crtfile); +#else rc = x509parse_crtfile(&certificate, crtfile); +#endif if (rc != 0) { - Log_warn("Could not read certificate file %s", crtfile); +#ifdef USE_POLARSSL_TESTCERT + Log_warn("Could not read certificate file '%s'. Falling back to test certificate.", crtfile); initTestCert(); +#else + Log_fatal("Could not read certificate file '%s'", crtfile); +#endif return; } } @@ -132,6 +183,21 @@ static void initKey() Log_fatal("Could not read RSA key file %s", keyfile); } +#ifndef USE_POLARSSL_HAVEGE +int urandom_bytes(void *ctx, unsigned char *dest, size_t len) +{ + int cur; + + while (len) { + cur = read(urandom_fd, dest, len); + if (cur < 0) + continue; + len -= cur; + } + return 0; +} +#endif + #define DEBUG_LEVEL 0 static void pssl_debug(void *ctx, int level, const char *str) { @@ -144,34 +210,55 @@ void SSLi_init(void) char verstring[12]; initCert(); +#ifdef USE_POLARSSL_TESTCERT if (builtInTestCertificate) { Log_warn("*** Using built-in test certificate and RSA key ***"); - Log_warn("*** This is not secure! Please use a CA-signed certificate or create a self-signed certificate ***"); + Log_warn("*** This is not secure! Please use a CA-signed certificate or create a key and self-signed certificate ***"); initTestKey(); } else initKey(); +#else + initKey(); +#endif + + /* Initialize random number generator */ +#ifdef USE_POLARSSL_HAVEGE havege_init(&hs); +#else + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) + Log_fatal("Cannot open /dev/urandom"); +#endif -#ifdef POLARSSL_VERSION_MAJOR version_get_string(verstring); Log_info("PolarSSL library version %s initialized", verstring); -#else - Log_info("PolarSSL library initialized"); -#endif } void SSLi_deinit(void) { +#ifdef POLARSSL_API_V1_3_ABOVE + x509_crt_free(&certificate); +#else x509_free(&certificate); +#endif rsa_free(&key); } /* Create SHA1 of last certificate in the peer's chain. */ bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash) { - x509_cert *cert = ssl->peer_cert; - if (!ssl->peer_cert) { +#ifdef POLARSSL_API_V1_3_ABOVE + x509_crt const *cert; +#else + x509_cert const *cert; +#endif +#ifdef POLARSSL_API_V1_2_ABOVE + cert = ssl_get_peer_cert(ssl); +#else + cert = ssl->peer_cert; +#endif + if (!cert) { return false; } sha1(cert->raw.p, cert->raw.len, hash); @@ -193,24 +280,34 @@ SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready) rc = ssl_init(ssl); if (rc != 0 ) - Log_fatal("Failed to initalize: %d", rc); + Log_fatal("Failed to initialize: %d", rc); ssl_set_endpoint(ssl, SSL_IS_SERVER); ssl_set_authmode(ssl, SSL_VERIFY_OPTIONAL); - + +#ifdef USE_POLARSSL_HAVEGE ssl_set_rng(ssl, HAVEGE_RAND, &hs); +#else + ssl_set_rng(ssl, urandom_bytes, NULL); +#endif + ssl_set_dbg(ssl, pssl_debug, NULL); ssl_set_bio(ssl, net_recv, fd, net_send, fd); -#ifdef POLARSSL_API_V1 ssl_set_ciphersuites(ssl, ciphers); + +#ifdef POLARSSL_API_V1_2_ABOVE + ssl_set_session(ssl, ssn); #else - ssl_set_ciphers(ssl, ciphers); -#endif ssl_set_session(ssl, 0, 0, ssn); +#endif ssl_set_ca_chain(ssl, &certificate, NULL, NULL); +#ifdef POLARSSL_API_V1_3_ABOVE + ssl_set_own_cert_rsa(ssl, &certificate, &key); +#else ssl_set_own_cert(ssl, &certificate, &key); +#endif ssl_set_dh_param(ssl, my_dhm_P, my_dhm_G); return ssl; @@ -222,13 +319,9 @@ int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready) rc = ssl_handshake(ssl); if (rc != 0) { -#ifdef POLARSSL_API_V1 if (rc == POLARSSL_ERR_NET_WANT_READ || rc == POLARSSL_ERR_NET_WANT_WRITE) { -#else - if (rc == POLARSSL_ERR_NET_TRY_AGAIN) { -#endif return 0; - } else if (POLARSSL_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */ + } else if (rc == POLARSSL_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */ return 0; } else { Log_warn("SSL handshake failed: %d", rc); @@ -244,11 +337,7 @@ int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len) int rc; rc = ssl_read(ssl, buf, len); -#ifdef POLARSSL_API_V1 if (rc == POLARSSL_ERR_NET_WANT_READ) -#else - if (rc == POLARSSL_ERR_NET_TRY_AGAIN) -#endif return SSLI_ERROR_WANT_READ; return rc; } @@ -258,11 +347,7 @@ int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len) int rc; rc = ssl_write(ssl, buf, len); -#ifdef POLARSSL_API_V1 if (rc == POLARSSL_ERR_NET_WANT_WRITE) -#else - if (rc == POLARSSL_ERR_NET_TRY_AGAIN) -#endif return SSLI_ERROR_WANT_WRITE; return rc; } @@ -285,7 +370,10 @@ void SSLi_shutdown(SSL_handle_t *ssl) void SSLi_free(SSL_handle_t *ssl) { Log_debug("SSLi_free"); - free(ssl->session); /* XXX - Hmmm. */ +#if (POLARSSL_VERSION_MINOR <= 2 && POLARSSL_VERSION_PATCH < 6) + free(ssl->session); /* Workaround for memory leak in PolarSSL < 1.2.6 */ + ssl->session = NULL; +#endif ssl_free(ssl); free(ssl); } @@ -325,7 +413,7 @@ static X509 *SSL_readcert(char *certfile) FILE *fp; X509 *x509; - /* open the private key file */ + /* open the certificate file */ fp = fopen(certfile, "r"); if (fp == NULL) { Log_warn("Unable to open the X509 file %s for reading.", certfile); @@ -378,23 +466,15 @@ static RSA *SSL_readprivatekey(char *keyfile) static void SSL_writecert(char *certfile, X509 *x509) { FILE *fp; - BIO *err_output; - - /* prepare a BIO for outputting error messages */ - - err_output = BIO_new_fp(stderr,BIO_NOCLOSE); - + /* open the private key file */ fp = fopen(certfile, "w"); if (fp == NULL) { - BIO_printf(err_output, "Unable to open the X509 file for writing.\n"); - BIO_free(err_output); + Log_warn("Unable to open the X509 file %s for writing", certfile); return; - } - + } if (PEM_write_X509(fp, x509) == 0) { - BIO_printf(err_output, "Error trying to write X509 info.\n"); - ERR_print_errors(err_output); + Log_warn("Error trying to write X509 info."); } fclose(fp); } @@ -402,27 +482,22 @@ static void SSL_writecert(char *certfile, X509 *x509) static void SSL_writekey(char *keyfile, RSA *rsa) { FILE *fp; - BIO *err_output; - /* prepare a BIO for outputing error messages */ - err_output = BIO_new_fp(stderr, BIO_NOCLOSE); /* open the private key file for reading */ fp = fopen(keyfile, "w"); if (fp == NULL) { - BIO_printf(err_output, "Unable to open the private key file %s for writing.\n", keyfile); - BIO_free(err_output); + Log_warn("Unable to open the private key file %s for writing.", keyfile); return; } if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) { - /* error reading the key - check the error stack */ - BIO_printf(err_output, "Error trying to write private key\n"); - ERR_print_errors(err_output); + Log_warn("Error trying to write private key"); } fclose(fp); } static void SSL_initializeCert() { + char *crt, *key, *pass; crt = (char *)getStrConf(CERTIFICATE); @@ -435,6 +510,7 @@ static void SSL_initializeCert() { pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); } + #if 0 /* Later ... */ @@ -468,14 +544,11 @@ static void SSL_initializeCert() { #endif if (!rsa || !x509) { - logthis("Generating new server certificate."); + Log_info("Generating new server certificate."); - BIO *bio_err; CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - bio_err=BIO_new_fp(stderr, BIO_NOCLOSE); - + x509 = X509_new(); pkey = EVP_PKEY_new(); rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL); @@ -514,16 +587,23 @@ void SSLi_init(void) char *cipherstring, tempstring[128]; SSL_library_init(); - OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */ - SSL_load_error_strings(); /* load all error messages */ - ERR_load_crypto_strings(); /* load all error messages */ - method = SSLv23_server_method(); /* create new server-method instance */ - context = SSL_CTX_new(method); /* create new context from method */ - if (context == NULL) - { - ERR_print_errors_fp(stderr); - abort(); - } + OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */ + SSL_load_error_strings(); /* load all error messages */ + ERR_load_crypto_strings(); /* load all error messages */ + method = SSLv23_server_method(); /* create new server-method instance */ + context = SSL_CTX_new(method); /* create new context from method */ + if (context == NULL) + { + ERR_print_errors_fp(stderr); + abort(); + } + + char* sslCAPath = getStrConf(CAPATH); + if(sslCAPath != NULL) + { + SSL_CTX_load_verify_locations(context, NULL, sslCAPath); + } + SSL_initializeCert(); if (SSL_CTX_use_certificate(context, x509) <= 0) Log_fatal("Failed to initialize cert"); @@ -531,7 +611,7 @@ void SSLi_init(void) ERR_print_errors_fp(stderr); Log_fatal("Failed to initialize private key"); } - + /* Set cipher list */ ssl = SSL_new(context); cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);