+Using Exim 4.80+ with GnuTLS
+============================
+
+(1) I'm having problems building with GnuTLS 1, why?
+(2) What changed? Why?
+(3) I'm seeing:
+ "(gnutls_handshake): A TLS packet with unexpected length was received"
+ Why?
+(4) What's the deal with MD5?
+(5) What happened to gnutls_require_kx / gnutls_require_mac /
+ gnutls_require_protocols?
+(6) What's the deal with tls_dh_max_bits? What's DH?
+(7) What's a Priority String?
+(8) How do I use tls_require_ciphers?
+(9) How do I test STARTTLS support?
+
+
+
+(1): I'm having problems building with GnuTLS 1, why?
+-----------------------------------------------------
+
+GnuTLS's library interface has changed and Exim uses the more current
+interface. Since GnuTLS is security critical code, you should probably update
+to a supported release.
+
+If updating GnuTLS is not an option, then build Exim against OpenSSL instead.
+
+If neither is an option, then you might build Exim with the rule
+"SUPPORT_TLS=yes" commented out in "Local/Makefile", so that your Exim build
+no longer has TLS support.
+
+If you need to keep TLS support, and you can't use OpenSSL, then you'll have
+to update the GnuTLS you have installed. Sorry.
+
+We've tested the build of Exim back as far as GnuTLS 2.8.x; most development
+work is done with 2.12 and tested on 2.10 and 3.x.
+
+If you have to pick a version to upgrade to, use GnuTLS 3.x if available. The
+GnuTLS developers took advantage of the version bump to add an error code
+return value which makes debugging some problems a lot easier.
+
+
+
+(2): What changed? Why?
+------------------------
+
+The GnuTLS provider integration in Exim was overhauled, rewritten but with
+some copy/paste, because building Exim against more current releases of GnuTLS
+was issuing deprecation warnings from the compiler.
+
+When a library provider marks up the include files so that some function calls
+will cause the compiler/linker to emit deprecation warnings, it's time to pay
+serious attention. A future release might not work at all. Using the new
+APIs may mean that Exim will *stop* working with older releases of GnuTLS.
+The GnuTLS support in Exim was overhauled in Exim 4.80. In prior releases,
+Exim hard-coded a lot of algorithms and constrained what could happen. In
+Exim 4.79, we added to the hard-coded list just enough to let TLSv1.1 and
+TLSv1.2 be negotiated, but not actually support the mandatory algorithms of
+those protocol versions. When Exim's GnuTLS integration was originally
+written, there was no other choice than to make Exim responsible for a lot of
+this. In the meantime, GnuTLS has improved.
+
+With the rewrite, we started using the current API and leaving a lot more
+responsibility for TLS decisions to the library.
+
+The GnuTLS developers added "priority strings" (see Q7), which provide an
+interface exposed to the configuration file for a lot of the tuning.
+
+The GnuTLS policy is to no longer support MD5 in certificates. Exim had
+previously been immune to this policy, but no longer. See Q4.
+
+
+
+(3): I'm seeing "A TLS packet with unexpected length was received". Why?
+-------------------------------------------------------------------------
+
+The most likely reason is that the client dropped the connection during
+handshake, because their library disliked some aspect of the negotiation.
+
+In GnuTLS 2, an EOF on the connection is reported with an error code for
+packets being too large, and the above is the string returned by the library
+for that error code. In GnuTLS 3, there's a specific error code for EOF and
+the diagnostic will be less confusing.
+
+Most likely cause is an MD5 hash used in a certificate. See Q4 below.
+Alternatively, the client dislikes the size of the Diffie-Hellman prime
+offered by the server; if lowering the value of the "tls_dh_max_bits" Exim
+option fixes the problem, this was the cause. See Q6.
+
+
+
+(4): What's the deal with MD5?
+------------------------------
+
+MD5 is a hash algorithm. Hash algorithms are used to reduce a lot of data
+down to a fairly short value, which is supposed to be extremely hard to
+manipulate to get a value of someone's choosing. Signatures, used to attest
+to identity or integrity, rely upon this manipulation being effectively
+impossible, because the signature is the result of math upon the hash result.
+Without hash algorithms, signatures would be longer than the text being
+signed.
+
+MD5 was once very popular. It still is far too popular. Real world attacks
+have been proven possible against MD5. Including an attack against PKI
+(Public Key Infrastructure) certificates used for SSL/TLS. In that attack,
+the attackers got a certificate for one identity but we able to then public a
+certificate with the same signature but a different identity. This undermines
+the whole purpose of having certificates.
+
+So GnuTLS stopped trusting any certificate with an MD5-based hash used in it.
+The world has been hurriedly moving away from MD5 in certificates for a while.
+If you still have such a certificate, you should move too.
+
+If you paid someone for your certificate, they should be willing to reissue
+the certificate with a different algorithm, for no extra money. If they try
+to charge money to replace their defective product, buy from someone else
+instead. Part of the reason for paying money on a recurring basis is to cover
+the ongoing costs of proving a trust relationship, such as providing
+revocation protocols. This is just another of those ongoing costs you have
+already paid for.
+
+
+
+(5): ... gnutls_require_kx / gnutls_require_mac / gnutls_require_protocols?
+---------------------------------------------------------------------------
+
+These Exim options were used to provide fine-grained control over the TLS
+negotiation performed by GnuTLS. They required explicit protocol knowledge
+from Exim, which vastly limited what GnuTLS could do and involved the Exim
+maintainers in decisions which aren't part of their professional areas of
+expertise. The need for Exim to be able to do this went away when GnuTLS
+introduced Priority Strings (see Q7).
+
+If you were using these options before, then you're already an expert user and
+should be able to easily craft a priority string to accomplish your goals.
+Set the Exim "tls_require_ciphers" value accordingly. There is a main section
+option of this name, used for Exim receiving inbound connections, and an SMTP
+driver transport option of this name, used for Exim establishing outbound
+connections.
+
+
+
+(6): What's the deal with tls_dh_max_bits? What's DH?
+------------------------------------------------------
+
+DH, Diffie-Hellman (or Diffie-Hellman-Merkle, or something naming Williamson)
+is the common name for a way for two parties to a communication stream to
+exchange some private random data so that both end up with a shared secret
+which no evesdropper can get. It does not provide for proof of the identity
+of either party, so on its own is subject to man-in-the-middle attacks, but is
+often combined with systems which do provide such proof, improving them by
+separating the session key (the shared secret) from the long-term identity,
+and so protecting past communications from a break of the long-term identity.
+
+To do this, the server sends to the client a very large prime number; this is
+in the clear, an attacker can see it. This is not a problem; it's so not a
+problem, that there are standard named primes which applications can use, and
+which a future release of Exim will probably support.
+
+The size of the prime number affects how difficult it is to break apart the
+shared secret and decrypt the data. As time passes, the size required to
+provide protection against an adversary climbs: computers get more powerful,
+mathematical advances are made, and so on.
+
+Estimates of the size needed are published as recommendations by various
+groups; a good summary of sizes currently recommended, for various
+cryptographic primitives, is available at:
+
+ http://www.keylength.com/en/3/
+
+The GnuTLS folks think the ECRYPT II advice is good. They know far more of
+such matters than the Exim folks, we just say "er, what they said".
+
+One of the new pieces of the GnuTLS API is a means for an application to ask
+it for guidance and advice on how large some numbers should be. This is not
+entirely internal to GnuTLS since generating the numbers is slow, an
+application might want to use a standard prime, etc. So, in an attempt to get
+away from being involved in cryptographic policy, and to get rid of a
+hard-coded "1024" in Exim's source-code, we switched to asking GnuTLS how many
+bits should be in the prime number generated for use for Diffie-Hellman. To
+give back to GnuTLS for use We can ask for various sizes, and did not expose
+this to the administrator but instead just asked for "NORMAL" protection.
+Literally:
+
+ dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_NORMAL);
+
+This API is only available as of GnuTLS 2.12. Prior to that release, we stuck
+with the old value, for compatibility, so "1024" is still hard-coded.
+Reviewing the page above, you'll see that this is described as "Short-term
+protection against medium organizations, medium-term protection against small
+organizations."
+
+So if you are using an old release of GnuTLS, you can either add to
+Local/Makefile a different value of "EXIM_SERVER_DH_BITS_PRE2_12" or accept
+that your protection might not be adequate to your needs. We advise updating
+to a more current GnuTLS release and rebuilding Exim against that.
+
+Unfortunately, some TLS libraries have the client side bound how large a DH
+prime they will accept from the server. The larger the number, the more
+computation required to work with it and the slower that things get. So they
+pick what they believe to be reasonable upper bounds, and then typically
+forget about it for several years.
+
+Worse, in TLS the DH negotiation happens after a ciphersuite has been chosen,
+so if the client dislikes the value then a different ciphersuite avoiding DH
+can not be negotiated! The client typically drops the connection, resulting
+in errors to the user and errors in the Exim logs. With GnuTLS 3, you'll see
+the EOF (End-Of-File) error message in Exim's logs, reported as being part of
+"gnutls_handshake", but with GnuTLS 2 you'll see a log message about a packet
+with an unexpected size. Unless the client software is written intelligently
+enough to be able to adapt and reconnect forbidding DH, the client will never
+be able to negotiate TLS.
+
+This time around, we discovered that the NSS library used by various Mozilla
+products, Chrome, etc, and most particularly by the Thunderbird mail client,
+has the lowest cap. In fact, prior to recent updates, their upper limit was
+lower than the value returned by GnuTLS for "NORMAL". The most recent NSS
+library release raises this, but the most recent Thunderbird release still has
+the old limit.
+
+So Exim had to get involved in cryptography policy decisions again. We added
+the "tls_dh_max_bits" global option, to set a number used in both OpenSSL and
+GnuTLS bindings for Exim. In GnuTLS, it clamps the value returned by
+gnutls_sec_param_to_pk_bits(), so that if the returned value is larger than
+tls_dh_max_bits then tls_dh_max_bits would be used instead.
+
+Our policy decision was to default the value of tls_dh_max_bits to the maximum
+supported in the most recent Thunderbird release, and to make this an
+administrator-available option so that administrators can choose to trade off
+security versus compatibility by raising it.
+
+A future release of Exim may even let the administrator tell GnuTLS to ask for
+more or less than "NORMAL".
+
+A TLS client does not get to choose the DH prime used, but can choose a
+minimum acceptable value. For Exim, this is a compile-time constant called
+"EXIM_CLIENT_DH_MIN_BITS" of 1024, which can be overruled in "Local/Makefile".
+
+
+
+(7): What's a Priority String?
+------------------------------
+
+A priority string is a way for a user of GnuTLS to tell GnuTLS how it should
+make decisions about what to do in TLS; it includes which algorithms to make
+available for various roles, what compatibility trade-offs to make, which
+features to enable or disable.
+
+It is exposed to the Mail Administrator in Exim's configuration file as the
+"tls_require_ciphers" option, which exists as a main section option for use in
+Exim as a server, accepting connections, and as an option on Transports using
+the SMTP driver, for use in Exim as a client. The main section option is
+*not* the default for the transport option, they are entirely independent.
+For both, the default value used by Exim is the string "NORMAL". (This is not
+the same NORMAL as for DH prime bit size selection in Q6, but a different
+NORMAL.) See Q8.
+
+The current documentation, for the most recent release of GnuTLS, is available
+online at:
+
+ http://www.gnu.org/software/gnutls/manual/html_node/Priority-Strings.html
+
+Beware that if you are not using the most recent GnuTLS release then this
+documentation will be wrong for you! You should find the "info" documentation
+which came with GnuTLS to review the available options. It's under "The TLS
+Handshake Protocol".
+
+$ pinfo --node="Priority Strings" gnutls
+
+(This author is unable to persuade the "info" command-line tool to jump
+straight to the required node, but "pinfo" works.)
+
+To trade off some security for more compatibility, you might set a value of
+"NORMAL:%COMPAT". See the documentation for more, including lowering security
+even further for more security, forcing clients to use the server's protocol
+suite, and ways to force selection of particular algorithms.
+
+
+
+(8): How do I use tls_require_ciphers?
+--------------------------------------
+
+This is the name of two options in Exim. One is a main section option, used
+by Exim as a server when a client initiates SSL/TLS negotiation, the other is
+an option on transports which use "driver = smtp", used when Exim initiates
+SSL/TLS as a client talking to a remote server.
+
+The option is expanded and so can take advantage of any variables which have
+been set. This includes the IP address of the remote side, the port upon
+which a connection was accepted (when a server), and more. Currently it does
+not have access to $tls_sni, whether as a client or as a server.
+
+This example, for the main section's option, will let the library defaults be
+permitted on the MX port, where there's probably no identity verification
+anyway, and lowers security further by increasing compatibility; but this ups
+the ante on the submission ports where the administrator might have some
+influence on the choice of clients used:
+
+tls_require_ciphers = ${if =={$received_port}{25}\
+ {NORMAL:%COMPAT}\
+ {SECURE128}}
+
+Note that during Exim start-up, when this option is sanity-checked, there will
+be no value of $received_port. In the above example, the checked value will
+thus be "SECURE128". Be careful to ensure that it always expands safely.
+
+
+
+(9): How do I test STARTTLS support?
+------------------------------------
+
+The best command-line client for debugging specifically SSL/TLS which this
+author has encountered is part of the GnuTLS suite, and is called
+"gnutls-cli". It's best because it's the only interactive tool which lets the
+user start TLS handshake exactly when they wish, so can choose to use the
+STARTTLS command.
+
+$ gnutls-cli --starttls --crlf --port 587 mail.example.org
+
+After EHLO, to see the capabilities, enter STARTTLS, wait for the response,
+then send EOF. Typically that's done by typing Ctrl-D at the start of a line.
+The "gnutls-cli" tool will take over, set up TLS (or fail) and by the time it
+returns to await more user input, you're using a secure connection and should
+type your second EHLO.
+
+The "--x509cafile" option may be helpful for checking certificates and
+"--priority" to pass a priority string to the client tool for configuring it.
+
+The --crlf is for strict protocol correctness, but Exim doesn't really need
+it, so "gnutls-cli -s -p 587 mail.example.org" is shorter.
+
+
+For debugging SMTP as a whole, we recommend swaks, "Swiss Army Knife SMTP", by
+John Jetmore (one of the Exim Maintainers). This has some TLS tuning options;
+it can be found at:
+
+ http://www.jetmore.org/john/code/swaks/
+
+
+For OpenSSL, the "openssl s_client" command helps; you can either set up Exim
+with a listening port which is SSL-on-connect or tell s_client to use
+STARTTLS.
+
+For the former, use the "tls_on_connect_ports" option and the
+"daemon_smtp_ports" option. Most clients for SSL-on-connect use the port
+which was briefly registered with IANA for this purpose, 465. So you would
+set something like:
+
+ daemon_smtp_ports = 25 : 465 : 587
+ tls_on_connect_ports = 465
+
+To use s_client with STARTTLS support, use "-starttls smtp" on the
+command-line. Beware that older versions of OpenSSL did not wait for the SMTP
+banner before sending EHLO, which will fall afoul of the protocol
+synchronisation checks in Exim (used to trip up pump-and-dump spammers); also
+you will not get control of the session until TLS is established. That said,
+this tool provides more tuning hooks for adjusting how TLS will be set up than
+most.
+
+*BEWARE* that by default, s_client will take any line starting with a capital
+letter "R" to be a request to initiate TLS renegotiation with the server and
+the line will not be sent. This may trip up "RCPT TO:<someone@example.org>"
+lines in SMTP. SMTP is not case-sensitive, so type "rcpt to" instead.
+Alternatively, invoke s_client with the "-ign_eof" option to disable this
+R-filtering and a few other features.
+
+
+# END OF FAQ