1 /* $NetBSD: tlsmgr.c,v 1.4 2022/10/08 16:12:50 christos Exp $ */
2
3 /*++
4 /* NAME
5 /* tlsmgr 8
6 /* SUMMARY
7 /* Postfix TLS session cache and PRNG manager
8 /* SYNOPSIS
9 /* \fBtlsmgr\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /* The \fBtlsmgr\fR(8) manages the Postfix TLS session caches.
12 /* It stores and retrieves cache entries on request by
13 /* \fBsmtpd\fR(8) and \fBsmtp\fR(8) processes, and periodically
14 /* removes entries that have expired.
15 /*
16 /* The \fBtlsmgr\fR(8) also manages the PRNG (pseudo random number
17 /* generator) pool. It answers queries by the \fBsmtpd\fR(8)
18 /* and \fBsmtp\fR(8)
19 /* processes to seed their internal PRNG pools.
20 /*
21 /* The \fBtlsmgr\fR(8)'s PRNG pool is initially seeded from
22 /* an external source (EGD, /dev/urandom, or regular file).
23 /* It is updated at configurable pseudo-random intervals with
24 /* data from the external source. It is updated periodically
25 /* with data from TLS session cache entries and with the time
26 /* of day, and is updated with the time of day whenever a
27 /* process requests \fBtlsmgr\fR(8) service.
28 /*
29 /* The \fBtlsmgr\fR(8) saves the PRNG state to an exchange file
30 /* periodically and when the process terminates, and reads
31 /* the exchange file when initializing its PRNG.
32 /* SECURITY
33 /* .ad
34 /* .fi
35 /* The \fBtlsmgr\fR(8) is not security-sensitive. The code that maintains
36 /* the external and internal PRNG pools does not "trust" the
37 /* data that it manipulates, and the code that maintains the
38 /* TLS session cache does not touch the contents of the cached
39 /* entries, except for seeding its internal PRNG pool.
40 /*
41 /* The \fBtlsmgr\fR(8) can be run chrooted and with reduced privileges.
42 /* At process startup it connects to the entropy source and
43 /* exchange file, and creates or truncates the optional TLS
44 /* session cache files.
45 /*
46 /* With Postfix version 2.5 and later, the \fBtlsmgr\fR(8) no
47 /* longer uses root privileges when opening cache files. These
48 /* files should now be stored under the Postfix-owned
49 /* \fBdata_directory\fR. As a migration aid, an attempt to
50 /* open a cache file under a non-Postfix directory is redirected
51 /* to the Postfix-owned \fBdata_directory\fR, and a warning
52 /* is logged.
53 /* DIAGNOSTICS
54 /* Problems and transactions are logged to \fBsyslogd\fR(8)
55 /* or \fBpostlogd\fR(8).
56 /* BUGS
57 /* There is no automatic means to limit the number of entries in the
58 /* TLS session caches and/or the size of the TLS cache files.
59 /* CONFIGURATION PARAMETERS
60 /* .ad
61 /* .fi
62 /* Changes to \fBmain.cf\fR are not picked up automatically,
63 /* because \fBtlsmgr\fR(8) is a persistent processes. Use the
64 /* command "\fBpostfix reload\fR" after a configuration change.
65 /*
66 /* The text below provides only a parameter summary. See
67 /* \fBpostconf\fR(5) for more details including examples.
68 /* TLS SESSION CACHE
69 /* .ad
70 /* .fi
71 /* .IP "\fBlmtp_tls_loglevel (0)\fR"
72 /* The LMTP-specific version of the smtp_tls_loglevel
73 /* configuration parameter.
74 /* .IP "\fBlmtp_tls_session_cache_database (empty)\fR"
75 /* The LMTP-specific version of the smtp_tls_session_cache_database
76 /* configuration parameter.
77 /* .IP "\fBlmtp_tls_session_cache_timeout (3600s)\fR"
78 /* The LMTP-specific version of the smtp_tls_session_cache_timeout
79 /* configuration parameter.
80 /* .IP "\fBsmtp_tls_loglevel (0)\fR"
81 /* Enable additional Postfix SMTP client logging of TLS activity.
82 /* .IP "\fBsmtp_tls_session_cache_database (empty)\fR"
83 /* Name of the file containing the optional Postfix SMTP client
84 /* TLS session cache.
85 /* .IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
86 /* The expiration time of Postfix SMTP client TLS session cache
87 /* information.
88 /* .IP "\fBsmtpd_tls_loglevel (0)\fR"
89 /* Enable additional Postfix SMTP server logging of TLS activity.
90 /* .IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
91 /* Name of the file containing the optional Postfix SMTP server
92 /* TLS session cache.
93 /* .IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
94 /* The expiration time of Postfix SMTP server TLS session cache
95 /* information.
96 /* PSEUDO RANDOM NUMBER GENERATOR
97 /* .ad
98 /* .fi
99 /* .IP "\fBtls_random_source (see 'postconf -d' output)\fR"
100 /* The external entropy source for the in-memory \fBtlsmgr\fR(8) pseudo
101 /* random number generator (PRNG) pool.
102 /* .IP "\fBtls_random_bytes (32)\fR"
103 /* The number of bytes that \fBtlsmgr\fR(8) reads from $tls_random_source
104 /* when (re)seeding the in-memory pseudo random number generator (PRNG)
105 /* pool.
106 /* .IP "\fBtls_random_exchange_name (see 'postconf -d' output)\fR"
107 /* Name of the pseudo random number generator (PRNG) state file
108 /* that is maintained by \fBtlsmgr\fR(8).
109 /* .IP "\fBtls_random_prng_update_period (3600s)\fR"
110 /* The time between attempts by \fBtlsmgr\fR(8) to save the state of
111 /* the pseudo random number generator (PRNG) to the file specified
112 /* with $tls_random_exchange_name.
113 /* .IP "\fBtls_random_reseed_period (3600s)\fR"
114 /* The maximal time between attempts by \fBtlsmgr\fR(8) to re-seed the
115 /* in-memory pseudo random number generator (PRNG) pool from external
116 /* sources.
117 /* MISCELLANEOUS CONTROLS
118 /* .ad
119 /* .fi
120 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
121 /* The default location of the Postfix main.cf and master.cf
122 /* configuration files.
123 /* .IP "\fBdata_directory (see 'postconf -d' output)\fR"
124 /* The directory with Postfix-writable data files (for example:
125 /* caches, pseudo-random numbers).
126 /* .IP "\fBdaemon_timeout (18000s)\fR"
127 /* How much time a Postfix daemon process may take to handle a
128 /* request before it is terminated by a built-in watchdog timer.
129 /* .IP "\fBprocess_id (read-only)\fR"
130 /* The process ID of a Postfix command or daemon process.
131 /* .IP "\fBprocess_name (read-only)\fR"
132 /* The process name of a Postfix command or daemon process.
133 /* .IP "\fBsyslog_facility (mail)\fR"
134 /* The syslog facility of Postfix logging.
135 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
136 /* A prefix that is prepended to the process name in syslog
137 /* records, so that, for example, "smtpd" becomes "prefix/smtpd".
138 /* .PP
139 /* Available in Postfix 3.3 and later:
140 /* .IP "\fBservice_name (read-only)\fR"
141 /* The master.cf service name of a Postfix daemon process.
142 /* SEE ALSO
143 /* smtp(8), Postfix SMTP client
144 /* smtpd(8), Postfix SMTP server
145 /* postconf(5), configuration parameters
146 /* master(5), generic daemon options
147 /* master(8), process manager
148 /* postlogd(8), Postfix logging
149 /* syslogd(8), system logging
150 /* README FILES
151 /* .ad
152 /* .fi
153 /* Use "\fBpostconf readme_directory\fR" or
154 /* "\fBpostconf html_directory\fR" to locate this information.
155 /* .na
156 /* .nf
157 /* TLS_README, Postfix TLS configuration and operation
158 /* LICENSE
159 /* .ad
160 /* .fi
161 /* The Secure Mailer license must be distributed with this software.
162 /* HISTORY
163 /* This service was introduced with Postfix version 2.2.
164 /* AUTHOR(S)
165 /* Lutz Jaenicke
166 /* BTU Cottbus
167 /* Allgemeine Elektrotechnik
168 /* Universitaetsplatz 3-4
169 /* D-03044 Cottbus, Germany
170 /*
171 /* Adapted by:
172 /* Wietse Venema
173 /* IBM T.J. Watson Research
174 /* P.O. Box 704
175 /* Yorktown Heights, NY 10598, USA
176 /*
177 /* Wietse Venema
178 /* Google, Inc.
179 /* 111 8th Avenue
180 /* New York, NY 10011, USA
181 /*--*/
182
183 /* System library. */
184
185 #include <sys_defs.h>
186 #include <sys/stat.h>
187 #include <stdlib.h>
188 #include <unistd.h>
189 #include <ctype.h>
190 #include <errno.h>
191 #include <string.h>
192 #include <sys/time.h> /* gettimeofday, not POSIX */
193 #include <limits.h>
194
195 #ifndef UCHAR_MAX
196 #define UCHAR_MAX 0xff
197 #endif
198
199 /* OpenSSL library. */
200
201 #ifdef USE_TLS
202 #include <openssl/rand.h> /* For the PRNG */
203 #endif
204
205 /* Utility library. */
206
207 #include <msg.h>
208 #include <events.h>
209 #include <stringops.h>
210 #include <mymalloc.h>
211 #include <iostuff.h>
212 #include <vstream.h>
213 #include <vstring.h>
214 #include <vstring_vstream.h>
215 #include <attr.h>
216 #include <set_eugid.h>
217 #include <htable.h>
218 #include <warn_stat.h>
219
220 /* Global library. */
221
222 #include <mail_conf.h>
223 #include <mail_params.h>
224 #include <mail_version.h>
225 #include <mail_proto.h>
226 #include <data_redirect.h>
227
228 /* Master process interface. */
229
230 #include <master_proto.h>
231 #include <mail_server.h>
232
233 /* TLS library. */
234
235 #ifdef USE_TLS
236 #include <tls_mgr.h>
237 #define TLS_INTERNAL
238 #include <tls.h> /* TLS_MGR_SCACHE_<type> */
239 #include <tls_prng.h>
240 #include <tls_scache.h>
241
242 /* Application-specific. */
243
244 /*
245 * Tunables.
246 */
247 char *var_tls_rand_source;
248 int var_tls_rand_bytes;
249 int var_tls_reseed_period;
250 int var_tls_prng_exch_period;
251 char *var_smtpd_tls_loglevel;
252 char *var_smtpd_tls_scache_db;
253 int var_smtpd_tls_scache_timeout;
254 char *var_smtp_tls_loglevel;
255 char *var_smtp_tls_scache_db;
256 int var_smtp_tls_scache_timeout;
257 char *var_lmtp_tls_loglevel;
258 char *var_lmtp_tls_scache_db;
259 int var_lmtp_tls_scache_timeout;
260 char *var_tls_rand_exch_name;
261
262 /*
263 * Bound the time that we are willing to wait for an I/O operation. This
264 * produces better error messages than waiting until the watchdog timer
265 * kills the process.
266 */
267 #define TLS_MGR_TIMEOUT 10
268
269 /*
270 * State for updating the PRNG exchange file.
271 */
272 static TLS_PRNG_SRC *rand_exch;
273
274 /*
275 * State for seeding the internal PRNG from external source.
276 */
277 static TLS_PRNG_SRC *rand_source_dev;
278 static TLS_PRNG_SRC *rand_source_egd;
279 static TLS_PRNG_SRC *rand_source_file;
280
281 /*
282 * The external entropy source type is encoded in the source name. The
283 * obvious alternative is to have separate configuration parameters per
284 * source type, so that one process can query multiple external sources.
285 */
286 #define DEV_PREF "dev:"
287 #define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
288 #define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
289
290 #define EGD_PREF "egd:"
291 #define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
292 #define EGD_PATH(egd) ((egd) + EGD_PREF_LEN)
293
294 /*
295 * State for TLS session caches.
296 */
297 typedef struct {
298 char *cache_label; /* cache short-hand name */
299 TLS_SCACHE *cache_info; /* cache handle */
300 int cache_active; /* cache status */
301 char **cache_db; /* main.cf parameter value */
302 const char *log_param; /* main.cf parameter name */
303 char **log_level; /* main.cf parameter value */
304 int *cache_timeout; /* main.cf parameter value */
305 } TLSMGR_SCACHE;
306
307 static TLSMGR_SCACHE cache_table[] = {
308 TLS_MGR_SCACHE_SMTPD, 0, 0, &var_smtpd_tls_scache_db,
309 VAR_SMTPD_TLS_LOGLEVEL,
310 &var_smtpd_tls_loglevel, &var_smtpd_tls_scache_timeout,
311 TLS_MGR_SCACHE_SMTP, 0, 0, &var_smtp_tls_scache_db,
312 VAR_SMTP_TLS_LOGLEVEL,
313 &var_smtp_tls_loglevel, &var_smtp_tls_scache_timeout,
314 TLS_MGR_SCACHE_LMTP, 0, 0, &var_lmtp_tls_scache_db,
315 VAR_LMTP_TLS_LOGLEVEL,
316 &var_lmtp_tls_loglevel, &var_lmtp_tls_scache_timeout,
317 0,
318 };
319
320 #define smtpd_cache (cache_table[0])
321
322 /*
323 * SLMs.
324 */
325 #define STR(x) vstring_str(x)
326 #define LEN(x) VSTRING_LEN(x)
327 #define STREQ(x, y) (strcmp((x), (y)) == 0)
328
329 /* tlsmgr_prng_exch_event - update PRNG exchange file */
330
tlsmgr_prng_exch_event(int unused_event,void * dummy)331 static void tlsmgr_prng_exch_event(int unused_event, void *dummy)
332 {
333 const char *myname = "tlsmgr_prng_exch_event";
334 unsigned char randbyte;
335 int next_period;
336 struct stat st;
337
338 if (msg_verbose)
339 msg_info("%s: update PRNG exchange file", myname);
340
341 /*
342 * Sanity check. If the PRNG exchange file was removed, there is no point
343 * updating it further. Restart the process and update the new file.
344 */
345 if (fstat(rand_exch->fd, &st) < 0)
346 msg_fatal("cannot fstat() the PRNG exchange file: %m");
347 if (st.st_nlink == 0) {
348 msg_warn("PRNG exchange file was removed -- exiting to reopen");
349 sleep(1);
350 exit(0);
351 }
352 tls_prng_exch_update(rand_exch);
353
354 /*
355 * Make prediction difficult for outsiders and calculate the time for the
356 * next execution randomly.
357 */
358 RAND_bytes(&randbyte, 1);
359 next_period = (var_tls_prng_exch_period * randbyte) / UCHAR_MAX;
360 event_request_timer(tlsmgr_prng_exch_event, dummy, next_period);
361 }
362
363 /* tlsmgr_reseed_event - re-seed the internal PRNG pool */
364
tlsmgr_reseed_event(int unused_event,void * dummy)365 static void tlsmgr_reseed_event(int unused_event, void *dummy)
366 {
367 int next_period;
368 unsigned char randbyte;
369 int must_exit = 0;
370
371 /*
372 * Reseed the internal PRNG from external source. Errors are recoverable.
373 * We simply restart and reconnect without making a fuss. This is OK
374 * because we do require that exchange file updates succeed. The exchange
375 * file is the only entropy source that really matters in the long term.
376 *
377 * If the administrator specifies an external randomness source that we
378 * could not open upon start-up, restart to see if we can open it now
379 * (and log a nagging warning if we can't).
380 */
381 if (*var_tls_rand_source) {
382
383 /*
384 * Source is a random device.
385 */
386 if (rand_source_dev) {
387 if (tls_prng_dev_read(rand_source_dev, var_tls_rand_bytes) <= 0) {
388 msg_info("cannot read from entropy device %s: %m -- "
389 "exiting to reopen", DEV_PATH(var_tls_rand_source));
390 must_exit = 1;
391 }
392 }
393
394 /*
395 * Source is an EGD compatible socket.
396 */
397 else if (rand_source_egd) {
398 if (tls_prng_egd_read(rand_source_egd, var_tls_rand_bytes) <= 0) {
399 msg_info("lost connection to EGD server %s -- "
400 "exiting to reconnect", EGD_PATH(var_tls_rand_source));
401 must_exit = 1;
402 }
403 }
404
405 /*
406 * Source is a regular file. Read the content once and close the
407 * file.
408 */
409 else if (rand_source_file) {
410 if (tls_prng_file_read(rand_source_file, var_tls_rand_bytes) <= 0)
411 msg_warn("cannot read from entropy file %s: %m",
412 var_tls_rand_source);
413 tls_prng_file_close(rand_source_file);
414 rand_source_file = 0;
415 var_tls_rand_source[0] = 0;
416 }
417
418 /*
419 * Could not open the external source upon start-up. See if we can
420 * open it this time. Save PRNG state before we exit.
421 */
422 else {
423 msg_info("exiting to reopen external entropy source %s",
424 var_tls_rand_source);
425 must_exit = 1;
426 }
427 }
428
429 /*
430 * Save PRNG state in case we must exit.
431 */
432 if (must_exit) {
433 if (rand_exch)
434 tls_prng_exch_update(rand_exch);
435 sleep(1);
436 exit(0);
437 }
438
439 /*
440 * Make prediction difficult for outsiders and calculate the time for the
441 * next execution randomly.
442 */
443 RAND_bytes(&randbyte, 1);
444 next_period = (var_tls_reseed_period * randbyte) / UCHAR_MAX;
445 event_request_timer(tlsmgr_reseed_event, dummy, next_period);
446 }
447
448 /* tlsmgr_cache_run_event - start TLS session cache scan */
449
tlsmgr_cache_run_event(int unused_event,void * ctx)450 static void tlsmgr_cache_run_event(int unused_event, void *ctx)
451 {
452 const char *myname = "tlsmgr_cache_run_event";
453 TLSMGR_SCACHE *cache = (TLSMGR_SCACHE *) ctx;
454
455 /*
456 * This routine runs when it is time for another TLS session cache scan.
457 * Make sure this routine gets called again in the future.
458 *
459 * Don't start a new scan when the timer goes off while cache cleanup is
460 * still in progress.
461 */
462 if (cache->cache_info->verbose)
463 msg_info("%s: start TLS %s session cache cleanup",
464 myname, cache->cache_label);
465
466 if (cache->cache_active == 0)
467 cache->cache_active =
468 tls_scache_sequence(cache->cache_info, DICT_SEQ_FUN_FIRST,
469 TLS_SCACHE_SEQUENCE_NOTHING);
470
471 event_request_timer(tlsmgr_cache_run_event, (void *) cache,
472 cache->cache_info->timeout);
473 }
474
475 /* tlsmgr_key - return matching or current RFC 5077 session ticket keys */
476
tlsmgr_key(VSTRING * buffer,int timeout)477 static int tlsmgr_key(VSTRING *buffer, int timeout)
478 {
479 TLS_TICKET_KEY *key;
480 TLS_TICKET_KEY tmp;
481 unsigned char *name;
482 time_t now = time((time_t *) 0);
483
484 /* In tlsmgr requests we encode null key names as empty strings. */
485 name = LEN(buffer) ? (unsigned char *) STR(buffer) : 0;
486
487 /*
488 * Each key's encrypt and subsequent decrypt-only timeout is half of the
489 * total session timeout.
490 */
491 timeout /= 2;
492
493 /* Attempt to locate existing key */
494 if ((key = tls_scache_key(name, now, timeout)) == 0) {
495 if (name == 0) {
496 /* Create new encryption key */
497 if (RAND_bytes(tmp.name, TLS_TICKET_NAMELEN) <= 0
498 || RAND_bytes(tmp.bits, TLS_TICKET_KEYLEN) <= 0
499 || RAND_bytes(tmp.hmac, TLS_TICKET_MACLEN) <= 0)
500 return (TLS_MGR_STAT_ERR);
501 tmp.tout = now + timeout - 1;
502 key = tls_scache_key_rotate(&tmp);
503 } else {
504 /* No matching decryption key found */
505 return (TLS_MGR_STAT_ERR);
506 }
507 }
508 /* Return value overwrites name buffer */
509 vstring_memcpy(buffer, (char *) key, sizeof(*key));
510 return (TLS_MGR_STAT_OK);
511 }
512
513 /* tlsmgr_loop - TLS manager main loop */
514
tlsmgr_loop(char * unused_name,char ** unused_argv)515 static int tlsmgr_loop(char *unused_name, char **unused_argv)
516 {
517 struct timeval tv;
518 int active = 0;
519 TLSMGR_SCACHE *ent;
520
521 /*
522 * Update the PRNG pool with the time of day. We do it here after every
523 * event (including internal timer events and external client request
524 * events), instead of doing it in individual event call-back routines.
525 */
526 GETTIMEOFDAY(&tv);
527 RAND_seed(&tv, sizeof(struct timeval));
528
529 /*
530 * This routine runs as part of the event handling loop, after the event
531 * manager has delivered a timer or I/O event, or after it has waited for
532 * a specified amount of time. The result value of tlsmgr_loop()
533 * specifies how long the event manager should wait for the next event.
534 *
535 * We use this loop to interleave TLS session cache cleanup with other
536 * activity. Interleaved processing is needed when we use a client-server
537 * protocol for entropy and session state exchange with smtp(8) and
538 * smtpd(8) processes.
539 */
540 #define DONT_WAIT 0
541 #define WAIT_FOR_EVENT (-1)
542
543 for (ent = cache_table; ent->cache_label; ++ent) {
544 if (ent->cache_info && ent->cache_active)
545 active |= ent->cache_active =
546 tls_scache_sequence(ent->cache_info, DICT_SEQ_FUN_NEXT,
547 TLS_SCACHE_SEQUENCE_NOTHING);
548 }
549
550 return (active ? DONT_WAIT : WAIT_FOR_EVENT);
551 }
552
553 /* tlsmgr_request_receive - receive request */
554
tlsmgr_request_receive(VSTREAM * client_stream,VSTRING * request)555 static int tlsmgr_request_receive(VSTREAM *client_stream, VSTRING *request)
556 {
557 int count;
558
559 /*
560 * Kluge: choose the protocol depending on the request size.
561 */
562 if (read_wait(vstream_fileno(client_stream), var_ipc_timeout) < 0) {
563 msg_warn("timeout while waiting for data from %s",
564 VSTREAM_PATH(client_stream));
565 return (-1);
566 }
567 if ((count = peekfd(vstream_fileno(client_stream))) < 0) {
568 msg_warn("cannot examine read buffer of %s: %m",
569 VSTREAM_PATH(client_stream));
570 return (-1);
571 }
572
573 /*
574 * Short request: master trigger. Use the string+null protocol.
575 */
576 if (count <= 2) {
577 if (vstring_get_null(request, client_stream) == VSTREAM_EOF) {
578 msg_warn("end-of-input while reading request from %s: %m",
579 VSTREAM_PATH(client_stream));
580 return (-1);
581 }
582 }
583
584 /*
585 * Long request: real tlsmgr client. Use the attribute list protocol.
586 */
587 else {
588 if (attr_scan(client_stream,
589 ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
590 RECV_ATTR_STR(TLS_MGR_ATTR_REQ, request),
591 ATTR_TYPE_END) != 1) {
592 return (-1);
593 }
594 }
595 return (0);
596 }
597
598 /* tlsmgr_service - respond to external request */
599
tlsmgr_service(VSTREAM * client_stream,char * unused_service,char ** argv)600 static void tlsmgr_service(VSTREAM *client_stream, char *unused_service,
601 char **argv)
602 {
603 static VSTRING *request = 0;
604 static VSTRING *cache_type = 0;
605 static VSTRING *cache_id = 0;
606 static VSTRING *buffer = 0;
607 int len;
608 static char wakeup[] = { /* master wakeup request */
609 TRIGGER_REQ_WAKEUP,
610 0,
611 };
612 TLSMGR_SCACHE *ent;
613 int status = TLS_MGR_STAT_FAIL;
614
615 /*
616 * Sanity check. This service takes no command-line arguments.
617 */
618 if (argv[0])
619 msg_fatal("unexpected command-line argument: %s", argv[0]);
620
621 /*
622 * Initialize. We're select threaded, so we can use static buffers.
623 */
624 if (request == 0) {
625 request = vstring_alloc(10);
626 cache_type = vstring_alloc(10);
627 cache_id = vstring_alloc(10);
628 buffer = vstring_alloc(10);
629 }
630
631 /*
632 * This routine runs whenever a client connects to the socket dedicated
633 * to the tlsmgr service (including wake up events sent by the master).
634 * All connection-management stuff is handled by the common code in
635 * multi_server.c.
636 */
637 if (tlsmgr_request_receive(client_stream, request) == 0) {
638
639 /*
640 * Load session from cache.
641 */
642 if (STREQ(STR(request), TLS_MGR_REQ_LOOKUP)) {
643 if (attr_scan(client_stream, ATTR_FLAG_STRICT,
644 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
645 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
646 ATTR_TYPE_END) == 2) {
647 for (ent = cache_table; ent->cache_label; ++ent)
648 if (strcmp(ent->cache_label, STR(cache_type)) == 0)
649 break;
650 if (ent->cache_label == 0) {
651 msg_warn("bogus cache type \"%s\" in \"%s\" request",
652 STR(cache_type), TLS_MGR_REQ_LOOKUP);
653 VSTRING_RESET(buffer);
654 } else if (ent->cache_info == 0) {
655
656 /*
657 * Cache type valid, but not enabled
658 */
659 VSTRING_RESET(buffer);
660 } else {
661 status = tls_scache_lookup(ent->cache_info,
662 STR(cache_id), buffer) ?
663 TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
664 }
665 }
666 attr_print(client_stream, ATTR_FLAG_NONE,
667 SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
668 SEND_ATTR_DATA(TLS_MGR_ATTR_SESSION,
669 LEN(buffer), STR(buffer)),
670 ATTR_TYPE_END);
671 }
672
673 /*
674 * Save session to cache.
675 */
676 else if (STREQ(STR(request), TLS_MGR_REQ_UPDATE)) {
677 if (attr_scan(client_stream, ATTR_FLAG_STRICT,
678 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
679 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
680 RECV_ATTR_DATA(TLS_MGR_ATTR_SESSION, buffer),
681 ATTR_TYPE_END) == 3) {
682 for (ent = cache_table; ent->cache_label; ++ent)
683 if (strcmp(ent->cache_label, STR(cache_type)) == 0)
684 break;
685 if (ent->cache_label == 0) {
686 msg_warn("bogus cache type \"%s\" in \"%s\" request",
687 STR(cache_type), TLS_MGR_REQ_UPDATE);
688 } else if (ent->cache_info != 0) {
689 status =
690 tls_scache_update(ent->cache_info, STR(cache_id),
691 STR(buffer), LEN(buffer)) ?
692 TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
693 }
694 }
695 attr_print(client_stream, ATTR_FLAG_NONE,
696 SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
697 ATTR_TYPE_END);
698 }
699
700 /*
701 * Delete session from cache.
702 */
703 else if (STREQ(STR(request), TLS_MGR_REQ_DELETE)) {
704 if (attr_scan(client_stream, ATTR_FLAG_STRICT,
705 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
706 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
707 ATTR_TYPE_END) == 2) {
708 for (ent = cache_table; ent->cache_label; ++ent)
709 if (strcmp(ent->cache_label, STR(cache_type)) == 0)
710 break;
711 if (ent->cache_label == 0) {
712 msg_warn("bogus cache type \"%s\" in \"%s\" request",
713 STR(cache_type), TLS_MGR_REQ_DELETE);
714 } else if (ent->cache_info != 0) {
715 status = tls_scache_delete(ent->cache_info,
716 STR(cache_id)) ?
717 TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
718 }
719 }
720 attr_print(client_stream, ATTR_FLAG_NONE,
721 SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
722 ATTR_TYPE_END);
723 }
724
725 /*
726 * RFC 5077 TLS session ticket keys
727 */
728 else if (STREQ(STR(request), TLS_MGR_REQ_TKTKEY)) {
729 if (attr_scan(client_stream, ATTR_FLAG_STRICT,
730 RECV_ATTR_DATA(TLS_MGR_ATTR_KEYNAME, buffer),
731 ATTR_TYPE_END) == 1) {
732 if (LEN(buffer) != 0 && LEN(buffer) != TLS_TICKET_NAMELEN) {
733 msg_warn("invalid session ticket key name length: %ld",
734 (long) LEN(buffer));
735 VSTRING_RESET(buffer);
736 } else if (*smtpd_cache.cache_timeout <= 0) {
737 status = TLS_MGR_STAT_ERR;
738 VSTRING_RESET(buffer);
739 } else {
740 status = tlsmgr_key(buffer, *smtpd_cache.cache_timeout);
741 }
742 }
743 attr_print(client_stream, ATTR_FLAG_NONE,
744 SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
745 SEND_ATTR_DATA(TLS_MGR_ATTR_KEYBUF,
746 LEN(buffer), STR(buffer)),
747 ATTR_TYPE_END);
748 }
749
750 /*
751 * Entropy request.
752 */
753 else if (STREQ(STR(request), TLS_MGR_REQ_SEED)) {
754 if (attr_scan(client_stream, ATTR_FLAG_STRICT,
755 RECV_ATTR_INT(TLS_MGR_ATTR_SIZE, &len),
756 ATTR_TYPE_END) == 1) {
757 VSTRING_RESET(buffer);
758 if (len <= 0 || len > 255) {
759 msg_warn("bogus seed length \"%d\" in \"%s\" request",
760 len, TLS_MGR_REQ_SEED);
761 } else {
762 VSTRING_SPACE(buffer, len);
763 RAND_bytes((unsigned char *) STR(buffer), len);
764 vstring_set_payload_size(buffer, len);
765 status = TLS_MGR_STAT_OK;
766 }
767 }
768 attr_print(client_stream, ATTR_FLAG_NONE,
769 SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
770 SEND_ATTR_DATA(TLS_MGR_ATTR_SEED,
771 LEN(buffer), STR(buffer)),
772 ATTR_TYPE_END);
773 }
774
775 /*
776 * Caching policy request.
777 */
778 else if (STREQ(STR(request), TLS_MGR_REQ_POLICY)) {
779 int cachable = 0;
780 int timeout = 0;
781
782 if (attr_scan(client_stream, ATTR_FLAG_STRICT,
783 RECV_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
784 ATTR_TYPE_END) == 1) {
785 for (ent = cache_table; ent->cache_label; ++ent)
786 if (strcmp(ent->cache_label, STR(cache_type)) == 0)
787 break;
788 if (ent->cache_label == 0) {
789 msg_warn("bogus cache type \"%s\" in \"%s\" request",
790 STR(cache_type), TLS_MGR_REQ_POLICY);
791 } else {
792 cachable = (ent->cache_info != 0) ? 1 : 0;
793 timeout = *ent->cache_timeout;
794 status = TLS_MGR_STAT_OK;
795 }
796 }
797 attr_print(client_stream, ATTR_FLAG_NONE,
798 SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
799 SEND_ATTR_INT(TLS_MGR_ATTR_CACHABLE, cachable),
800 SEND_ATTR_INT(TLS_MGR_ATTR_SESSTOUT, timeout),
801 ATTR_TYPE_END);
802 }
803
804 /*
805 * Master trigger. Normally, these triggers arrive only after some
806 * other process requested the tlsmgr's service. The purpose is to
807 * restart the tlsmgr after it aborted due to a fatal run-time error,
808 * so that it can continue its housekeeping even while nothing is
809 * using TLS.
810 *
811 * XXX Which begs the question, if TLS isn't used often, do we need a
812 * tlsmgr background process? It could terminate when the session
813 * caches are empty.
814 */
815 else if (STREQ(STR(request), wakeup)) {
816 if (msg_verbose)
817 msg_info("received master trigger");
818 multi_server_disconnect(client_stream);
819 return; /* NOT: vstream_fflush */
820 }
821 }
822
823 /*
824 * Protocol error.
825 */
826 else {
827 attr_print(client_stream, ATTR_FLAG_NONE,
828 SEND_ATTR_INT(MAIL_ATTR_STATUS, TLS_MGR_STAT_FAIL),
829 ATTR_TYPE_END);
830 }
831 vstream_fflush(client_stream);
832 }
833
834 /* tlsmgr_pre_init - pre-jail initialization */
835
tlsmgr_pre_init(char * unused_name,char ** unused_argv)836 static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
837 {
838 char *path;
839 struct timeval tv;
840 TLSMGR_SCACHE *ent;
841 VSTRING *redirect;
842 HTABLE *dup_filter;
843 const char *dup_label;
844
845 /*
846 * If nothing else works then at least this will get us a few bits of
847 * entropy.
848 *
849 * XXX This is our first call into the OpenSSL library. We should find out
850 * if this can be moved to the post-jail initialization phase, without
851 * breaking compatibility with existing installations.
852 */
853 GETTIMEOFDAY(&tv);
854 tv.tv_sec ^= getpid();
855 RAND_seed(&tv, sizeof(struct timeval));
856
857 /*
858 * Open the external entropy source. We will not be able to open it again
859 * after we are sent to chroot jail, so we keep it open. Errors are not
860 * fatal. The exchange file (see below) is the only entropy source that
861 * really matters in the long run.
862 *
863 * Security note: we open the entropy source while privileged, but we don't
864 * access the source until after we release privileges. This way, none of
865 * the OpenSSL code gets to execute while we are privileged.
866 */
867 if (*var_tls_rand_source) {
868
869 /*
870 * Source is a random device.
871 */
872 if (!strncmp(var_tls_rand_source, DEV_PREF, DEV_PREF_LEN)) {
873 path = DEV_PATH(var_tls_rand_source);
874 rand_source_dev = tls_prng_dev_open(path, TLS_MGR_TIMEOUT);
875 if (rand_source_dev == 0)
876 msg_warn("cannot open entropy device %s: %m", path);
877 }
878
879 /*
880 * Source is an EGD compatible socket.
881 */
882 else if (!strncmp(var_tls_rand_source, EGD_PREF, EGD_PREF_LEN)) {
883 path = EGD_PATH(var_tls_rand_source);
884 rand_source_egd = tls_prng_egd_open(path, TLS_MGR_TIMEOUT);
885 if (rand_source_egd == 0)
886 msg_warn("cannot connect to EGD server %s: %m", path);
887 }
888
889 /*
890 * Source is regular file. We read this only once.
891 */
892 else {
893 rand_source_file =
894 tls_prng_file_open(var_tls_rand_source, TLS_MGR_TIMEOUT);
895 }
896 } else {
897 msg_warn("no entropy source specified with parameter %s",
898 VAR_TLS_RAND_SOURCE);
899 msg_warn("encryption keys etc. may be predictable");
900 }
901
902 /*
903 * Security: don't create root-owned files that contain untrusted data.
904 * And don't create Postfix-owned files in root-owned directories,
905 * either. We want a correct relationship between (file/directory)
906 * ownership and (file/directory) content.
907 */
908 SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
909 redirect = vstring_alloc(100);
910
911 /*
912 * Open the PRNG exchange file before going to jail, but don't use root
913 * privileges. Start the exchange file read/update pseudo thread after
914 * dropping privileges.
915 */
916 if (*var_tls_rand_exch_name) {
917 rand_exch =
918 tls_prng_exch_open(data_redirect_file(redirect,
919 var_tls_rand_exch_name));
920 if (rand_exch == 0)
921 msg_fatal("cannot open PRNG exchange file %s: %m",
922 var_tls_rand_exch_name);
923 }
924
925 /*
926 * Open the session cache files and discard old information before going
927 * to jail, but don't use root privilege. Start the cache maintenance
928 * pseudo threads after dropping privileges.
929 */
930 dup_filter = htable_create(sizeof(cache_table) / sizeof(cache_table[0]));
931 for (ent = cache_table; ent->cache_label; ++ent) {
932 /* Sanitize session timeout */
933 if (*ent->cache_timeout > 0) {
934 if (*ent->cache_timeout < TLS_SESSION_LIFEMIN)
935 *ent->cache_timeout = TLS_SESSION_LIFEMIN;
936 } else {
937 *ent->cache_timeout = 0;
938 }
939 /* External cache database disabled if timeout is non-positive */
940 if (*ent->cache_timeout > 0 && **ent->cache_db) {
941 if ((dup_label = htable_find(dup_filter, *ent->cache_db)) != 0)
942 msg_fatal("do not use the same TLS cache file %s for %s and %s",
943 *ent->cache_db, dup_label, ent->cache_label);
944 htable_enter(dup_filter, *ent->cache_db, ent->cache_label);
945 ent->cache_info =
946 tls_scache_open(data_redirect_map(redirect, *ent->cache_db),
947 ent->cache_label,
948 tls_log_mask(ent->log_param,
949 *ent->log_level) & TLS_LOG_CACHE,
950 *ent->cache_timeout);
951 }
952 }
953 htable_free(dup_filter, (void (*) (void *)) 0);
954
955 /*
956 * Clean up and restore privilege.
957 */
958 vstring_free(redirect);
959 RESTORE_SAVED_EUGID();
960 }
961
962 /* tlsmgr_post_init - post-jail initialization */
963
tlsmgr_post_init(char * unused_name,char ** unused_argv)964 static void tlsmgr_post_init(char *unused_name, char **unused_argv)
965 {
966 TLSMGR_SCACHE *ent;
967
968 #define NULL_EVENT (0)
969 #define NULL_CONTEXT ((char *) 0)
970
971 /*
972 * This routine runs after the skeleton code has entered the chroot jail,
973 * but before any client requests are serviced. Prevent automatic process
974 * suicide after a limited number of client requests or after a limited
975 * amount of idle time.
976 */
977 var_use_limit = 0;
978 var_idle_limit = 0;
979
980 /*
981 * Start the internal PRNG re-seeding pseudo thread first.
982 */
983 if (*var_tls_rand_source) {
984 if (var_tls_reseed_period > INT_MAX / UCHAR_MAX)
985 var_tls_reseed_period = INT_MAX / UCHAR_MAX;
986 tlsmgr_reseed_event(NULL_EVENT, NULL_CONTEXT);
987 }
988
989 /*
990 * Start the exchange file read/update pseudo thread.
991 */
992 if (*var_tls_rand_exch_name) {
993 if (var_tls_prng_exch_period > INT_MAX / UCHAR_MAX)
994 var_tls_prng_exch_period = INT_MAX / UCHAR_MAX;
995 tlsmgr_prng_exch_event(NULL_EVENT, NULL_CONTEXT);
996 }
997
998 /*
999 * Start the cache maintenance pseudo threads last. Strictly speaking
1000 * there is nothing to clean up after we truncate the database to zero
1001 * length, but early cleanup makes verbose logging more informative (we
1002 * get positive confirmation that the cleanup threads are running).
1003 */
1004 for (ent = cache_table; ent->cache_label; ++ent)
1005 if (ent->cache_info)
1006 tlsmgr_cache_run_event(NULL_EVENT, (void *) ent);
1007 }
1008
1009 /* tlsmgr_post_accept - announce our protocol */
1010
tlsmgr_post_accept(VSTREAM * stream,char * unused_name,char ** unused_argv,HTABLE * unused_table)1011 static void tlsmgr_post_accept(VSTREAM *stream, char *unused_name,
1012 char **unused_argv, HTABLE *unused_table)
1013 {
1014
1015 /*
1016 * Announce the protocol.
1017 */
1018 attr_print(stream, ATTR_FLAG_NONE,
1019 SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
1020 ATTR_TYPE_END);
1021 (void) vstream_fflush(stream);
1022 }
1023
1024
1025 /* tlsmgr_before_exit - save PRNG state before exit */
1026
tlsmgr_before_exit(char * unused_service_name,char ** unused_argv)1027 static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
1028 {
1029
1030 /*
1031 * Save state before we exit after "postfix reload".
1032 */
1033 if (rand_exch)
1034 tls_prng_exch_update(rand_exch);
1035 }
1036
1037 MAIL_VERSION_STAMP_DECLARE;
1038
1039 /* main - the main program */
1040
main(int argc,char ** argv)1041 int main(int argc, char **argv)
1042 {
1043 static const CONFIG_STR_TABLE str_table[] = {
1044 VAR_TLS_RAND_SOURCE, DEF_TLS_RAND_SOURCE, &var_tls_rand_source, 0, 0,
1045 VAR_TLS_RAND_EXCH_NAME, DEF_TLS_RAND_EXCH_NAME, &var_tls_rand_exch_name, 0, 0,
1046 VAR_SMTPD_TLS_SCACHE_DB, DEF_SMTPD_TLS_SCACHE_DB, &var_smtpd_tls_scache_db, 0, 0,
1047 VAR_SMTP_TLS_SCACHE_DB, DEF_SMTP_TLS_SCACHE_DB, &var_smtp_tls_scache_db, 0, 0,
1048 VAR_LMTP_TLS_SCACHE_DB, DEF_LMTP_TLS_SCACHE_DB, &var_lmtp_tls_scache_db, 0, 0,
1049 VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
1050 VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0,
1051 VAR_LMTP_TLS_LOGLEVEL, DEF_LMTP_TLS_LOGLEVEL, &var_lmtp_tls_loglevel, 0, 0,
1052 0,
1053 };
1054 static const CONFIG_TIME_TABLE time_table[] = {
1055 VAR_TLS_RESEED_PERIOD, DEF_TLS_RESEED_PERIOD, &var_tls_reseed_period, 1, 0,
1056 VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_exch_period, 1, 0,
1057 VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, MAX_SMTPD_TLS_SCACHETIME,
1058 VAR_SMTP_TLS_SCACHTIME, DEF_SMTP_TLS_SCACHTIME, &var_smtp_tls_scache_timeout, 0, MAX_SMTP_TLS_SCACHETIME,
1059 VAR_LMTP_TLS_SCACHTIME, DEF_LMTP_TLS_SCACHTIME, &var_lmtp_tls_scache_timeout, 0, MAX_LMTP_TLS_SCACHETIME,
1060 0,
1061 };
1062 static const CONFIG_INT_TABLE int_table[] = {
1063 VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 1, 0,
1064 0,
1065 };
1066
1067 /*
1068 * Fingerprint executables and core dumps.
1069 */
1070 MAIL_VERSION_STAMP_ALLOCATE;
1071
1072 /*
1073 * Use the multi service skeleton, and require that no-one else is
1074 * monitoring our service port while this process runs.
1075 */
1076 multi_server_main(argc, argv, tlsmgr_service,
1077 CA_MAIL_SERVER_TIME_TABLE(time_table),
1078 CA_MAIL_SERVER_INT_TABLE(int_table),
1079 CA_MAIL_SERVER_STR_TABLE(str_table),
1080 CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init),
1081 CA_MAIL_SERVER_POST_INIT(tlsmgr_post_init),
1082 CA_MAIL_SERVER_POST_ACCEPT(tlsmgr_post_accept),
1083 CA_MAIL_SERVER_EXIT(tlsmgr_before_exit),
1084 CA_MAIL_SERVER_LOOP(tlsmgr_loop),
1085 CA_MAIL_SERVER_SOLITARY,
1086 0);
1087 }
1088
1089 #else
1090
1091 /* tlsmgr_service - respond to external trigger(s), non-TLS version */
1092
tlsmgr_service(VSTREAM * unused_stream,char * unused_service,char ** unused_argv)1093 static void tlsmgr_service(VSTREAM *unused_stream, char *unused_service,
1094 char **unused_argv)
1095 {
1096 msg_info("TLS support is not compiled in -- exiting");
1097 }
1098
1099 /* main - the main program, non-TLS version */
1100
main(int argc,char ** argv)1101 int main(int argc, char **argv)
1102 {
1103
1104 /*
1105 * 200411 We can't simply use msg_fatal() here, because the logging
1106 * hasn't been initialized. The text would disappear because stderr is
1107 * redirected to /dev/null.
1108 *
1109 * We invoke multi_server_main() to complete program initialization
1110 * (including logging) and then invoke the tlsmgr_service() routine to
1111 * log the message that says why this program will not run.
1112 */
1113 multi_server_main(argc, argv, tlsmgr_service,
1114 0);
1115 }
1116
1117 #endif
1118