Commit | Line | Data |
---|---|---|
51fb80db PP |
1 | Using Exim 4.80+ with GnuTLS |
2 | ============================ | |
3 | ||
4 | (1) I'm having problems building with GnuTLS 1, why? | |
5 | (2) What changed? Why? | |
6 | (3) I'm seeing: | |
7 | "(gnutls_handshake): A TLS packet with unexpected length was received" | |
8 | Why? | |
9 | (4) What's the deal with MD5? | |
10 | (5) What happened to gnutls_require_kx / gnutls_require_mac / | |
11 | gnutls_require_protocols? | |
12 | (6) What's the deal with tls_dh_max_bits? What's DH? | |
13 | (7) What's a Priority String? | |
14 | (8) How do I use tls_require_ciphers? | |
15 | (9) How do I test STARTTLS support? | |
16 | ||
17 | ||
18 | ||
19 | (1): I'm having problems building with GnuTLS 1, why? | |
20 | ----------------------------------------------------- | |
21 | ||
22 | GnuTLS's library interface has changed and Exim uses the more current | |
23 | interface. Since GnuTLS is security critical code, you should probably update | |
24 | to a supported release. | |
25 | ||
26 | If updating GnuTLS is not an option, then build Exim against OpenSSL instead. | |
27 | ||
28 | If neither is an option, then you might build Exim with the rule | |
29 | "SUPPORT_TLS=yes" commented out in "Local/Makefile", so that your Exim build | |
30 | no longer has TLS support. | |
31 | ||
32 | If you need to keep TLS support, and you can't use OpenSSL, then you'll have | |
33 | to update the GnuTLS you have installed. Sorry. | |
34 | ||
35 | We've tested the build of Exim back as far as GnuTLS 2.8.x; most development | |
36 | work is done with 2.12 and tested on 2.10 and 3.x. | |
37 | ||
38 | If you have to pick a version to upgrade to, use GnuTLS 3.x if available. The | |
39 | GnuTLS developers took advantage of the version bump to add an error code | |
40 | return value which makes debugging some problems a lot easier. | |
41 | ||
42 | ||
43 | ||
44 | (2): What changed? Why? | |
45 | ------------------------ | |
46 | ||
47 | The GnuTLS provider integration in Exim was overhauled, rewritten but with | |
48 | some copy/paste, because building Exim against more current releases of GnuTLS | |
49 | was issuing deprecation warnings from the compiler. | |
50 | ||
51 | When a library provider marks up the include files so that some function calls | |
52 | will cause the compiler/linker to emit deprecation warnings, it's time to pay | |
53 | serious attention. A future release might not work at all. Using the new | |
54 | APIs may mean that Exim will *stop* working with older releases of GnuTLS. | |
55 | The GnuTLS support in Exim was overhauled in Exim 4.80. In prior releases, | |
56 | Exim hard-coded a lot of algorithms and constrained what could happen. In | |
57 | Exim 4.79, we added to the hard-coded list just enough to let TLSv1.1 and | |
58 | TLSv1.2 be negotiated, but not actually support the mandatory algorithms of | |
59 | those protocol versions. When Exim's GnuTLS integration was originally | |
60 | written, there was no other choice than to make Exim responsible for a lot of | |
61 | this. In the meantime, GnuTLS has improved. | |
62 | ||
63 | With the rewrite, we started using the current API and leaving a lot more | |
64 | responsibility for TLS decisions to the library. | |
65 | ||
66 | The GnuTLS developers added "priority strings" (see Q7), which provide an | |
67 | interface exposed to the configuration file for a lot of the tuning. | |
68 | ||
69 | The GnuTLS policy is to no longer support MD5 in certificates. Exim had | |
70 | previously been immune to this policy, but no longer. See Q4. | |
71 | ||
72 | ||
73 | ||
74 | (3): I'm seeing "A TLS packet with unexpected length was received". Why? | |
75 | ------------------------------------------------------------------------- | |
76 | ||
77 | The most likely reason is that the client dropped the connection during | |
78 | handshake, because their library disliked some aspect of the negotiation. | |
79 | ||
80 | In GnuTLS 2, an EOF on the connection is reported with an error code for | |
81 | packets being too large, and the above is the string returned by the library | |
82 | for that error code. In GnuTLS 3, there's a specific error code for EOF and | |
83 | the diagnostic will be less confusing. | |
84 | ||
85 | Most likely cause is an MD5 hash used in a certificate. See Q4 below. | |
86 | Alternatively, the client dislikes the size of the Diffie-Hellman prime | |
87 | offered by the server; if lowering the value of the "tls_dh_max_bits" Exim | |
88 | option fixes the problem, this was the cause. See Q6. | |
89 | ||
90 | ||
91 | ||
92 | (4): What's the deal with MD5? | |
93 | ------------------------------ | |
94 | ||
95 | MD5 is a hash algorithm. Hash algorithms are used to reduce a lot of data | |
96 | down to a fairly short value, which is supposed to be extremely hard to | |
97 | manipulate to get a value of someone's choosing. Signatures, used to attest | |
98 | to identity or integrity, rely upon this manipulation being effectively | |
99 | impossible, because the signature is the result of math upon the hash result. | |
100 | Without hash algorithms, signatures would be longer than the text being | |
101 | signed. | |
102 | ||
103 | MD5 was once very popular. It still is far too popular. Real world attacks | |
104 | have been proven possible against MD5. Including an attack against PKI | |
105 | (Public Key Infrastructure) certificates used for SSL/TLS. In that attack, | |
8d68e115 PP |
106 | the attackers got a certificate for one identity but were able to then publish |
107 | a certificate with the same signature but a different identity. This | |
108 | undermines the whole purpose of having certificates. | |
51fb80db PP |
109 | |
110 | So GnuTLS stopped trusting any certificate with an MD5-based hash used in it. | |
111 | The world has been hurriedly moving away from MD5 in certificates for a while. | |
112 | If you still have such a certificate, you should move too. | |
113 | ||
114 | If you paid someone for your certificate, they should be willing to reissue | |
115 | the certificate with a different algorithm, for no extra money. If they try | |
116 | to charge money to replace their defective product, buy from someone else | |
117 | instead. Part of the reason for paying money on a recurring basis is to cover | |
118 | the ongoing costs of proving a trust relationship, such as providing | |
119 | revocation protocols. This is just another of those ongoing costs you have | |
120 | already paid for. | |
121 | ||
122 | ||
123 | ||
124 | (5): ... gnutls_require_kx / gnutls_require_mac / gnutls_require_protocols? | |
125 | --------------------------------------------------------------------------- | |
126 | ||
127 | These Exim options were used to provide fine-grained control over the TLS | |
128 | negotiation performed by GnuTLS. They required explicit protocol knowledge | |
129 | from Exim, which vastly limited what GnuTLS could do and involved the Exim | |
130 | maintainers in decisions which aren't part of their professional areas of | |
131 | expertise. The need for Exim to be able to do this went away when GnuTLS | |
132 | introduced Priority Strings (see Q7). | |
133 | ||
134 | If you were using these options before, then you're already an expert user and | |
135 | should be able to easily craft a priority string to accomplish your goals. | |
136 | Set the Exim "tls_require_ciphers" value accordingly. There is a main section | |
137 | option of this name, used for Exim receiving inbound connections, and an SMTP | |
138 | driver transport option of this name, used for Exim establishing outbound | |
139 | connections. | |
140 | ||
141 | ||
142 | ||
143 | (6): What's the deal with tls_dh_max_bits? What's DH? | |
144 | ------------------------------------------------------ | |
145 | ||
a799883d PP |
146 | You can avoid all of the tls_dh_max_bits issues if you leave "tls_dhparam" |
147 | unset, so that you get one of the standard built-in primes used for DH. | |
148 | ||
149 | ||
51fb80db PP |
150 | DH, Diffie-Hellman (or Diffie-Hellman-Merkle, or something naming Williamson) |
151 | is the common name for a way for two parties to a communication stream to | |
152 | exchange some private random data so that both end up with a shared secret | |
8d68e115 | 153 | which no eavesdropper can get. It does not provide for proof of the identity |
51fb80db PP |
154 | of either party, so on its own is subject to man-in-the-middle attacks, but is |
155 | often combined with systems which do provide such proof, improving them by | |
156 | separating the session key (the shared secret) from the long-term identity, | |
157 | and so protecting past communications from a break of the long-term identity. | |
158 | ||
159 | To do this, the server sends to the client a very large prime number; this is | |
160 | in the clear, an attacker can see it. This is not a problem; it's so not a | |
161 | problem, that there are standard named primes which applications can use, and | |
8d68e115 | 162 | which Exim now supports. |
51fb80db PP |
163 | |
164 | The size of the prime number affects how difficult it is to break apart the | |
165 | shared secret and decrypt the data. As time passes, the size required to | |
166 | provide protection against an adversary climbs: computers get more powerful, | |
167 | mathematical advances are made, and so on. | |
168 | ||
169 | Estimates of the size needed are published as recommendations by various | |
170 | groups; a good summary of sizes currently recommended, for various | |
171 | cryptographic primitives, is available at: | |
172 | ||
173 | http://www.keylength.com/en/3/ | |
174 | ||
175 | The GnuTLS folks think the ECRYPT II advice is good. They know far more of | |
176 | such matters than the Exim folks, we just say "er, what they said". | |
177 | ||
178 | One of the new pieces of the GnuTLS API is a means for an application to ask | |
179 | it for guidance and advice on how large some numbers should be. This is not | |
8d68e115 | 180 | entirely internal to GnuTLS, since generating the numbers is slow, an |
51fb80db PP |
181 | application might want to use a standard prime, etc. So, in an attempt to get |
182 | away from being involved in cryptographic policy, and to get rid of a | |
183 | hard-coded "1024" in Exim's source-code, we switched to asking GnuTLS how many | |
8d68e115 PP |
184 | bits should be in the prime number generated for use for Diffie-Hellman. We |
185 | then give this number straight back to GnuTLS when generating a DH prime. | |
186 | We can ask for various sizes, and did not expose this to the administrator but | |
187 | instead just asked for "NORMAL" protection. | |
51fb80db PP |
188 | Literally: |
189 | ||
190 | dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_NORMAL); | |
191 | ||
192 | This API is only available as of GnuTLS 2.12. Prior to that release, we stuck | |
193 | with the old value, for compatibility, so "1024" is still hard-coded. | |
194 | Reviewing the page above, you'll see that this is described as "Short-term | |
195 | protection against medium organizations, medium-term protection against small | |
196 | organizations." | |
197 | ||
198 | So if you are using an old release of GnuTLS, you can either add to | |
199 | Local/Makefile a different value of "EXIM_SERVER_DH_BITS_PRE2_12" or accept | |
200 | that your protection might not be adequate to your needs. We advise updating | |
201 | to a more current GnuTLS release and rebuilding Exim against that. | |
202 | ||
203 | Unfortunately, some TLS libraries have the client side bound how large a DH | |
204 | prime they will accept from the server. The larger the number, the more | |
205 | computation required to work with it and the slower that things get. So they | |
206 | pick what they believe to be reasonable upper bounds, and then typically | |
207 | forget about it for several years. | |
208 | ||
209 | Worse, in TLS the DH negotiation happens after a ciphersuite has been chosen, | |
210 | so if the client dislikes the value then a different ciphersuite avoiding DH | |
211 | can not be negotiated! The client typically drops the connection, resulting | |
212 | in errors to the user and errors in the Exim logs. With GnuTLS 3, you'll see | |
213 | the EOF (End-Of-File) error message in Exim's logs, reported as being part of | |
214 | "gnutls_handshake", but with GnuTLS 2 you'll see a log message about a packet | |
215 | with an unexpected size. Unless the client software is written intelligently | |
216 | enough to be able to adapt and reconnect forbidding DH, the client will never | |
217 | be able to negotiate TLS. | |
218 | ||
219 | This time around, we discovered that the NSS library used by various Mozilla | |
220 | products, Chrome, etc, and most particularly by the Thunderbird mail client, | |
221 | has the lowest cap. In fact, prior to recent updates, their upper limit was | |
222 | lower than the value returned by GnuTLS for "NORMAL". The most recent NSS | |
223 | library release raises this, but the most recent Thunderbird release still has | |
224 | the old limit. | |
225 | ||
226 | So Exim had to get involved in cryptography policy decisions again. We added | |
227 | the "tls_dh_max_bits" global option, to set a number used in both OpenSSL and | |
228 | GnuTLS bindings for Exim. In GnuTLS, it clamps the value returned by | |
229 | gnutls_sec_param_to_pk_bits(), so that if the returned value is larger than | |
230 | tls_dh_max_bits then tls_dh_max_bits would be used instead. | |
231 | ||
232 | Our policy decision was to default the value of tls_dh_max_bits to the maximum | |
233 | supported in the most recent Thunderbird release, and to make this an | |
234 | administrator-available option so that administrators can choose to trade off | |
235 | security versus compatibility by raising it. | |
236 | ||
237 | A future release of Exim may even let the administrator tell GnuTLS to ask for | |
238 | more or less than "NORMAL". | |
239 | ||
201f5254 PP |
240 | To add to the fun, the size of the prime returned by GnuTLS when we call |
241 | gnutls_dh_params_generate2() is not limited to be the requested size. GnuTLS | |
242 | has a tendency to overshoot. 2237 bit primes are common when 2236 is | |
243 | requested, and higher still have been observed. Further, there is no API to | |
244 | ask how large the prime bundled up inside the parameter is; the most we can do | |
245 | is ask how large the DH prime used in an active TLS session is. Since we're | |
246 | not able to use GnuTLS API calls (and exporting to PKCS3 and then calling | |
247 | OpenSSL routines would be undiplomatic, plus add a library dependency), we're | |
248 | left with no way to actually know the size of the freshly generated DH prime. | |
249 | ||
250 | Thus we check if the the value returned is at least 10 more than the minimum | |
251 | we'll accept as a client (EXIM_CLIENT_DH_MIN_BITS, see below, defaults to | |
bba74fc6 | 252 | 1024) and if it is, we subtract 10. Then we reluctantly deploy a strategy |
201f5254 PP |
253 | called "hope". This is not guaranteed to be successful; in the first code |
254 | pass on this logic, we subtracted 3, asked for 2233 bits and got 2240 in the | |
255 | first test. | |
256 | ||
257 | If you see Thunderbird clients still failing, then as a user who can see into | |
258 | Exim's spool directory, run: | |
259 | ||
260 | $ openssl dhparam -noout -text -in /path/to/spool/gnutls-params-2236 | head | |
261 | ||
262 | Ideally, the first line will read "PKCS#3 DH Parameters: (2236 bit)". If the | |
263 | count is more than 2236, then remove the file and let Exim regenerate it, or | |
264 | generate one yourself and move it into place. Ideally use "openssl dhparam" | |
265 | to generate it, and then wait a very long time; at least this way, the size | |
a799883d PP |
266 | will be correct. |
267 | ||
268 | The use of "hope" as a strategy was felt to be unacceptable as a default, so | |
269 | late in the RC series for 4.80, the whole issue was side-stepped. The primes | |
270 | used for DH are publicly revealed; moreover, there are selection criteria for | |
271 | what makes a "good" DH prime. As it happens, there are *standard* primes | |
272 | which can be used, and are specified to be used for certain protocols. So | |
273 | these primes were built into Exim, and by default exim now uses a 2048 bit | |
274 | prime from section 2.2 of RFC 5114. | |
201f5254 PP |
275 | |
276 | ||
51fb80db PP |
277 | A TLS client does not get to choose the DH prime used, but can choose a |
278 | minimum acceptable value. For Exim, this is a compile-time constant called | |
bba74fc6 | 279 | "EXIM_CLIENT_DH_MIN_BITS" of 1024, which can be overruled in "Local/Makefile". |
51fb80db PP |
280 | |
281 | ||
282 | ||
283 | (7): What's a Priority String? | |
284 | ------------------------------ | |
285 | ||
286 | A priority string is a way for a user of GnuTLS to tell GnuTLS how it should | |
287 | make decisions about what to do in TLS; it includes which algorithms to make | |
288 | available for various roles, what compatibility trade-offs to make, which | |
289 | features to enable or disable. | |
290 | ||
291 | It is exposed to the Mail Administrator in Exim's configuration file as the | |
292 | "tls_require_ciphers" option, which exists as a main section option for use in | |
293 | Exim as a server, accepting connections, and as an option on Transports using | |
294 | the SMTP driver, for use in Exim as a client. The main section option is | |
295 | *not* the default for the transport option, they are entirely independent. | |
296 | For both, the default value used by Exim is the string "NORMAL". (This is not | |
297 | the same NORMAL as for DH prime bit size selection in Q6, but a different | |
298 | NORMAL.) See Q8. | |
299 | ||
300 | The current documentation, for the most recent release of GnuTLS, is available | |
301 | online at: | |
302 | ||
42bfef1e | 303 | http://www.gnutls.org/manual/html_node/Priority-Strings.html |
51fb80db PP |
304 | |
305 | Beware that if you are not using the most recent GnuTLS release then this | |
306 | documentation will be wrong for you! You should find the "info" documentation | |
307 | which came with GnuTLS to review the available options. It's under "The TLS | |
308 | Handshake Protocol". | |
309 | ||
310 | $ pinfo --node="Priority Strings" gnutls | |
311 | ||
312 | (This author is unable to persuade the "info" command-line tool to jump | |
313 | straight to the required node, but "pinfo" works.) | |
314 | ||
315 | To trade off some security for more compatibility, you might set a value of | |
316 | "NORMAL:%COMPAT". See the documentation for more, including lowering security | |
317 | even further for more security, forcing clients to use the server's protocol | |
318 | suite, and ways to force selection of particular algorithms. | |
319 | ||
320 | ||
321 | ||
322 | (8): How do I use tls_require_ciphers? | |
323 | -------------------------------------- | |
324 | ||
325 | This is the name of two options in Exim. One is a main section option, used | |
326 | by Exim as a server when a client initiates SSL/TLS negotiation, the other is | |
327 | an option on transports which use "driver = smtp", used when Exim initiates | |
328 | SSL/TLS as a client talking to a remote server. | |
329 | ||
330 | The option is expanded and so can take advantage of any variables which have | |
331 | been set. This includes the IP address of the remote side, the port upon | |
332 | which a connection was accepted (when a server), and more. Currently it does | |
333 | not have access to $tls_sni, whether as a client or as a server. | |
334 | ||
335 | This example, for the main section's option, will let the library defaults be | |
336 | permitted on the MX port, where there's probably no identity verification | |
337 | anyway, and lowers security further by increasing compatibility; but this ups | |
338 | the ante on the submission ports where the administrator might have some | |
339 | influence on the choice of clients used: | |
340 | ||
341 | tls_require_ciphers = ${if =={$received_port}{25}\ | |
342 | {NORMAL:%COMPAT}\ | |
343 | {SECURE128}} | |
344 | ||
345 | Note that during Exim start-up, when this option is sanity-checked, there will | |
346 | be no value of $received_port. In the above example, the checked value will | |
347 | thus be "SECURE128". Be careful to ensure that it always expands safely. | |
348 | ||
349 | ||
350 | ||
351 | (9): How do I test STARTTLS support? | |
352 | ------------------------------------ | |
353 | ||
354 | The best command-line client for debugging specifically SSL/TLS which this | |
355 | author has encountered is part of the GnuTLS suite, and is called | |
356 | "gnutls-cli". It's best because it's the only interactive tool which lets the | |
357 | user start TLS handshake exactly when they wish, so can choose to use the | |
358 | STARTTLS command. | |
359 | ||
360 | $ gnutls-cli --starttls --crlf --port 587 mail.example.org | |
361 | ||
362 | After EHLO, to see the capabilities, enter STARTTLS, wait for the response, | |
363 | then send EOF. Typically that's done by typing Ctrl-D at the start of a line. | |
364 | The "gnutls-cli" tool will take over, set up TLS (or fail) and by the time it | |
365 | returns to await more user input, you're using a secure connection and should | |
366 | type your second EHLO. | |
367 | ||
368 | The "--x509cafile" option may be helpful for checking certificates and | |
369 | "--priority" to pass a priority string to the client tool for configuring it. | |
370 | ||
371 | The --crlf is for strict protocol correctness, but Exim doesn't really need | |
372 | it, so "gnutls-cli -s -p 587 mail.example.org" is shorter. | |
373 | ||
374 | ||
375 | For debugging SMTP as a whole, we recommend swaks, "Swiss Army Knife SMTP", by | |
376 | John Jetmore (one of the Exim Maintainers). This has some TLS tuning options; | |
377 | it can be found at: | |
378 | ||
379 | http://www.jetmore.org/john/code/swaks/ | |
380 | ||
381 | ||
382 | For OpenSSL, the "openssl s_client" command helps; you can either set up Exim | |
383 | with a listening port which is SSL-on-connect or tell s_client to use | |
384 | STARTTLS. | |
385 | ||
386 | For the former, use the "tls_on_connect_ports" option and the | |
387 | "daemon_smtp_ports" option. Most clients for SSL-on-connect use the port | |
388 | which was briefly registered with IANA for this purpose, 465. So you would | |
389 | set something like: | |
390 | ||
391 | daemon_smtp_ports = 25 : 465 : 587 | |
392 | tls_on_connect_ports = 465 | |
393 | ||
394 | To use s_client with STARTTLS support, use "-starttls smtp" on the | |
395 | command-line. Beware that older versions of OpenSSL did not wait for the SMTP | |
396 | banner before sending EHLO, which will fall afoul of the protocol | |
397 | synchronisation checks in Exim (used to trip up pump-and-dump spammers); also | |
398 | you will not get control of the session until TLS is established. That said, | |
399 | this tool provides more tuning hooks for adjusting how TLS will be set up than | |
400 | most. | |
401 | ||
402 | *BEWARE* that by default, s_client will take any line starting with a capital | |
403 | letter "R" to be a request to initiate TLS renegotiation with the server and | |
404 | the line will not be sent. This may trip up "RCPT TO:<someone@example.org>" | |
405 | lines in SMTP. SMTP is not case-sensitive, so type "rcpt to" instead. | |
406 | Alternatively, invoke s_client with the "-ign_eof" option to disable this | |
407 | R-filtering and a few other features. | |
408 | ||
409 | ||
410 | # END OF FAQ |