825313a9a25de7f25792fab31deb8ecabda96941
[exim.git] / src / src / tls.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10 /* This module provides TLS (aka SSL) support for Exim. The code for OpenSSL is
11 based on a patch that was originally contributed by Steve Haslam. It was
12 adapted from stunnel, a GPL program by Michal Trojnara. The code for GNU TLS is
13 based on a patch contributed by Nikos Mavrogiannopoulos. Because these packages
14 are so very different, the functions for each are kept in separate files. The
15 relevant file is #included as required, after any any common functions.
16
17 No cryptographic code is included in Exim. All this module does is to call
18 functions from the OpenSSL or GNU TLS libraries. */
19
20
21 #include "exim.h"
22 #include "transports/smtp.h"
23
24 #if !defined(DISABLE_TLS) && !defined(USE_OPENSSL) && !defined(USE_GNUTLS)
25 # error One of USE_OPENSSL or USE_GNUTLS must be defined for a TLS build
26 #endif
27
28
29 #if defined(MACRO_PREDEF) && !defined(DISABLE_TLS)
30 # include "macro_predef.h"
31 # ifdef USE_GNUTLS
32 #  include "tls-gnu.c"
33 # else
34 #  include "tls-openssl.c"
35 # endif
36 #endif
37
38 #ifndef MACRO_PREDEF
39
40 static void tls_per_lib_daemon_init(void);
41 static void tls_per_lib_daemon_tick(void);
42 static unsigned  tls_server_creds_init(void);
43 static void tls_server_creds_invalidate(void);
44 static void tls_client_creds_init(transport_instance *, BOOL);
45 static void tls_client_creds_invalidate(transport_instance *);
46 static void tls_daemon_creds_reload(void);
47 static BOOL opt_set_and_noexpand(const uschar *);
48 static BOOL opt_unset_or_noexpand(const uschar *);
49
50
51
52 /* This module is compiled only when it is specifically requested in the
53 build-time configuration. However, some compilers don't like compiling empty
54 modules, so keep them happy with a dummy when skipping the rest. Make it
55 reference itself to stop picky compilers complaining that it is unused, and put
56 in a dummy argument to stop even pickier compilers complaining about infinite
57 loops. */
58
59 #ifdef DISABLE_TLS
60 static void dummy(int x) { dummy(x-1); }
61 #else   /* most of the rest of the file */
62
63 const exim_tlslib_state null_tls_preload = {0};
64
65 /* Static variables that are used for buffering data by both sets of
66 functions and the common functions below.
67
68 We're moving away from this; GnuTLS is already using a state, which
69 can switch, so we can do TLS callouts during ACLs. */
70
71 static const int ssl_xfer_buffer_size = 4096;
72 #ifdef USE_OPENSSL
73 static uschar *ssl_xfer_buffer = NULL;
74 static int ssl_xfer_buffer_lwm = 0;
75 static int ssl_xfer_buffer_hwm = 0;
76 static int ssl_xfer_eof = FALSE;
77 static BOOL ssl_xfer_error = FALSE;
78 #endif
79
80 #ifdef EXIM_HAVE_KEVENT
81 # define KEV_SIZE 16    /* Eight file,dir pairs */
82 static struct kevent kev[KEV_SIZE];
83 static int kev_used = 0;
84 #endif
85
86 static unsigned tls_creds_expire = 0;
87
88 /*************************************************
89 *       Expand string; give error on failure     *
90 *************************************************/
91
92 /* If expansion is forced to fail, set the result NULL and return TRUE.
93 Other failures return FALSE. For a server, an SMTP response is given.
94
95 Arguments:
96   s         the string to expand; if NULL just return TRUE
97   name      name of string being expanded (for error)
98   result    where to put the result
99
100 Returns:    TRUE if OK; result may still be NULL after forced failure
101 */
102
103 static BOOL
104 expand_check(const uschar * s, const uschar * name,
105   uschar ** result, uschar ** errstr)
106 {
107 if (!s)
108   *result = NULL;
109 else if (  !(*result = expand_string(US s)) /* need to clean up const more */
110         && !f.expand_string_forcedfail
111         )
112   {
113   *errstr = US"Internal error";
114   log_write(0, LOG_MAIN|LOG_PANIC, "expansion of %s failed: %s", name,
115     expand_string_message);
116   return FALSE;
117   }
118 return TRUE;
119 }
120
121
122 #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
123 /* Add the directory for a filename to the inotify handle, creating that if
124 needed.  This is enough to see changes to files in that dir.
125 Return boolean success.
126
127 The word "system" fails, which is on the safe side as we don't know what
128 directory it implies nor if the TLS library handles a watch for us.
129
130 The string "system,cache" is recognised and explicitly accepted without
131 setting a watch.  This permits the system CA bundle to be cached even though
132 we have no way to tell when it gets modified by an update.
133 The call chain for OpenSSL uses a (undocumented) call into the library
134 to discover the actual file.  We don't know what GnuTLS uses.
135
136 A full set of caching including the CAs takes 35ms output off of the
137 server tls_init() (GnuTLS, Fedora 32, 2018-class x86_64 laptop hardware).
138 */
139 static BOOL
140 tls_set_one_watch(const uschar * filename)
141 # ifdef EXIM_HAVE_INOTIFY
142 {
143 uschar buf[PATH_MAX];
144 ssize_t len;
145 uschar * s;
146
147 if (Ustrcmp(filename, "system,cache") == 0) return TRUE;
148 if (!(s = Ustrrchr(filename, '/'))) return FALSE;
149
150 for (unsigned loop = 20;
151      (len = readlink(CCS filename, CS buf, sizeof(buf))) >= 0; )
152   {                                             /* a symlink */
153   if (--loop == 0) { errno = ELOOP; return FALSE; }
154   filename = buf[0] == '/'
155     ? string_copyn(buf, (unsigned)len)  /* mem released by tls_set_watch */
156     : string_sprintf("%.*s/%.*s", (int)(s - filename), filename, (int)len, buf);
157   s = Ustrrchr(filename, '/');
158   }
159 if (errno != EINVAL)
160   return FALSE;                                 /* other error */
161
162 /* not a symlink */
163 s = string_copyn(filename, s - filename);       /* mem released by tls_set_watch */
164
165 DEBUG(D_tls) debug_printf("watch dir '%s'\n", s);
166
167 if (inotify_add_watch(tls_watch_fd, CCS s,
168       IN_ONESHOT | IN_CLOSE_WRITE | IN_DELETE | IN_DELETE_SELF
169       | IN_MOVED_FROM | IN_MOVED_TO | IN_MOVE_SELF) >= 0)
170   return TRUE;
171 DEBUG(D_tls) debug_printf("notify_add_watch: %s\n", strerror(errno));
172 return FALSE;
173 }
174 # endif
175 # ifdef EXIM_HAVE_KEVENT
176 {
177 uschar * s, * t;
178 int fd1, fd2, i, j, cnt = 0;
179 struct stat sb;
180 #ifdef OpenBSD
181 struct kevent k_dummy;
182 struct timespec ts = {0};
183 #endif
184
185 errno = 0;
186 if (Ustrcmp(filename, "system,cache") == 0) return TRUE;
187
188 for (;;)
189   {
190   if (kev_used > KEV_SIZE-2) { s = US"out of kev space"; goto bad; }
191   if (!(s = Ustrrchr(filename, '/'))) return FALSE;
192   s = string_copyn(filename, s - filename);     /* mem released by tls_set_watch */
193
194   /* The dir open will fail if there is a symlink on the path. Fine; it's too
195   much effort to handle all possible cases; just refuse the preload. */
196
197   if ((fd2 = open(CCS s, O_RDONLY | O_NOFOLLOW)) < 0) { s = US"open dir"; goto bad; }
198
199   if ((lstat(CCS filename, &sb)) < 0) { s = US"lstat"; goto bad; }
200   if (!S_ISLNK(sb.st_mode))
201     {
202     if ((fd1 = open(CCS filename, O_RDONLY | O_NOFOLLOW)) < 0)
203       { s = US"open file"; goto bad; }
204     DEBUG(D_tls) debug_printf("watch file '%s':\t%d\n", filename, fd1);
205     EV_SET(&kev[kev_used++],
206         (uintptr_t)fd1,
207         EVFILT_VNODE,
208         EV_ADD | EV_ENABLE | EV_ONESHOT,
209         NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
210         | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
211         0,
212         NULL);
213     cnt++;
214     }
215   DEBUG(D_tls) debug_printf("watch dir  '%s':\t%d\n", s, fd2);
216   EV_SET(&kev[kev_used++],
217         (uintptr_t)fd2,
218         EVFILT_VNODE,
219         EV_ADD | EV_ENABLE | EV_ONESHOT,
220         NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
221         | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
222         0,
223         NULL);
224   cnt++;
225
226   if (!(S_ISLNK(sb.st_mode))) break;
227
228   t = store_get(1024, GET_UNTAINTED);
229   Ustrncpy(t, s, 1022);
230   j = Ustrlen(s);
231   t[j++] = '/';
232   if ((i = readlink(CCS filename, (void *)(t+j), 1023-j)) < 0) { s = US"readlink"; goto bad; }
233   filename = t;
234   *(t += i+j) = '\0';
235   store_release_above(t+1);
236   }
237
238 #ifdef OpenBSD
239 if (kevent(tls_watch_fd, &kev[kev_used-cnt], cnt, &k_dummy, 1, &ts) >= 0)
240   return TRUE;
241 #else
242 if (kevent(tls_watch_fd, &kev[kev_used-cnt], cnt, NULL, 0, NULL) >= 0)
243   return TRUE;
244 #endif
245 s = US"kevent";
246
247 bad:
248 DEBUG(D_tls)
249   if (errno)
250     debug_printf("%s: %s: %s\n", __FUNCTION__, s, strerror(errno));
251   else
252     debug_printf("%s: %s\n", __FUNCTION__, s);
253 return FALSE;
254 }
255 # endif /*EXIM_HAVE_KEVENT*/
256
257
258 /* Create an inotify facility if needed.
259 Then set watches on the dir containing the given file or (optionally)
260 list of files.  Return boolean success. */
261
262 static BOOL
263 tls_set_watch(const uschar * filename, BOOL list)
264 {
265 rmark r;
266 BOOL rc = FALSE;
267
268 if (!filename || !*filename) return TRUE;
269 if (Ustrncmp(filename, "system", 6) == 0) return TRUE;
270
271 DEBUG(D_tls) debug_printf("tls_set_watch: '%s'\n", filename);
272
273 if (  tls_watch_fd < 0
274 # ifdef EXIM_HAVE_INOTIFY
275    && (tls_watch_fd = inotify_init1(O_CLOEXEC)) < 0
276 # endif
277 # ifdef EXIM_HAVE_KEVENT
278    && (tls_watch_fd = kqueue()) < 0
279 # endif
280    )
281     {
282     DEBUG(D_tls) debug_printf("inotify_init: %s\n", strerror(errno));
283     return FALSE;
284     }
285
286 r = store_mark();
287
288 if (list)
289   {
290   int sep = 0;
291   for (uschar * s; s = string_nextinlist(&filename, &sep, NULL, 0); )
292     if (!(rc = tls_set_one_watch(s))) break;
293   }
294 else
295   rc = tls_set_one_watch(filename);
296
297 store_reset(r);
298 if (!rc) DEBUG(D_tls) debug_printf("tls_set_watch() fail on '%s': %s\n", filename, strerror(errno));
299 return rc;
300 }
301
302
303 void
304 tls_watch_discard_event(int fd)
305 {
306 #ifdef EXIM_HAVE_INOTIFY
307 (void) read(fd, big_buffer, big_buffer_size);
308 #endif
309 #ifdef EXIM_HAVE_KEVENT
310 struct kevent kev;
311 struct timespec t = {0};
312 (void) kevent(fd, NULL, 0, &kev, 1, &t);
313 #endif
314 }
315 #endif  /*EXIM_HAVE_INOTIFY*/
316
317
318 void
319 tls_client_creds_reload(BOOL watch)
320 {
321 for(transport_instance * t = transports; t; t = t->next)
322   if (Ustrcmp(t->driver_name, "smtp") == 0)
323     {
324     tls_client_creds_invalidate(t);
325     tls_client_creds_init(t, watch);
326     }
327 }
328
329
330 void
331 tls_watch_invalidate(void)
332 {
333 if (tls_watch_fd < 0) return;
334
335 #ifdef EXIM_HAVE_KEVENT
336 /* Close the files we had open for kevent */
337 for (int i = 0; i < kev_used; i++)
338   {
339   DEBUG(D_tls) debug_printf("closing watch fd: %d\n", (int) kev[i].ident);
340   (void) close((int) kev[i].ident);
341   kev[i].ident = (uintptr_t)-1;
342   }
343 kev_used = 0;
344 #endif
345
346 close(tls_watch_fd);
347 tls_watch_fd = -1;
348 }
349
350
351 static void
352 tls_daemon_creds_reload(void)
353 {
354 unsigned lifetime;
355
356 #ifdef EXIM_HAVE_KEVENT
357 tls_watch_invalidate();
358 #endif
359
360 tls_server_creds_invalidate();
361
362 /* _expire is for a time-limited selfsign server cert */
363 tls_creds_expire = (lifetime = tls_server_creds_init())
364   ? time(NULL) + lifetime : 0;
365
366 tls_client_creds_reload(TRUE);
367 }
368
369
370 /* Utility predicates for use by the per-library code */
371 static BOOL
372 opt_set_and_noexpand(const uschar * opt)
373 { return opt && *opt && Ustrchr(opt, '$') == NULL; }
374
375 static BOOL
376 opt_unset_or_noexpand(const uschar * opt)
377 { return !opt || Ustrchr(opt, '$') == NULL; }
378
379
380
381 /* Called every time round the daemon loop.
382
383 If we reloaded fd-watcher, return the old watch fd
384 having modified the global for the new one. Otherwise
385 return -1.
386 */
387
388 int
389 tls_daemon_tick(void)
390 {
391 int old_watch_fd = tls_watch_fd;
392
393 tls_per_lib_daemon_tick();
394 #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
395 if (tls_creds_expire && time(NULL) >= tls_creds_expire)
396   {
397   /* The server cert is a selfsign, with limited lifetime.  Dump it and
398   generate a new one.  Reload the rest of the creds also as the machinery
399   is all there. */
400
401   DEBUG(D_tls) debug_printf("selfsign cert rotate\n");
402   tls_creds_expire = 0;
403   tls_daemon_creds_reload();
404   return old_watch_fd;
405   }
406 else if (tls_watch_trigger_time && time(NULL) >= tls_watch_trigger_time + 5)
407   {
408   /* Called, after a delay for multiple file ops to get done, from
409   the daemon when any of the watches added (above) fire.
410   Dump the set of watches and arrange to reload cached creds (which
411   will set up new watches). */
412
413   DEBUG(D_tls) debug_printf("watch triggered\n");
414   tls_watch_trigger_time = tls_creds_expire = 0;
415   tls_daemon_creds_reload();
416   return old_watch_fd;
417   }
418 #endif
419 return -1;
420 }
421
422 /* Called once at daemon startup */
423
424 void
425 tls_daemon_init(void)
426 {
427 tls_per_lib_daemon_init();
428 }
429
430
431 /*************************************************
432 *        Timezone environment flipping           *
433 *************************************************/
434
435 static uschar *
436 to_tz(uschar * tz)
437 {
438 uschar * old = US getenv("TZ");
439 (void) setenv("TZ", CCS tz, 1);
440 tzset();
441 return old;
442 }
443
444 static void
445 restore_tz(uschar * tz)
446 {
447 if (tz)
448   (void) setenv("TZ", CCS tz, 1);
449 else
450   (void) os_unsetenv(US"TZ");
451 tzset();
452 }
453
454 /*************************************************
455 *        Many functions are package-specific     *
456 *************************************************/
457 /* Forward decl. */
458 static void tls_client_resmption_key(tls_support *, smtp_connect_args *,
459   smtp_transport_options_block *);
460
461
462 #ifdef USE_GNUTLS
463 # include "tls-gnu.c"
464 # include "tlscert-gnu.c"
465 # define ssl_xfer_buffer (state_server.xfer_buffer)
466 # define ssl_xfer_buffer_lwm (state_server.xfer_buffer_lwm)
467 # define ssl_xfer_buffer_hwm (state_server.xfer_buffer_hwm)
468 # define ssl_xfer_eof (state_server.xfer_eof)
469 # define ssl_xfer_error (state_server.xfer_error)
470 #endif
471
472 #ifdef USE_OPENSSL
473 # include "tls-openssl.c"
474 # include "tlscert-openssl.c"
475 #endif
476
477
478
479 /*************************************************
480 *           TLS version of ungetc                *
481 *************************************************/
482
483 /* Puts a character back in the input buffer. Only ever
484 called once.
485 Only used by the server-side TLS.
486
487 Arguments:
488   ch           the character
489
490 Returns:       the character
491 */
492
493 int
494 tls_ungetc(int ch)
495 {
496 if (ssl_xfer_buffer_lwm <= 0)
497   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "buffer underflow in tls_ungetc");
498
499 ssl_xfer_buffer[--ssl_xfer_buffer_lwm] = ch;
500 return ch;
501 }
502
503
504
505 /*************************************************
506 *           TLS version of feof                  *
507 *************************************************/
508
509 /* Tests for a previous EOF
510 Only used by the server-side TLS.
511
512 Arguments:     none
513 Returns:       non-zero if the eof flag is set
514 */
515
516 int
517 tls_feof(void)
518 {
519 return (int)ssl_xfer_eof;
520 }
521
522
523
524 /*************************************************
525 *              TLS version of ferror             *
526 *************************************************/
527
528 /* Tests for a previous read error, and returns with errno
529 restored to what it was when the error was detected.
530 Only used by the server-side TLS.
531
532 >>>>> Hmm. Errno not handled yet. Where do we get it from?  >>>>>
533
534 Arguments:     none
535 Returns:       non-zero if the error flag is set
536 */
537
538 int
539 tls_ferror(void)
540 {
541 return (int)ssl_xfer_error;
542 }
543
544
545 /*************************************************
546 *           TLS version of smtp_buffered         *
547 *************************************************/
548
549 /* Tests for unused chars in the TLS input buffer.
550 Only used by the server-side TLS.
551
552 Arguments:     none
553 Returns:       TRUE/FALSE
554 */
555
556 BOOL
557 tls_smtp_buffered(void)
558 {
559 return ssl_xfer_buffer_lwm < ssl_xfer_buffer_hwm;
560 }
561
562
563 #endif  /*DISABLE_TLS*/
564
565 void
566 tls_modify_variables(tls_support * dest_tsp)
567 {
568 modify_variable(US"tls_bits",                 &dest_tsp->bits);
569 modify_variable(US"tls_certificate_verified", &dest_tsp->certificate_verified);
570 modify_variable(US"tls_cipher",               &dest_tsp->cipher);
571 modify_variable(US"tls_peerdn",               &dest_tsp->peerdn);
572 #ifdef USE_OPENSSL
573 modify_variable(US"tls_sni",                  &dest_tsp->sni);
574 #endif
575 }
576
577
578 #ifndef DISABLE_TLS
579 /************************************************
580 *       TLS certificate name operations         *
581 ************************************************/
582
583 /* Convert an rfc4514 DN to an exim comma-sep list.
584 Backslashed commas need to be replaced by doublecomma
585 for Exim's list quoting.  We modify the given string
586 inplace.
587 */
588
589 static void
590 dn_to_list(uschar * dn)
591 {
592 for (uschar * cp = dn; *cp; cp++)
593   if (cp[0] == '\\' && cp[1] == ',')
594     *cp++ = ',';
595 }
596
597
598 /* Extract fields of a given type from an RFC4514-
599 format Distinguished Name.  Return an Exim list.
600 NOTE: We modify the supplied dn string during operation.
601
602 Arguments:
603         dn      Distinguished Name string
604         mod     list containing optional output list-sep and
605                 field selector match, comma-separated
606 Return:
607         allocated string with list of matching fields,
608         field type stripped
609 */
610
611 uschar *
612 tls_field_from_dn(uschar * dn, const uschar * mod)
613 {
614 int insep = ',';
615 uschar outsep = '\n';
616 uschar * ele;
617 uschar * match = NULL;
618 int len;
619 gstring * list = NULL;
620
621 while ((ele = string_nextinlist(&mod, &insep, NULL, 0)))
622   if (ele[0] != '>')
623     match = ele;        /* field tag to match */
624   else if (ele[1])
625     outsep = ele[1];    /* nondefault output separator */
626
627 dn_to_list(dn);
628 insep = ',';
629 len = match ? Ustrlen(match) : -1;
630 while ((ele = string_nextinlist(CUSS &dn, &insep, NULL, 0)))
631   if (  !match
632      || Ustrncmp(ele, match, len) == 0 && ele[len] == '='
633      )
634     list = string_append_listele(list, outsep, ele+len+1);
635 return string_from_gstring(list);
636 }
637
638
639 /* Compare a domain name with a possibly-wildcarded name. Wildcards
640 are restricted to a single one, as the first element of patterns
641 having at least three dot-separated elements.  Case-independent.
642 Return TRUE for a match
643 */
644 static BOOL
645 is_name_match(const uschar * name, const uschar * pat)
646 {
647 uschar * cp;
648 return *pat == '*'              /* possible wildcard match */
649   ?    *++pat == '.'            /* starts star, dot              */
650     && !Ustrchr(++pat, '*')     /* has no more stars             */
651     && Ustrchr(pat, '.')        /* and has another dot.          */
652     && (cp = Ustrchr(name, '.'))/* The name has at least one dot */
653     && strcmpic(++cp, pat) == 0 /* and we only compare after it. */
654   :    !Ustrchr(pat+1, '*')
655     && strcmpic(name, pat) == 0;
656 }
657
658 /* Compare a list of names with the dnsname elements
659 of the Subject Alternate Name, if any, and the
660 Subject otherwise.
661
662 Arguments:
663         namelist names to compare
664         cert     certificate
665
666 Returns:
667         TRUE/FALSE
668 */
669
670 BOOL
671 tls_is_name_for_cert(const uschar * namelist, void * cert)
672 {
673 uschar * altnames = tls_cert_subject_altname(cert, US"dns");
674 uschar * subjdn;
675 uschar * certname;
676 int cmp_sep = 0;
677 uschar * cmpname;
678
679 if ((altnames = tls_cert_subject_altname(cert, US"dns")))
680   {
681   int alt_sep = '\n';
682   while ((cmpname = string_nextinlist(&namelist, &cmp_sep, NULL, 0)))
683     {
684     const uschar * an = altnames;
685     while ((certname = string_nextinlist(&an, &alt_sep, NULL, 0)))
686       if (is_name_match(cmpname, certname))
687         return TRUE;
688     }
689   }
690
691 else if ((subjdn = tls_cert_subject(cert, NULL)))
692   {
693   int sn_sep = ',';
694
695   dn_to_list(subjdn);
696   while ((cmpname = string_nextinlist(&namelist, &cmp_sep, NULL, 0)))
697     {
698     const uschar * sn = subjdn;
699     while ((certname = string_nextinlist(&sn, &sn_sep, NULL, 0)))
700       if (  *certname++ == 'C'
701          && *certname++ == 'N'
702          && *certname++ == '='
703          && is_name_match(cmpname, certname)
704          )
705         return TRUE;
706     }
707   }
708 return FALSE;
709 }
710
711 /* Environment cleanup: The GnuTLS library uses SSLKEYLOGFILE in the environment
712 and writes a file by that name.  Our OpenSSL code does the same, using keying
713 info from the library API.
714 The GnuTLS support only works if exim is run by root, not taking advantage of
715 the setuid bit.
716 You can use either the external environment (modulo the keep_environment config)
717 or the add_environment config option for SSLKEYLOGFILE; the latter takes
718 precedence.
719
720 If the path is absolute, require it starts with the spooldir; otherwise delete
721 the env variable.  If relative, prefix the spooldir.
722 */
723 void
724 tls_clean_env(void)
725 {
726 uschar * path = US getenv("SSLKEYLOGFILE");
727 if (path)
728   if (!*path)
729     unsetenv("SSLKEYLOGFILE");
730   else if (*path != '/')
731     {
732     DEBUG(D_tls)
733       debug_printf("prepending spooldir to  env SSLKEYLOGFILE\n");
734     setenv("SSLKEYLOGFILE", CCS string_sprintf("%s/%s", spool_directory, path), 1);
735     }
736   else if (Ustrncmp(path, spool_directory, Ustrlen(spool_directory)) != 0)
737     {
738     DEBUG(D_tls)
739       debug_printf("removing env SSLKEYLOGFILE=%s: not under spooldir\n", path);
740     unsetenv("SSLKEYLOGFILE");
741     }
742 }
743
744 /*************************************************
745 *       Drop privs for checking TLS config      *
746 *************************************************/
747
748 /* We want to validate TLS options during readconf, but do not want to be
749 root when we call into the TLS library, in case of library linkage errors
750 which cause segfaults; before this check, those were always done as the Exim
751 runtime user and it makes sense to continue with that.
752
753 Assumes:  tls_require_ciphers has been set, if it will be
754           exim_user has been set, if it will be
755           exim_group has been set, if it will be
756
757 Returns:  bool for "okay"; false will cause caller to immediately exit.
758 */
759
760 BOOL
761 tls_dropprivs_validate_require_cipher(BOOL nowarn)
762 {
763 const uschar *errmsg;
764 pid_t pid;
765 int rc, status;
766 void (*oldsignal)(int);
767
768 /* If TLS will never be used, no point checking ciphers */
769
770 if (  !tls_advertise_hosts
771    || !*tls_advertise_hosts
772    || Ustrcmp(tls_advertise_hosts, ":") == 0
773    )
774   return TRUE;
775 else if (!nowarn && !tls_certificate)
776   log_write(0, LOG_MAIN,
777     "Warning: No server certificate defined; will use a selfsigned one.\n"
778     " Suggested action: either install a certificate or change tls_advertise_hosts option");
779
780 oldsignal = signal(SIGCHLD, SIG_DFL);
781
782 fflush(NULL);
783 if ((pid = exim_fork(US"cipher-validate")) < 0)
784   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
785
786 if (pid == 0)
787   {
788   /* in some modes, will have dropped privilege already */
789   if (!geteuid())
790     exim_setugid(exim_uid, exim_gid, FALSE,
791         US"calling tls_validate_require_cipher");
792
793   if ((errmsg = tls_validate_require_cipher()))
794     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
795         "tls_require_ciphers invalid: %s", errmsg);
796   fflush(NULL);
797   exim_underbar_exit(EXIT_SUCCESS);
798   }
799
800 do {
801   rc = waitpid(pid, &status, 0);
802 } while (rc < 0 && errno == EINTR);
803
804 DEBUG(D_tls)
805   debug_printf("tls_validate_require_cipher child %d ended: status=0x%x\n",
806       (int)pid, status);
807
808 signal(SIGCHLD, oldsignal);
809
810 return status == 0;
811 }
812
813
814
815
816 static void
817 tls_client_resmption_key(tls_support * tlsp, smtp_connect_args * conn_args,
818   smtp_transport_options_block * ob)
819 {
820 #ifndef DISABLE_TLS_RESUME
821 hctx * h = &tlsp->resume_hctx;
822 blob b;
823 gstring * g;
824
825 DEBUG(D_tls) if (conn_args->host_lbserver)
826   debug_printf("TLS: lbserver '%s'\n", conn_args->host_lbserver);
827
828 # ifdef EXIM_HAVE_SHA2
829 exim_sha_init(h, HASH_SHA2_256);
830 # else
831 exim_sha_init(h, HASH_SHA1);
832 # endif
833 exim_sha_update_string(h, conn_args->host_lbserver);
834 # ifdef SUPPORT_DANE
835 if (conn_args->dane)
836   exim_sha_update(h,  CUS &conn_args->tlsa_dnsa, sizeof(dns_answer));
837 # endif
838 exim_sha_update_string(h, conn_args->host->address);
839 exim_sha_update(h,   CUS &conn_args->host->port, sizeof(conn_args->host->port));
840 exim_sha_update_string(h, conn_args->sending_ip_address);
841 exim_sha_update_string(h, openssl_options);
842 exim_sha_update_string(h, ob->tls_require_ciphers);
843 exim_sha_update_string(h, tlsp->sni);
844 # ifdef EXIM_HAVE_ALPN
845 exim_sha_update_string(h, ob->tls_alpn);
846 # endif
847 exim_sha_finish(h, &b);
848 for (g = string_get(b.len*2+1); b.len-- > 0; )
849   g = string_fmt_append(g, "%02x", *b.data++);
850 tlsp->resume_index = string_from_gstring(g);
851 DEBUG(D_tls) debug_printf("TLS: resume session index %s\n", tlsp->resume_index);
852 #endif
853 }
854
855
856
857 /* Start TLS as a client for an ajunct connection, eg. readsocket
858 Return boolean success.
859 */
860
861 BOOL
862 tls_client_adjunct_start(host_item * host, client_conn_ctx * cctx,
863   const uschar * sni, uschar ** errmsg)
864 {
865 union sockaddr_46 interface_sock;
866 EXIM_SOCKLEN_T size = sizeof(interface_sock);
867 smtp_connect_args conn_args = {.host = host };
868 tls_support tls_dummy = { .sni = NULL };
869 uschar * errstr;
870
871 if (getsockname(cctx->sock, (struct sockaddr *) &interface_sock, &size) == 0)
872   conn_args.sending_ip_address = host_ntoa(-1, &interface_sock, NULL, NULL);
873 else
874   {
875   *errmsg = string_sprintf("getsockname failed: %s", strerror(errno));
876   return FALSE;
877   }
878
879 /* To handle SNI we need to emulate more of a real transport because the
880 base tls code assumes that is where the SNI string lives. */
881
882 if (*sni)
883   {
884   transport_instance * tb;
885   smtp_transport_options_block * ob;
886
887   conn_args.tblock = tb = store_get(sizeof(*tb), GET_UNTAINTED);
888   memset(tb, 0, sizeof(*tb));
889
890   tb->options_block = ob = store_get(sizeof(*ob), GET_UNTAINTED);
891   memcpy(ob, &smtp_transport_option_defaults, sizeof(*ob));
892
893   ob->tls_sni = sni;
894   }
895
896 if (!tls_client_start(cctx, &conn_args, NULL, &tls_dummy, &errstr))
897   {
898   *errmsg = string_sprintf("TLS connect failed: %s", errstr);
899   return FALSE;
900   }
901 return TRUE;
902 }
903
904
905
906 #endif  /*!DISABLE_TLS*/
907 #endif  /*!MACRO_PREDEF*/
908
909 /* vi: aw ai sw=2
910 */
911 /* End of tls.c */