~ubuntu-branches/ubuntu/natty/exim4/natty

« back to all changes in this revision

Viewing changes to .pc/66_enlarge-dh-parameters-size.dpatch/src/tls-gnu.c

  • Committer: Bazaar Package Importer
  • Author(s): Artur Rona
  • Date: 2010-07-25 02:00:42 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100725020042-bk1uw1p7ysmnsn9f
Tags: 4.72-1ubuntu1
* Merge with Debian unstable (LP: #609620). Remaining changes:
  + debian/patches/71_exiq_grep_error_on_messages_without_size.dpatch:
    Improve handling of broken messages when "exim4 -bp" (mailq) reports
    lines without size info.
  + Don't declare a Provides: default-mta; in Ubuntu, we want postfix to be
    the default.
  + debian/control: Change build dependencies to MySQL 5.1.
  + debian/{control,rules}: add and enable hardened build for PIE
    (Closes: #542726).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Cambridge: exim/exim-src/src/tls-gnu.c,v 1.24 2009/11/16 19:50:37 nm4 Exp $ */
 
2
 
 
3
/*************************************************
 
4
*     Exim - an Internet mail transport agent    *
 
5
*************************************************/
 
6
 
 
7
/* Copyright (c) University of Cambridge 1995 - 2009 */
 
8
/* See the file NOTICE for conditions of use and distribution. */
 
9
 
 
10
/* This module provides TLS (aka SSL) support for Exim using the GnuTLS
 
11
library. It is #included into tls.c when that library is used. The code herein
 
12
is based on a patch that was contributed by Nikos Mavroyanopoulos.
 
13
 
 
14
No cryptographic code is included in Exim. All this module does is to call
 
15
functions from the GnuTLS library. */
 
16
 
 
17
 
 
18
/* Heading stuff for GnuTLS */
 
19
 
 
20
#include <gnutls/gnutls.h>
 
21
#include <gnutls/x509.h>
 
22
 
 
23
 
 
24
#define UNKNOWN_NAME "unknown"
 
25
#define DH_BITS      1024
 
26
#define PARAM_SIZE 2*1024
 
27
 
 
28
 
 
29
/* Values for verify_requirment */
 
30
 
 
31
enum { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED };
 
32
 
 
33
/* Local static variables for GNUTLS */
 
34
 
 
35
static host_item *client_host;
 
36
 
 
37
static gnutls_dh_params dh_params = NULL;
 
38
 
 
39
static gnutls_certificate_server_credentials x509_cred = NULL;
 
40
static gnutls_session tls_session = NULL;
 
41
 
 
42
static char ssl_errstring[256];
 
43
 
 
44
static int  ssl_session_timeout = 200;
 
45
static int  verify_requirement;
 
46
 
 
47
/* Priorities for TLS algorithms to use. In each case there's a default table,
 
48
and space into which it can be copied and altered. */
 
49
 
 
50
static const int default_proto_priority[16] = {
 
51
  GNUTLS_TLS1,
 
52
  GNUTLS_SSL3,
 
53
  0 };
 
54
 
 
55
static int proto_priority[16];
 
56
 
 
57
static const int default_kx_priority[16] = {
 
58
  GNUTLS_KX_RSA,
 
59
  GNUTLS_KX_DHE_DSS,
 
60
  GNUTLS_KX_DHE_RSA,
 
61
  0 };
 
62
 
 
63
static int kx_priority[16];
 
64
 
 
65
static int default_cipher_priority[16] = {
 
66
  GNUTLS_CIPHER_AES_256_CBC,
 
67
  GNUTLS_CIPHER_AES_128_CBC,
 
68
  GNUTLS_CIPHER_3DES_CBC,
 
69
  GNUTLS_CIPHER_ARCFOUR_128,
 
70
  0 };
 
71
 
 
72
static int cipher_priority[16];
 
73
 
 
74
static const int default_mac_priority[16] = {
 
75
  GNUTLS_MAC_SHA,
 
76
  GNUTLS_MAC_MD5,
 
77
  0 };
 
78
 
 
79
static int mac_priority[16];
 
80
 
 
81
/* These two are currently not changeable. */
 
82
 
 
83
static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
 
84
static const int cert_type_priority[16] = { GNUTLS_CRT_X509, 0 };
 
85
 
 
86
/* Tables of priority names and equivalent numbers */
 
87
 
 
88
typedef struct pri_item {
 
89
  uschar *name;
 
90
  int *values;
 
91
} pri_item;
 
92
 
 
93
 
 
94
static int tls1_codes[] = { GNUTLS_TLS1, 0 };
 
95
static int ssl3_codes[] = { GNUTLS_SSL3, 0 };
 
96
 
 
97
static pri_item proto_index[] = {
 
98
  { US"TLS1", tls1_codes },
 
99
  { US"SSL3", ssl3_codes }
 
100
};
 
101
 
 
102
 
 
103
static int kx_rsa_codes[]      = { GNUTLS_KX_RSA,
 
104
                                   GNUTLS_KX_DHE_RSA, 0 };
 
105
static int kx_dhe_codes[]      = { GNUTLS_KX_DHE_DSS,
 
106
                                   GNUTLS_KX_DHE_RSA, 0 };
 
107
static int kx_dhe_dss_codes[]  = { GNUTLS_KX_DHE_DSS, 0 };
 
108
static int kx_dhe_rsa_codes[]  = { GNUTLS_KX_DHE_RSA, 0 };
 
109
 
 
110
static pri_item kx_index[] = {
 
111
  { US"DHE_DSS", kx_dhe_dss_codes },
 
112
  { US"DHE_RSA", kx_dhe_rsa_codes },
 
113
  { US"RSA", kx_rsa_codes },
 
114
  { US"DHE", kx_dhe_codes }
 
115
};
 
116
 
 
117
 
 
118
static int arcfour_128_codes[] = { GNUTLS_CIPHER_ARCFOUR_128, 0 };
 
119
static int arcfour_40_codes[]  = { GNUTLS_CIPHER_ARCFOUR_40, 0 };
 
120
static int arcfour_codes[]     = { GNUTLS_CIPHER_ARCFOUR_128,
 
121
                                   GNUTLS_CIPHER_ARCFOUR_40, 0 };
 
122
static int aes_256_codes[]     = { GNUTLS_CIPHER_AES_256_CBC, 0 };
 
123
static int aes_128_codes[]     = { GNUTLS_CIPHER_AES_128_CBC, 0 };
 
124
static int aes_codes[]         = { GNUTLS_CIPHER_AES_256_CBC,
 
125
                                   GNUTLS_CIPHER_AES_128_CBC, 0 };
 
126
static int des3_codes[]        = { GNUTLS_CIPHER_3DES_CBC, 0 };
 
127
 
 
128
static pri_item cipher_index[] = {
 
129
  { US"ARCFOUR_128", arcfour_128_codes },
 
130
  { US"ARCFOUR_40", arcfour_40_codes },
 
131
  { US"ARCFOUR", arcfour_codes },
 
132
  { US"AES_256", aes_256_codes },
 
133
  { US"AES_128", aes_128_codes },
 
134
  { US"AES", aes_codes },
 
135
  { US"3DES", des3_codes }
 
136
};
 
137
 
 
138
 
 
139
static int mac_sha_codes[]     = { GNUTLS_MAC_SHA, 0 };
 
140
static int mac_md5_codes[]     = { GNUTLS_MAC_MD5, 0 };
 
141
 
 
142
static pri_item mac_index[] = {
 
143
  { US"SHA",  mac_sha_codes },
 
144
  { US"SHA1", mac_sha_codes },
 
145
  { US"MD5",  mac_md5_codes }
 
146
};
 
147
 
 
148
 
 
149
 
 
150
/*************************************************
 
151
*               Handle TLS error                 *
 
152
*************************************************/
 
153
 
 
154
/* Called from lots of places when errors occur before actually starting to do
 
155
the TLS handshake, that is, while the session is still in clear. Always returns
 
156
DEFER for a server and FAIL for a client so that most calls can use "return
 
157
tls_error(...)" to do this processing and then give an appropriate return. A
 
158
single function is used for both server and client, because it is called from
 
159
some shared functions.
 
160
 
 
161
Argument:
 
162
  prefix    text to include in the logged error
 
163
  host      NULL if setting up a server;
 
164
            the connected host if setting up a client
 
165
  msg       additional error string (may be NULL)
 
166
            usually obtained from gnutls_strerror()
 
167
 
 
168
Returns:    OK/DEFER/FAIL
 
169
*/
 
170
 
 
171
static int
 
172
tls_error(uschar *prefix, host_item *host, const char *msg)
 
173
{
 
174
if (host == NULL)
 
175
  {
 
176
  uschar *conn_info = smtp_get_connection_info();
 
177
  if (strncmp(conn_info, "SMTP ", 5) == 0)
 
178
    conn_info += 5;
 
179
  log_write(0, LOG_MAIN, "TLS error on %s (%s)%s%s",
 
180
    conn_info, prefix, msg ? ": " : "", msg ? msg : "");
 
181
  return DEFER;
 
182
  }
 
183
else
 
184
  {
 
185
  log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s)%s%s",
 
186
    host->name, host->address, prefix, msg ? ": " : "", msg ? msg : "");
 
187
  return FAIL;
 
188
  }
 
189
}
 
190
 
 
191
 
 
192
 
 
193
/*************************************************
 
194
*             Verify certificate                 *
 
195
*************************************************/
 
196
 
 
197
/* Called after a successful handshake, when certificate verification is
 
198
required or optional, for both server and client.
 
199
 
 
200
Arguments:
 
201
  session    GNUTLS session
 
202
  error      where to put text giving a reason for failure
 
203
 
 
204
Returns:     TRUE/FALSE
 
205
*/
 
206
 
 
207
static BOOL
 
208
verify_certificate(gnutls_session session, const char **error)
 
209
{
 
210
int verify;
 
211
uschar *dn_string = US"";
 
212
const gnutls_datum *cert;
 
213
unsigned int cert_size = 0;
 
214
 
 
215
*error = NULL;
 
216
 
 
217
/* Get the peer's certificate. If it sent one, extract it's DN, and then
 
218
attempt to verify the certificate. If no certificate is supplied, verification
 
219
is forced to fail. */
 
220
 
 
221
cert = gnutls_certificate_get_peers(session, &cert_size);
 
222
if (cert != NULL)
 
223
  {
 
224
  uschar buff[1024];
 
225
  gnutls_x509_crt gcert;
 
226
 
 
227
  gnutls_x509_crt_init(&gcert);
 
228
  dn_string = US"unknown";
 
229
 
 
230
  if (gnutls_x509_crt_import(gcert, cert, GNUTLS_X509_FMT_DER) == 0)
 
231
    {
 
232
    size_t bufsize = sizeof(buff);
 
233
    if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
 
234
      dn_string = string_copy_malloc(buff);
 
235
    }
 
236
 
 
237
  verify = gnutls_certificate_verify_peers(session);
 
238
  }
 
239
else
 
240
  {
 
241
  DEBUG(D_tls) debug_printf("no peer certificate supplied\n");
 
242
  verify = GNUTLS_CERT_INVALID;
 
243
  *error = "not supplied";
 
244
  }
 
245
 
 
246
/* Handle the result of verification. INVALID seems to be set as well
 
247
as REVOKED, but leave the test for both. */
 
248
 
 
249
if ((verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0)
 
250
  {
 
251
  tls_certificate_verified = FALSE;
 
252
  if (*error == NULL) *error = ((verify & GNUTLS_CERT_REVOKED) != 0)?
 
253
    "revoked" : "invalid";
 
254
  if (verify_requirement == VERIFY_REQUIRED)
 
255
    {
 
256
    DEBUG(D_tls) debug_printf("TLS certificate verification failed (%s): "
 
257
      "peerdn=%s\n", *error, dn_string);
 
258
    gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE);
 
259
    return FALSE;                       /* reject */
 
260
    }
 
261
  DEBUG(D_tls) debug_printf("TLS certificate verify failure (%s) overridden "
 
262
      "(host in tls_try_verify_hosts): peerdn=%s\n", *error, dn_string);
 
263
  }
 
264
else
 
265
  {
 
266
  tls_certificate_verified = TRUE;
 
267
  DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=%s\n",
 
268
    dn_string);
 
269
  }
 
270
 
 
271
tls_peerdn = dn_string;
 
272
return TRUE;                            /* accept */
 
273
}
 
274
 
 
275
 
 
276
 
 
277
/*************************************************
 
278
*            Setup up DH parameters              *
 
279
*************************************************/
 
280
 
 
281
/* Generating the D-H parameters may take a long time. They only need to
 
282
be re-generated every so often, depending on security policy. What we do is to
 
283
keep these parameters in a file in the spool directory. If the file does not
 
284
exist, we generate them. This means that it is easy to cause a regeneration.
 
285
 
 
286
The new file is written as a temporary file and renamed, so that an incomplete
 
287
file is never present. If two processes both compute some new parameters, you
 
288
waste a bit of effort, but it doesn't seem worth messing around with locking to
 
289
prevent this.
 
290
 
 
291
Argument:
 
292
  host       NULL for server, server for client (for error handling)
 
293
 
 
294
Returns:     OK/DEFER/FAIL
 
295
*/
 
296
 
 
297
static int
 
298
init_dh(host_item *host)
 
299
{
 
300
int fd;
 
301
int ret;
 
302
gnutls_datum m;
 
303
uschar filename[200];
 
304
 
 
305
/* Initialize the data structures for holding the parameters */
 
306
 
 
307
ret = gnutls_dh_params_init(&dh_params);
 
308
if (ret < 0) return tls_error(US"init dh_params", host, gnutls_strerror(ret));
 
309
 
 
310
/* Set up the name of the cache file */
 
311
 
 
312
if (!string_format(filename, sizeof(filename), "%s/gnutls-params",
 
313
      spool_directory))
 
314
  return tls_error(US"overlong filename", host, NULL);
 
315
 
 
316
/* Open the cache file for reading and if successful, read it and set up the
 
317
parameters. */
 
318
 
 
319
fd = Uopen(filename, O_RDONLY, 0);
 
320
if (fd >= 0)
 
321
  {
 
322
  struct stat statbuf;
 
323
  if (fstat(fd, &statbuf) < 0)
 
324
    {
 
325
    (void)close(fd);
 
326
    return tls_error(US"TLS cache stat failed", host, strerror(errno));
 
327
    }
 
328
 
 
329
  m.size = statbuf.st_size;
 
330
  m.data = malloc(m.size);
 
331
  if (m.data == NULL)
 
332
    return tls_error(US"memory allocation failed", host, strerror(errno));
 
333
  errno = 0;
 
334
  if (read(fd, m.data, m.size) != m.size)
 
335
    return tls_error(US"TLS cache read failed", host, strerror(errno));
 
336
  (void)close(fd);
 
337
 
 
338
  ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
 
339
  if (ret < 0)
 
340
    return tls_error(US"DH params import", host, gnutls_strerror(ret));
 
341
  DEBUG(D_tls) debug_printf("read D-H parameters from file\n");
 
342
 
 
343
  free(m.data);
 
344
  }
 
345
 
 
346
/* If the file does not exist, fall through to compute new data and cache it.
 
347
If there was any other opening error, it is serious. */
 
348
 
 
349
else if (errno == ENOENT)
 
350
  {
 
351
  ret = -1;
 
352
  DEBUG(D_tls)
 
353
    debug_printf("parameter cache file %s does not exist\n", filename);
 
354
  }
 
355
else
 
356
  return tls_error(string_open_failed(errno, "%s for reading", filename),
 
357
    host, NULL);
 
358
 
 
359
/* If ret < 0, either the cache file does not exist, or the data it contains
 
360
is not useful. One particular case of this is when upgrading from an older
 
361
release of Exim in which the data was stored in a different format. We don't
 
362
try to be clever and support both formats; we just regenerate new data in this
 
363
case. */
 
364
 
 
365
if (ret < 0)
 
366
  {
 
367
  uschar tempfilename[sizeof(filename) + 10];
 
368
 
 
369
  DEBUG(D_tls) debug_printf("generating %d bit Diffie-Hellman key...\n",
 
370
    DH_BITS);
 
371
  ret = gnutls_dh_params_generate2(dh_params, DH_BITS);
 
372
  if (ret < 0) return tls_error(US"D-H key generation", host, gnutls_strerror(ret));
 
373
 
 
374
  /* Write the parameters to a file in the spool directory so that we
 
375
  can use them from other Exim processes. */
 
376
 
 
377
  sprintf(CS tempfilename, "%s-%d", filename, (int)getpid());
 
378
  fd = Uopen(tempfilename, O_WRONLY|O_CREAT, 0400);
 
379
  if (fd < 0)
 
380
    return tls_error(string_open_failed(errno, "%s for writing", filename),
 
381
      host, NULL);
 
382
  (void)fchown(fd, exim_uid, exim_gid);   /* Probably not necessary */
 
383
 
 
384
  /* export the parameters in a format that can be generated using GNUTLS'
 
385
   * certtool or other programs.
 
386
   *
 
387
   * The commands for certtool are:
 
388
   * $ certtool --generate-dh-params --bits 1024 > params
 
389
   */
 
390
 
 
391
  m.size = PARAM_SIZE;
 
392
  m.data = malloc(m.size);
 
393
  if (m.data == NULL)
 
394
    return tls_error(US"memory allocation failed", host, strerror(errno));
 
395
 
 
396
  m.size = PARAM_SIZE;
 
397
  ret = gnutls_dh_params_export_pkcs3(dh_params, GNUTLS_X509_FMT_PEM, m.data,
 
398
    &m.size);
 
399
  if (ret < 0)
 
400
    return tls_error(US"DH params export", host, gnutls_strerror(ret));
 
401
 
 
402
  m.size = Ustrlen(m.data);
 
403
  errno = 0;
 
404
  if (write(fd, m.data, m.size) != m.size || write(fd, "\n", 1) != 1)
 
405
    return tls_error(US"TLS cache write failed", host, strerror(errno));
 
406
 
 
407
  free(m.data);
 
408
  (void)close(fd);
 
409
 
 
410
  if (rename(CS tempfilename, CS filename) < 0)
 
411
    return tls_error(string_sprintf("failed to rename %s as %s",
 
412
      tempfilename, filename), host, strerror(errno));
 
413
 
 
414
  DEBUG(D_tls) debug_printf("wrote D-H parameters to file %s\n", filename);
 
415
  }
 
416
 
 
417
DEBUG(D_tls) debug_printf("initialized D-H parameters\n");
 
418
return OK;
 
419
}
 
420
 
 
421
 
 
422
 
 
423
 
 
424
/*************************************************
 
425
*            Initialize for GnuTLS               *
 
426
*************************************************/
 
427
 
 
428
/* Called from both server and client code. In the case of a server, errors
 
429
before actual TLS negotiation return DEFER.
 
430
 
 
431
Arguments:
 
432
  host            connected host, if client; NULL if server
 
433
  certificate     certificate file
 
434
  privatekey      private key file
 
435
  cas             CA certs file
 
436
  crl             CRL file
 
437
 
 
438
Returns:          OK/DEFER/FAIL
 
439
*/
 
440
 
 
441
static int
 
442
tls_init(host_item *host, uschar *certificate, uschar *privatekey, uschar *cas,
 
443
  uschar *crl)
 
444
{
 
445
int rc;
 
446
uschar *cert_expanded, *key_expanded, *cas_expanded, *crl_expanded;
 
447
 
 
448
client_host = host;
 
449
 
 
450
rc = gnutls_global_init();
 
451
if (rc < 0) return tls_error(US"tls-init", host, gnutls_strerror(rc));
 
452
 
 
453
/* Create D-H parameters, or read them from the cache file. This function does
 
454
its own SMTP error messaging. */
 
455
 
 
456
rc = init_dh(host);
 
457
if (rc != OK) return rc;
 
458
 
 
459
/* Create the credentials structure */
 
460
 
 
461
rc = gnutls_certificate_allocate_credentials(&x509_cred);
 
462
if (rc < 0)
 
463
  return tls_error(US"certificate_allocate_credentials",
 
464
    host, gnutls_strerror(rc));
 
465
 
 
466
/* This stuff must be done for each session, because different certificates
 
467
may be required for different sessions. */
 
468
 
 
469
if (!expand_check(certificate, US"tls_certificate", &cert_expanded))
 
470
  return DEFER;
 
471
 
 
472
key_expanded = NULL;
 
473
if (privatekey != NULL)
 
474
  {
 
475
  if (!expand_check(privatekey, US"tls_privatekey", &key_expanded))
 
476
    return DEFER;
 
477
  }
 
478
 
 
479
/* If expansion was forced to fail, key_expanded will be NULL. If the result of
 
480
the expansion is an empty string, ignore it also, and assume that the private
 
481
key is in the same file as the certificate. */
 
482
 
 
483
if (key_expanded == NULL || *key_expanded == 0)
 
484
  key_expanded = cert_expanded;
 
485
 
 
486
/* Set the certificate and private keys */
 
487
 
 
488
if (cert_expanded != NULL)
 
489
  {
 
490
  DEBUG(D_tls) debug_printf("certificate file = %s\nkey file = %s\n",
 
491
    cert_expanded, key_expanded);
 
492
  rc = gnutls_certificate_set_x509_key_file(x509_cred, CS cert_expanded,
 
493
    CS key_expanded, GNUTLS_X509_FMT_PEM);
 
494
  if (rc < 0)
 
495
    {
 
496
    uschar *msg = string_sprintf("cert/key setup: cert=%s key=%s",
 
497
      cert_expanded, key_expanded);
 
498
    return tls_error(msg, host, gnutls_strerror(rc));
 
499
    }
 
500
  }
 
501
 
 
502
/* A certificate is mandatory in a server, but not in a client */
 
503
 
 
504
else
 
505
  {
 
506
  if (host == NULL)
 
507
    return tls_error(US"no TLS server certificate is specified", NULL, NULL);
 
508
  DEBUG(D_tls) debug_printf("no TLS client certificate is specified\n");
 
509
  }
 
510
 
 
511
/* Set the trusted CAs file if one is provided, and then add the CRL if one is
 
512
provided. Experiment shows that, if the certificate file is empty, an unhelpful
 
513
error message is provided. However, if we just refrain from setting anything up
 
514
in that case, certificate verification fails, which seems to be the correct
 
515
behaviour. */
 
516
 
 
517
if (cas != NULL)
 
518
  {
 
519
  struct stat statbuf;
 
520
 
 
521
  if (!expand_check(cas, US"tls_verify_certificates", &cas_expanded))
 
522
    return DEFER;
 
523
 
 
524
  if (stat(CS cas_expanded, &statbuf) < 0)
 
525
    {
 
526
    log_write(0, LOG_MAIN|LOG_PANIC, "could not stat %s "
 
527
      "(tls_verify_certificates): %s", cas_expanded, strerror(errno));
 
528
    return DEFER;
 
529
    }
 
530
 
 
531
  DEBUG(D_tls) debug_printf("verify certificates = %s size=" OFF_T_FMT "\n",
 
532
    cas_expanded, statbuf.st_size);
 
533
 
 
534
  /* If the cert file is empty, there's no point in loading the CRL file. */
 
535
 
 
536
  if (statbuf.st_size > 0)
 
537
    {
 
538
    rc = gnutls_certificate_set_x509_trust_file(x509_cred, CS cas_expanded,
 
539
      GNUTLS_X509_FMT_PEM);
 
540
    if (rc < 0) return tls_error(US"setup_certs", host, gnutls_strerror(rc));
 
541
 
 
542
    if (crl != NULL && *crl != 0)
 
543
      {
 
544
      if (!expand_check(crl, US"tls_crl", &crl_expanded))
 
545
        return DEFER;
 
546
      DEBUG(D_tls) debug_printf("loading CRL file = %s\n", crl_expanded);
 
547
      rc = gnutls_certificate_set_x509_crl_file(x509_cred, CS crl_expanded,
 
548
        GNUTLS_X509_FMT_PEM);
 
549
      if (rc < 0) return tls_error(US"CRL setup", host, gnutls_strerror(rc));
 
550
      }
 
551
    }
 
552
  }
 
553
 
 
554
/* Associate the parameters with the x509 credentials structure. */
 
555
 
 
556
gnutls_certificate_set_dh_params(x509_cred, dh_params);
 
557
 
 
558
DEBUG(D_tls) debug_printf("initialized certificate stuff\n");
 
559
return OK;
 
560
}
 
561
 
 
562
 
 
563
 
 
564
 
 
565
/*************************************************
 
566
*           Remove from a priority list          *
 
567
*************************************************/
 
568
 
 
569
/* Cautiously written so that it will remove duplicates if present.
 
570
 
 
571
Arguments:
 
572
  list         a zero-terminated list
 
573
  remove_list  a zero-terminated list to be removed
 
574
 
 
575
Returns:       nothing
 
576
*/
 
577
 
 
578
static void
 
579
remove_priority(int *list, int *remove_list)
 
580
{
 
581
for (; *remove_list != 0; remove_list++)
 
582
  {
 
583
  int *p = list;
 
584
  while (*p != 0)
 
585
    {
 
586
    if (*p == *remove_list)
 
587
      {
 
588
      int *pp = p;
 
589
      do { pp[0] = pp[1]; pp++; } while (*pp != 0);
 
590
      }
 
591
    else p++;
 
592
    }
 
593
  }
 
594
}
 
595
 
 
596
 
 
597
 
 
598
/*************************************************
 
599
*            Add to a priority list              *
 
600
*************************************************/
 
601
 
 
602
/* Cautiously written to check the list size
 
603
 
 
604
Arguments:
 
605
  list         a zero-terminated list
 
606
  list_max     maximum offset in the list
 
607
  add_list     a zero-terminated list to be added
 
608
 
 
609
Returns:       TRUE if OK; FALSE if list overflows
 
610
*/
 
611
 
 
612
static BOOL
 
613
add_priority(int *list, int list_max, int *add_list)
 
614
{
 
615
int next = 0;
 
616
while (list[next] != 0) next++;
 
617
while (*add_list != 0)
 
618
  {
 
619
  if (next >= list_max) return FALSE;
 
620
  list[next++] = *add_list++;
 
621
  }
 
622
list[next] = 0;
 
623
return TRUE;
 
624
}
 
625
 
 
626
 
 
627
 
 
628
/*************************************************
 
629
*          Adjust a priority list                *
 
630
*************************************************/
 
631
 
 
632
/* This function is called to adjust the lists of cipher algorithms, MAC
 
633
algorithms, key-exchange methods, and protocols.
 
634
 
 
635
Arguments:
 
636
  plist       the appropriate priority list
 
637
  psize       the length of the list
 
638
  s           the configuation string
 
639
  index       the index of recognized strings
 
640
  isize       the length of the index
 
641
 
 
642
 
 
643
  which       text for an error message
 
644
 
 
645
Returns:      FALSE if the table overflows, else TRUE
 
646
*/
 
647
 
 
648
static BOOL
 
649
set_priority(int *plist, int psize, uschar *s, pri_item *index, int isize,
 
650
   uschar *which)
 
651
{
 
652
int sep = 0;
 
653
BOOL first = TRUE;
 
654
uschar *t;
 
655
 
 
656
while ((t = string_nextinlist(&s, &sep, big_buffer, big_buffer_size)) != NULL)
 
657
  {
 
658
  int i;
 
659
  BOOL exclude = t[0] == '!';
 
660
  if (first && !exclude) plist[0] = 0;
 
661
  first = FALSE;
 
662
  for (i = 0; i < isize; i++)
 
663
    {
 
664
    uschar *ss = strstric(t, index[i].name, FALSE);
 
665
    if (ss != NULL)
 
666
      {
 
667
      uschar *endss = ss + Ustrlen(index[i].name);
 
668
      if ((ss == t || !isalnum(ss[-1])) && !isalnum(*endss))
 
669
        {
 
670
        if (exclude)
 
671
          remove_priority(plist, index[i].values);
 
672
        else
 
673
          {
 
674
          if (!add_priority(plist, psize, index[i].values))
 
675
            {
 
676
            log_write(0, LOG_MAIN|LOG_PANIC, "GnuTLS init failed: %s "
 
677
              "priority table overflow", which);
 
678
            return FALSE;
 
679
            }
 
680
          }
 
681
        }
 
682
      }
 
683
    }
 
684
  }
 
685
 
 
686
DEBUG(D_tls)
 
687
  {
 
688
  int *ptr = plist;
 
689
  debug_printf("adjusted %s priorities:", which);
 
690
  while (*ptr != 0) debug_printf(" %d", *ptr++);
 
691
  debug_printf("\n");
 
692
  }
 
693
 
 
694
return TRUE;
 
695
}
 
696
 
 
697
 
 
698
 
 
699
 
 
700
/*************************************************
 
701
*        Initialize a single GNUTLS session      *
 
702
*************************************************/
 
703
 
 
704
/* Set the algorithm, the db backend, whether to request certificates etc.
 
705
 
 
706
TLS in Exim was first implemented using OpenSSL. This has a function to which
 
707
you pass a list of cipher suites that are permitted/not permitted. GnuTLS works
 
708
differently. It operates using priority lists for the different components of
 
709
cipher suites.
 
710
 
 
711
For compatibility of configuration, we scan a list of cipher suites and set
 
712
priorities therefrom. However, at the moment, we pay attention only to the bulk
 
713
cipher.
 
714
 
 
715
Arguments:
 
716
  side         one of GNUTLS_SERVER, GNUTLS_CLIENT
 
717
  expciphers   expanded ciphers list or NULL
 
718
  expmac       expanded MAC list or NULL
 
719
  expkx        expanded key-exchange list or NULL
 
720
  expproto     expanded protocol list or NULL
 
721
 
 
722
Returns:  a gnutls_session, or NULL if there is a problem
 
723
*/
 
724
 
 
725
static gnutls_session
 
726
tls_session_init(int side, uschar *expciphers, uschar *expmac, uschar *expkx,
 
727
  uschar *expproto)
 
728
{
 
729
gnutls_session session;
 
730
 
 
731
gnutls_init(&session, side);
 
732
 
 
733
/* Initialize the lists of permitted protocols, key-exchange methods, ciphers,
 
734
and MACs. */
 
735
 
 
736
memcpy(cipher_priority, default_cipher_priority, sizeof(cipher_priority));
 
737
memcpy(mac_priority, default_mac_priority, sizeof(mac_priority));
 
738
memcpy(kx_priority, default_kx_priority, sizeof(kx_priority));
 
739
memcpy(proto_priority, default_proto_priority, sizeof(proto_priority));
 
740
 
 
741
/* The names OpenSSL uses in tls_require_ciphers are of the form DES-CBC3-SHA,
 
742
using hyphen separators. GnuTLS uses underscore separators. So that I can use
 
743
either form for tls_require_ciphers in my tests, and also for general
 
744
convenience, we turn hyphens into underscores before scanning the list. */
 
745
 
 
746
if (expciphers != NULL)
 
747
  {
 
748
  uschar *s = expciphers;
 
749
  while (*s != 0) { if (*s == '-') *s = '_'; s++; }
 
750
  }
 
751
 
 
752
if ((expciphers != NULL &&
 
753
      !set_priority(cipher_priority, sizeof(cipher_priority)/sizeof(int),
 
754
        expciphers, cipher_index, sizeof(cipher_index)/sizeof(pri_item),
 
755
        US"cipher")) ||
 
756
    (expmac != NULL &&
 
757
      !set_priority(mac_priority, sizeof(mac_priority)/sizeof(int),
 
758
        expmac, mac_index, sizeof(mac_index)/sizeof(pri_item),
 
759
        US"MAC")) ||
 
760
    (expkx != NULL &&
 
761
      !set_priority(kx_priority, sizeof(kx_priority)/sizeof(int),
 
762
        expkx, kx_index, sizeof(kx_index)/sizeof(pri_item),
 
763
        US"key-exchange")) ||
 
764
    (expproto != NULL &&
 
765
      !set_priority(proto_priority, sizeof(proto_priority)/sizeof(int),
 
766
        expproto, proto_index, sizeof(proto_index)/sizeof(pri_item),
 
767
        US"protocol")))
 
768
  {
 
769
  gnutls_deinit(session);
 
770
  return NULL;
 
771
  }
 
772
 
 
773
/* Define the various priorities */
 
774
 
 
775
gnutls_cipher_set_priority(session, cipher_priority);
 
776
gnutls_compression_set_priority(session, comp_priority);
 
777
gnutls_kx_set_priority(session, kx_priority);
 
778
gnutls_protocol_set_priority(session, proto_priority);
 
779
gnutls_mac_set_priority(session, mac_priority);
 
780
 
 
781
gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
 
782
 
 
783
gnutls_dh_set_prime_bits(session, DH_BITS);
 
784
 
 
785
/* Request or demand a certificate of the peer, as configured. This will
 
786
happen only in a server. */
 
787
 
 
788
if (verify_requirement != VERIFY_NONE)
 
789
  gnutls_certificate_server_set_request(session,
 
790
    (verify_requirement == VERIFY_OPTIONAL)?
 
791
      GNUTLS_CERT_REQUEST : GNUTLS_CERT_REQUIRE);
 
792
 
 
793
gnutls_db_set_cache_expiration(session, ssl_session_timeout);
 
794
 
 
795
/* Reduce security in favour of increased compatibility, if the admin
 
796
decides to make that trade-off. */
 
797
if (gnutls_compat_mode)
 
798
  {
 
799
#if LIBGNUTLS_VERSION_NUMBER >= 0x020104
 
800
  DEBUG(D_tls) debug_printf("lowering GnuTLS security, compatibility mode\n");
 
801
  gnutls_session_enable_compatibility_mode(session);
 
802
#else
 
803
  DEBUG(D_tls) debug_printf("Unable to set gnutls_compat_mode - GnuTLS version too old\n");
 
804
#endif
 
805
  }
 
806
 
 
807
DEBUG(D_tls) debug_printf("initialized GnuTLS session\n");
 
808
return session;
 
809
}
 
810
 
 
811
 
 
812
 
 
813
/*************************************************
 
814
*           Get name of cipher in use            *
 
815
*************************************************/
 
816
 
 
817
/* The answer is left in a static buffer, and tls_cipher is set to point
 
818
to it.
 
819
 
 
820
Argument:   pointer to a GnuTLS session
 
821
Returns:    nothing
 
822
*/
 
823
 
 
824
static void
 
825
construct_cipher_name(gnutls_session session)
 
826
{
 
827
static uschar cipherbuf[256];
 
828
uschar *ver;
 
829
int bits, c, kx, mac;
 
830
 
 
831
ver = string_copy(
 
832
  US gnutls_protocol_get_name(gnutls_protocol_get_version(session)));
 
833
if (Ustrncmp(ver, "TLS ", 4) == 0) ver[3] = '-';   /* Don't want space */
 
834
 
 
835
c = gnutls_cipher_get(session);
 
836
bits = gnutls_cipher_get_key_size(c);
 
837
 
 
838
mac = gnutls_mac_get(session);
 
839
kx = gnutls_kx_get(session);
 
840
 
 
841
string_format(cipherbuf, sizeof(cipherbuf), "%s:%s:%u", ver,
 
842
  gnutls_cipher_suite_get_name(kx, c, mac), bits);
 
843
tls_cipher = cipherbuf;
 
844
 
 
845
DEBUG(D_tls) debug_printf("cipher: %s\n", cipherbuf);
 
846
}
 
847
 
 
848
 
 
849
 
 
850
/*************************************************
 
851
*       Start a TLS session in a server          *
 
852
*************************************************/
 
853
 
 
854
/* This is called when Exim is running as a server, after having received
 
855
the STARTTLS command. It must respond to that command, and then negotiate
 
856
a TLS session.
 
857
 
 
858
Arguments:
 
859
  require_ciphers  list of allowed ciphers or NULL
 
860
  require_mac      list of allowed MACs or NULL
 
861
  require_kx       list of allowed key_exchange methods or NULL
 
862
  require_proto    list of allowed protocols or NULL
 
863
 
 
864
Returns:           OK on success
 
865
                   DEFER for errors before the start of the negotiation
 
866
                   FAIL for errors during the negotation; the server can't
 
867
                     continue running.
 
868
*/
 
869
 
 
870
int
 
871
tls_server_start(uschar *require_ciphers, uschar *require_mac,
 
872
  uschar *require_kx, uschar *require_proto)
 
873
{
 
874
int rc;
 
875
const char *error;
 
876
uschar *expciphers = NULL;
 
877
uschar *expmac = NULL;
 
878
uschar *expkx = NULL;
 
879
uschar *expproto = NULL;
 
880
 
 
881
/* Check for previous activation */
 
882
 
 
883
if (tls_active >= 0)
 
884
  {
 
885
  tls_error("STARTTLS received after TLS started", NULL, "");
 
886
  smtp_printf("554 Already in TLS\r\n");
 
887
  return FAIL;
 
888
  }
 
889
 
 
890
/* Initialize the library. If it fails, it will already have logged the error
 
891
and sent an SMTP response. */
 
892
 
 
893
DEBUG(D_tls) debug_printf("initializing GnuTLS as a server\n");
 
894
 
 
895
rc = tls_init(NULL, tls_certificate, tls_privatekey, tls_verify_certificates,
 
896
  tls_crl);
 
897
if (rc != OK) return rc;
 
898
 
 
899
if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers) ||
 
900
    !expand_check(require_mac, US"gnutls_require_mac", &expmac) ||
 
901
    !expand_check(require_kx, US"gnutls_require_kx", &expkx) ||
 
902
    !expand_check(require_proto, US"gnutls_require_proto", &expproto))
 
903
  return FAIL;
 
904
 
 
905
/* If this is a host for which certificate verification is mandatory or
 
906
optional, set up appropriately. */
 
907
 
 
908
tls_certificate_verified = FALSE;
 
909
verify_requirement = VERIFY_NONE;
 
910
 
 
911
if (verify_check_host(&tls_verify_hosts) == OK)
 
912
  verify_requirement = VERIFY_REQUIRED;
 
913
else if (verify_check_host(&tls_try_verify_hosts) == OK)
 
914
  verify_requirement = VERIFY_OPTIONAL;
 
915
 
 
916
/* Prepare for new connection */
 
917
 
 
918
tls_session = tls_session_init(GNUTLS_SERVER, expciphers, expmac, expkx,
 
919
  expproto);
 
920
if (tls_session == NULL)
 
921
  return tls_error(US"tls_session_init", NULL,
 
922
    gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
 
923
 
 
924
/* Set context and tell client to go ahead, except in the case of TLS startup
 
925
on connection, where outputting anything now upsets the clients and tends to
 
926
make them disconnect. We need to have an explicit fflush() here, to force out
 
927
the response. Other smtp_printf() calls do not need it, because in non-TLS
 
928
mode, the fflush() happens when smtp_getc() is called. */
 
929
 
 
930
if (!tls_on_connect)
 
931
  {
 
932
  smtp_printf("220 TLS go ahead\r\n");
 
933
  fflush(smtp_out);
 
934
  }
 
935
 
 
936
/* Now negotiate the TLS session. We put our own timer on it, since it seems
 
937
that the GnuTLS library doesn't. */
 
938
 
 
939
gnutls_transport_set_ptr2(tls_session, (gnutls_transport_ptr)fileno(smtp_in),
 
940
                                       (gnutls_transport_ptr)fileno(smtp_out));
 
941
 
 
942
sigalrm_seen = FALSE;
 
943
if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
 
944
rc = gnutls_handshake(tls_session);
 
945
alarm(0);
 
946
 
 
947
if (rc < 0)
 
948
  {
 
949
  tls_error(US"gnutls_handshake", NULL,
 
950
    sigalrm_seen ? "timed out" : gnutls_strerror(rc));
 
951
 
 
952
  /* It seems that, except in the case of a timeout, we have to close the
 
953
  connection right here; otherwise if the other end is running OpenSSL it hangs
 
954
  until the server times out. */
 
955
 
 
956
  if (!sigalrm_seen)
 
957
    {
 
958
    (void)fclose(smtp_out);
 
959
    (void)fclose(smtp_in);
 
960
    }
 
961
 
 
962
  return FAIL;
 
963
  }
 
964
 
 
965
DEBUG(D_tls) debug_printf("gnutls_handshake was successful\n");
 
966
 
 
967
if (verify_requirement != VERIFY_NONE &&
 
968
     !verify_certificate(tls_session, &error))
 
969
  {
 
970
  tls_error(US"certificate verification failed", NULL, error);
 
971
  return FAIL;
 
972
  }
 
973
 
 
974
construct_cipher_name(tls_session);
 
975
 
 
976
/* TLS has been set up. Adjust the input functions to read via TLS,
 
977
and initialize appropriately. */
 
978
 
 
979
ssl_xfer_buffer = store_malloc(ssl_xfer_buffer_size);
 
980
ssl_xfer_buffer_lwm = ssl_xfer_buffer_hwm = 0;
 
981
ssl_xfer_eof = ssl_xfer_error = 0;
 
982
 
 
983
receive_getc = tls_getc;
 
984
receive_ungetc = tls_ungetc;
 
985
receive_feof = tls_feof;
 
986
receive_ferror = tls_ferror;
 
987
receive_smtp_buffered = tls_smtp_buffered;
 
988
 
 
989
tls_active = fileno(smtp_out);
 
990
 
 
991
return OK;
 
992
}
 
993
 
 
994
 
 
995
 
 
996
 
 
997
/*************************************************
 
998
*    Start a TLS session in a client             *
 
999
*************************************************/
 
1000
 
 
1001
/* Called from the smtp transport after STARTTLS has been accepted.
 
1002
 
 
1003
Arguments:
 
1004
  fd                the fd of the connection
 
1005
  host              connected host (for messages)
 
1006
  addr              the first address (not used)
 
1007
  dhparam           DH parameter file
 
1008
  certificate       certificate file
 
1009
  privatekey        private key file
 
1010
  verify_certs      file for certificate verify
 
1011
  verify_crl        CRL for verify
 
1012
  require_ciphers   list of allowed ciphers or NULL
 
1013
  require_mac       list of allowed MACs or NULL
 
1014
  require_kx        list of allowed key_exchange methods or NULL
 
1015
  require_proto     list of allowed protocols or NULL
 
1016
  timeout           startup timeout
 
1017
 
 
1018
Returns:            OK/DEFER/FAIL (because using common functions),
 
1019
                    but for a client, DEFER and FAIL have the same meaning
 
1020
*/
 
1021
 
 
1022
int
 
1023
tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
 
1024
  uschar *certificate, uschar *privatekey, uschar *verify_certs,
 
1025
  uschar *verify_crl, uschar *require_ciphers, uschar *require_mac,
 
1026
  uschar *require_kx, uschar *require_proto, int timeout)
 
1027
{
 
1028
const gnutls_datum *server_certs;
 
1029
uschar *expciphers = NULL;
 
1030
uschar *expmac = NULL;
 
1031
uschar *expkx = NULL;
 
1032
uschar *expproto = NULL;
 
1033
const char *error;
 
1034
unsigned int server_certs_size;
 
1035
int rc;
 
1036
 
 
1037
DEBUG(D_tls) debug_printf("initializing GnuTLS as a client\n");
 
1038
 
 
1039
verify_requirement = (verify_certs == NULL)? VERIFY_NONE : VERIFY_REQUIRED;
 
1040
rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
 
1041
if (rc != OK) return rc;
 
1042
 
 
1043
if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers) ||
 
1044
    !expand_check(require_mac, US"gnutls_require_mac", &expmac) ||
 
1045
    !expand_check(require_kx, US"gnutls_require_kx", &expkx) ||
 
1046
    !expand_check(require_proto, US"gnutls_require_proto", &expproto))
 
1047
  return FAIL;
 
1048
 
 
1049
tls_session = tls_session_init(GNUTLS_CLIENT, expciphers, expmac, expkx,
 
1050
  expproto);
 
1051
 
 
1052
if (tls_session == NULL)
 
1053
  return tls_error(US "tls_session_init", host,
 
1054
    gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
 
1055
 
 
1056
gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fd);
 
1057
 
 
1058
/* There doesn't seem to be a built-in timeout on connection. */
 
1059
 
 
1060
sigalrm_seen = FALSE;
 
1061
alarm(timeout);
 
1062
rc = gnutls_handshake(tls_session);
 
1063
alarm(0);
 
1064
 
 
1065
if (rc < 0)
 
1066
  return tls_error(US "gnutls_handshake", host,
 
1067
    sigalrm_seen ? "timed out" : gnutls_strerror(rc));
 
1068
 
 
1069
server_certs = gnutls_certificate_get_peers(tls_session, &server_certs_size);
 
1070
 
 
1071
if (server_certs != NULL)
 
1072
  {
 
1073
  uschar buff[1024];
 
1074
  gnutls_x509_crt gcert;
 
1075
 
 
1076
  gnutls_x509_crt_init(&gcert);
 
1077
  tls_peerdn = US"unknown";
 
1078
 
 
1079
  if (gnutls_x509_crt_import(gcert, server_certs, GNUTLS_X509_FMT_DER) == 0)
 
1080
    {
 
1081
    size_t bufsize = sizeof(buff);
 
1082
    if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
 
1083
      tls_peerdn = string_copy_malloc(buff);
 
1084
    }
 
1085
  }
 
1086
 
 
1087
/* Should we also verify the hostname here? */
 
1088
 
 
1089
if (verify_requirement != VERIFY_NONE &&
 
1090
      !verify_certificate(tls_session, &error))
 
1091
  return tls_error(US"certificate verification failed", host, error);
 
1092
 
 
1093
construct_cipher_name(tls_session);    /* Sets tls_cipher */
 
1094
tls_active = fd;
 
1095
return OK;
 
1096
}
 
1097
 
 
1098
 
 
1099
 
 
1100
/*************************************************
 
1101
*    Deal with logging errors during I/O         *
 
1102
*************************************************/
 
1103
 
 
1104
/* We have to get the identity of the peer from saved data.
 
1105
 
 
1106
Argument:
 
1107
  ec       the GnuTLS error code, or 0 if it's a local error
 
1108
  when     text identifying read or write
 
1109
  text     local error text when ec is 0
 
1110
 
 
1111
Returns:   nothing
 
1112
*/
 
1113
 
 
1114
static void
 
1115
record_io_error(int ec, uschar *when, uschar *text)
 
1116
{
 
1117
const char *msg;
 
1118
 
 
1119
if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED)
 
1120
  msg = string_sprintf("%s: %s", gnutls_strerror(ec),
 
1121
    gnutls_alert_get_name(gnutls_alert_get(tls_session)));
 
1122
else
 
1123
  msg = gnutls_strerror(ec);
 
1124
 
 
1125
tls_error(when, client_host, msg);
 
1126
}
 
1127
 
 
1128
 
 
1129
 
 
1130
/*************************************************
 
1131
*            TLS version of getc                 *
 
1132
*************************************************/
 
1133
 
 
1134
/* This gets the next byte from the TLS input buffer. If the buffer is empty,
 
1135
it refills the buffer via the GnuTLS reading function.
 
1136
 
 
1137
Arguments:  none
 
1138
Returns:    the next character or EOF
 
1139
*/
 
1140
 
 
1141
int
 
1142
tls_getc(void)
 
1143
{
 
1144
if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
 
1145
  {
 
1146
  int inbytes;
 
1147
 
 
1148
  DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
 
1149
    (long) tls_session, (long) ssl_xfer_buffer, ssl_xfer_buffer_size);
 
1150
 
 
1151
  if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
 
1152
  inbytes = gnutls_record_recv(tls_session, CS ssl_xfer_buffer,
 
1153
    ssl_xfer_buffer_size);
 
1154
  alarm(0);
 
1155
 
 
1156
  /* A zero-byte return appears to mean that the TLS session has been
 
1157
     closed down, not that the socket itself has been closed down. Revert to
 
1158
     non-TLS handling. */
 
1159
 
 
1160
  if (inbytes == 0)
 
1161
    {
 
1162
    DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
 
1163
 
 
1164
    receive_getc = smtp_getc;
 
1165
    receive_ungetc = smtp_ungetc;
 
1166
    receive_feof = smtp_feof;
 
1167
    receive_ferror = smtp_ferror;
 
1168
    receive_smtp_buffered = smtp_buffered;
 
1169
 
 
1170
    gnutls_deinit(tls_session);
 
1171
    tls_session = NULL;
 
1172
    tls_active = -1;
 
1173
    tls_cipher = NULL;
 
1174
    tls_peerdn = NULL;
 
1175
 
 
1176
    return smtp_getc();
 
1177
    }
 
1178
 
 
1179
  /* Handle genuine errors */
 
1180
 
 
1181
  else if (inbytes < 0)
 
1182
    {
 
1183
    record_io_error(inbytes, US"recv", NULL);
 
1184
    ssl_xfer_error = 1;
 
1185
    return EOF;
 
1186
    }
 
1187
#ifndef DISABLE_DKIM
 
1188
  dkim_exim_verify_feed(ssl_xfer_buffer, inbytes);
 
1189
#endif
 
1190
  ssl_xfer_buffer_hwm = inbytes;
 
1191
  ssl_xfer_buffer_lwm = 0;
 
1192
  }
 
1193
 
 
1194
 
 
1195
/* Something in the buffer; return next uschar */
 
1196
 
 
1197
return ssl_xfer_buffer[ssl_xfer_buffer_lwm++];
 
1198
}
 
1199
 
 
1200
 
 
1201
 
 
1202
/*************************************************
 
1203
*          Read bytes from TLS channel           *
 
1204
*************************************************/
 
1205
 
 
1206
/*
 
1207
Arguments:
 
1208
  buff      buffer of data
 
1209
  len       size of buffer
 
1210
 
 
1211
Returns:    the number of bytes read
 
1212
            -1 after a failed read
 
1213
*/
 
1214
 
 
1215
int
 
1216
tls_read(uschar *buff, size_t len)
 
1217
{
 
1218
int inbytes;
 
1219
 
 
1220
DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
 
1221
  (long) tls_session, (long) buff, len);
 
1222
 
 
1223
inbytes = gnutls_record_recv(tls_session, CS buff, len);
 
1224
if (inbytes > 0) return inbytes;
 
1225
if (inbytes == 0)
 
1226
  {
 
1227
  DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
 
1228
  }
 
1229
else record_io_error(inbytes, US"recv", NULL);
 
1230
 
 
1231
return -1;
 
1232
}
 
1233
 
 
1234
 
 
1235
 
 
1236
/*************************************************
 
1237
*         Write bytes down TLS channel           *
 
1238
*************************************************/
 
1239
 
 
1240
/*
 
1241
Arguments:
 
1242
  buff      buffer of data
 
1243
  len       number of bytes
 
1244
 
 
1245
Returns:    the number of bytes after a successful write,
 
1246
            -1 after a failed write
 
1247
*/
 
1248
 
 
1249
int
 
1250
tls_write(const uschar *buff, size_t len)
 
1251
{
 
1252
int outbytes;
 
1253
int left = len;
 
1254
 
 
1255
DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long) buff, left);
 
1256
while (left > 0)
 
1257
  {
 
1258
  DEBUG(D_tls) debug_printf("gnutls_record_send(SSL, %lx, %d)\n", (long)buff,
 
1259
    left);
 
1260
  outbytes = gnutls_record_send(tls_session, CS buff, left);
 
1261
 
 
1262
  DEBUG(D_tls) debug_printf("outbytes=%d\n", outbytes);
 
1263
  if (outbytes < 0)
 
1264
    {
 
1265
    record_io_error(outbytes, US"send", NULL);
 
1266
    return -1;
 
1267
    }
 
1268
  if (outbytes == 0)
 
1269
    {
 
1270
    record_io_error(0, US"send", US"TLS channel closed on write");
 
1271
    return -1;
 
1272
    }
 
1273
 
 
1274
  left -= outbytes;
 
1275
  buff += outbytes;
 
1276
  }
 
1277
 
 
1278
return len;
 
1279
}
 
1280
 
 
1281
 
 
1282
 
 
1283
/*************************************************
 
1284
*         Close down a TLS session               *
 
1285
*************************************************/
 
1286
 
 
1287
/* This is also called from within a delivery subprocess forked from the
 
1288
daemon, to shut down the TLS library, without actually doing a shutdown (which
 
1289
would tamper with the TLS session in the parent process).
 
1290
 
 
1291
Arguments:   TRUE if gnutls_bye is to be called
 
1292
Returns:     nothing
 
1293
*/
 
1294
 
 
1295
void
 
1296
tls_close(BOOL shutdown)
 
1297
{
 
1298
if (tls_active < 0) return;  /* TLS was not active */
 
1299
 
 
1300
if (shutdown)
 
1301
  {
 
1302
  DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS\n");
 
1303
  gnutls_bye(tls_session, GNUTLS_SHUT_WR);
 
1304
  }
 
1305
 
 
1306
gnutls_deinit(tls_session);
 
1307
tls_session = NULL;
 
1308
gnutls_global_deinit();
 
1309
 
 
1310
tls_active = -1;
 
1311
}
 
1312
 
 
1313
 
 
1314
 
 
1315
 
 
1316
/*************************************************
 
1317
*         Report the library versions.           *
 
1318
*************************************************/
 
1319
 
 
1320
/* See a description in tls-openssl.c for an explanation of why this exists.
 
1321
 
 
1322
Arguments:   a FILE* to print the results to
 
1323
Returns:     nothing
 
1324
*/
 
1325
 
 
1326
void
 
1327
tls_version_report(FILE *f)
 
1328
{
 
1329
fprintf(f, "GnuTLS compile-time version: %s\n", LIBGNUTLS_VERSION);
 
1330
fprintf(f, "GnuTLS runtime version: %s\n", gnutls_check_version(NULL));
 
1331
}
 
1332
 
 
1333
/* End of tls-gnu.c */