X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftls-openssl.c;h=a9251c7f46c68943a1e07b271ac3c3015c1d933b;hb=0a49a7a4f1090b6f1ce1d0f9d969804c9226b53e;hp=edaed35aecae027dda68c3513da1844d2629833b;hpb=a0475b6996e895bf9d993c733d49c2a850cc11e8;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index edaed35ae..a9251c7f4 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/tls-openssl.c,v 1.16 2009/10/16 08:34:50 tom Exp $ */ +/* $Cambridge: exim/src/src/tls-openssl.c,v 1.22 2009/11/16 19:50:37 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2007 */ +/* Copyright (c) University of Cambridge 1995 - 2009 */ /* See the file NOTICE for conditions of use and distribution. */ /* This module provides the TLS (aka SSL) support for Exim using the OpenSSL @@ -26,8 +26,8 @@ functions from the OpenSSL library. */ /* Structure for collecting random data for seeding. */ typedef struct randstuff { - time_t t; - pid_t p; + struct timeval tv; + pid_t p; } randstuff; /* Local static variables */ @@ -73,13 +73,13 @@ tls_error(uschar *prefix, host_item *host, uschar *msg) if (msg == NULL) { ERR_error_string(ERR_get_error(), ssl_errstring); - msg = ssl_errstring; + msg = (uschar *)ssl_errstring; } if (host == NULL) { uschar *conn_info = smtp_get_connection_info(); - if (strncmp(conn_info, "SMTP ", 5) == 0) + if (Ustrncmp(conn_info, US"SMTP ", 5) == 0) conn_info += 5; log_write(0, LOG_MAIN, "TLS error on %s (%s): %s", conn_info, prefix, msg); @@ -253,7 +253,7 @@ if (dhexpanded == NULL) return TRUE; if ((bio = BIO_new_file(CS dhexpanded, "r")) == NULL) { tls_error(string_sprintf("could not read dhparams file %s", dhexpanded), - host, strerror(errno)); + host, (uschar *)strerror(errno)); yield = FALSE; } else @@ -305,9 +305,11 @@ tls_init(host_item *host, uschar *dhparam, uschar *certificate, SSL_load_error_strings(); /* basic set up */ OpenSSL_add_ssl_algorithms(); +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) /* SHA256 is becoming ever moar popular. This makes sure it gets added to the list of available digests. */ EVP_add_digest(EVP_sha256()); +#endif /* Create a context */ @@ -327,7 +329,7 @@ afterwards. */ if (!RAND_status()) { randstuff r; - r.t = time(NULL); + gettimeofday(&r.tv, NULL); r.p = getpid(); RAND_seed((uschar *)(&r), sizeof(r)); @@ -336,7 +338,7 @@ if (!RAND_status()) if (!RAND_status()) return tls_error(US"RAND_status", host, - "unable to seed random number generator"); + US"unable to seed random number generator"); } /* Set up the information callback, which outputs if debugging is at a suitable @@ -619,7 +621,7 @@ uschar *expciphers; if (tls_active >= 0) { - tls_error("STARTTLS received after TLS started", NULL, ""); + tls_error(US"STARTTLS received after TLS started", NULL, US""); smtp_printf("554 Already in TLS\r\n"); return FAIL; } @@ -1053,4 +1055,72 @@ fprintf(f, "OpenSSL compile-time version: %s\n", OPENSSL_VERSION_TEXT); fprintf(f, "OpenSSL runtime version: %s\n", SSLeay_version(SSLEAY_VERSION)); } + + + +/************************************************* +* Pseudo-random number generation * +*************************************************/ + +/* Pseudo-random number generation. The result is not expected to be +cryptographically strong but not so weak that someone will shoot themselves +in the foot using it as a nonce in input in some email header scheme or +whatever weirdness they'll twist this into. The result should handle fork() +and avoid repeating sequences. OpenSSL handles that for us. + +Arguments: + max range maximum +Returns a random number in range [0, max-1] +*/ + +int +pseudo_random_number(int max) +{ +unsigned int r; +int i, needed_len; +uschar *p; +uschar smallbuf[sizeof(r)]; + +if (max <= 1) + return 0; + +/* OpenSSL auto-seeds from /dev/random, etc, but this a double-check. */ +if (!RAND_status()) + { + randstuff r; + gettimeofday(&r.tv, NULL); + r.p = getpid(); + + RAND_seed((uschar *)(&r), sizeof(r)); + } +/* We're after pseudo-random, not random; if we still don't have enough data +in the internal PRNG then our options are limited. We could sleep and hope +for entropy to come along (prayer technique) but if the system is so depleted +in the first place then something is likely to just keep taking it. Instead, +we'll just take whatever little bit of pseudo-random we can still manage to +get. */ + +needed_len = sizeof(r); +/* Don't take 8 times more entropy than needed if int is 8 octets and we were +asked for a number less than 10. */ +for (r = max, i = 0; r; ++i) + r >>= 1; +i = (i + 7) / 8; +if (i < needed_len) + needed_len = i; + +/* We do not care if crypto-strong */ +(void) RAND_pseudo_bytes(smallbuf, needed_len); +r = 0; +for (p = smallbuf; needed_len; --needed_len, ++p) + { + r *= 256; + r += *p; + } + +/* We don't particularly care about weighted results; if someone wants +smooth distribution and cares enough then they should submit a patch then. */ +return r % max; +} + /* End of tls-openssl.c */