+
+
+
+/*************************************************
+* Report the library versions. *
+*************************************************/
+
+/* There have historically been some issues with binary compatibility in
+OpenSSL libraries; if Exim (like many other applications) is built against
+one version of OpenSSL but the run-time linker picks up another version,
+it can result in serious failures, including crashing with a SIGSEGV. So
+report the version found by the compiler and the run-time version.
+
+Arguments: a FILE* to print the results to
+Returns: nothing
+*/
+
+void
+tls_version_report(FILE *f)
+{
+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;
+}
+