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