1155324Simp/*	$NetBSD$	*/
2155324Simp
3155324Simp/*++
4155324Simp/* NAME
5155324Simp/*	tlsmgr 8
6155324Simp/* SUMMARY
7155324Simp/*	Postfix TLS session cache and PRNG manager
8155324Simp/* SYNOPSIS
9155324Simp/*	\fBtlsmgr\fR [generic Postfix daemon options]
10155324Simp/* DESCRIPTION
11155324Simp/*	The \fBtlsmgr\fR(8) manages the Postfix TLS session caches.
12155324Simp/*	It stores and retrieves cache entries on request by
13185265Simp/*	\fBsmtpd\fR(8) and \fBsmtp\fR(8) processes, and periodically
14185265Simp/*	removes entries that have expired.
15185265Simp/*
16185265Simp/*	The \fBtlsmgr\fR(8) also manages the PRNG (pseudo random number
17185265Simp/*	generator) pool. It answers queries by the \fBsmtpd\fR(8)
18185265Simp/*	and \fBsmtp\fR(8)
19185265Simp/*	processes to seed their internal PRNG pools.
20185265Simp/*
21185265Simp/*	The \fBtlsmgr\fR(8)'s PRNG pool is initially seeded from
22185265Simp/*	an external source (EGD, /dev/urandom, or regular file).
23185265Simp/*	It is updated at configurable pseudo-random intervals with
24155324Simp/*	data from the external source. It is updated periodically
25155324Simp/*	with data from TLS session cache entries and with the time
26155324Simp/*	of day, and is updated with the time of day whenever a
27155324Simp/*	process requests \fBtlsmgr\fR(8) service.
28155324Simp/*
29155324Simp/*	The \fBtlsmgr\fR(8) saves the PRNG state to an exchange file
30155324Simp/*	periodically and when the process terminates, and reads
31155324Simp/*	the exchange file when initializing its PRNG.
32157561Simp/* SECURITY
33157561Simp/* .ad
34157561Simp/* .fi
35157561Simp/*	The \fBtlsmgr\fR(8) is not security-sensitive. The code that maintains
36157561Simp/*	the external and internal PRNG pools does not "trust" the
37157561Simp/*	data that it manipulates, and the code that maintains the
38157561Simp/*	TLS session cache does not touch the contents of the cached
39157561Simp/*	entries, except for seeding its internal PRNG pool.
40157561Simp/*
41157561Simp/*	The \fBtlsmgr\fR(8) can be run chrooted and with reduced privileges.
42157561Simp/*	At process startup it connects to the entropy source and
43157561Simp/*	exchange file, and creates or truncates the optional TLS
44157561Simp/*	session cache files.
45157561Simp/*
46157561Simp/*	With Postfix version 2.5 and later, the \fBtlsmgr\fR(8) no
47157561Simp/*	longer uses root privileges when opening cache files. These
48157561Simp/*	files should now be stored under the Postfix-owned
49157561Simp/*	\fBdata_directory\fR.  As a migration aid, an attempt to
50155324Simp/*	open a cache file under a non-Postfix directory is redirected
51155324Simp/*	to the Postfix-owned \fBdata_directory\fR, and a warning
52155324Simp/*	is logged.
53155324Simp/* DIAGNOSTICS
54155324Simp/*	Problems and transactions are logged to the syslog daemon.
55155324Simp/* BUGS
56155324Simp/*	There is no automatic means to limit the number of entries in the
57155324Simp/*	TLS session caches and/or the size of the TLS cache files.
58155324Simp/* CONFIGURATION PARAMETERS
59155324Simp/* .ad
60155324Simp/* .fi
61155324Simp/*	Changes to \fBmain.cf\fR are not picked up automatically,
62155324Simp/*	because \fBtlsmgr\fR(8) is a persistent processes.  Use the
63155324Simp/*	command "\fBpostfix reload\fR" after a configuration change.
64155324Simp/*
65155324Simp/*	The text below provides only a parameter summary. See
66155324Simp/*	\fBpostconf\fR(5) for more details including examples.
67155324Simp/* TLS SESSION CACHE
68155324Simp/* .ad
69155324Simp/* .fi
70155324Simp/* .IP "\fBlmtp_tls_loglevel (0)\fR"
71155324Simp/*	The LMTP-specific version of the smtp_tls_loglevel
72155324Simp/*	configuration parameter.
73155324Simp/* .IP "\fBlmtp_tls_session_cache_database (empty)\fR"
74155324Simp/*	The LMTP-specific version of the smtp_tls_session_cache_database
75155324Simp/*	configuration parameter.
76155324Simp/* .IP "\fBlmtp_tls_session_cache_timeout (3600s)\fR"
77155324Simp/*	The LMTP-specific version of the smtp_tls_session_cache_timeout
78155324Simp/*	configuration parameter.
79155324Simp/* .IP "\fBsmtp_tls_loglevel (0)\fR"
80155324Simp/*	Enable additional Postfix SMTP client logging of TLS activity.
81155324Simp/* .IP "\fBsmtp_tls_session_cache_database (empty)\fR"
82155324Simp/*	Name of the file containing the optional Postfix SMTP client
83155324Simp/*	TLS session cache.
84155324Simp/* .IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
85155324Simp/*	The expiration time of Postfix SMTP client TLS session cache
86155324Simp/*	information.
87155324Simp/* .IP "\fBsmtpd_tls_loglevel (0)\fR"
88155324Simp/*	Enable additional Postfix SMTP server logging of TLS activity.
89155324Simp/* .IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
90155324Simp/*	Name of the file containing the optional Postfix SMTP server
91155324Simp/*	TLS session cache.
92155324Simp/* .IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
93155324Simp/*	The expiration time of Postfix SMTP server TLS session cache
94155324Simp/*	information.
95157561Simp/* PSEUDO RANDOM NUMBER GENERATOR
96157561Simp/* .ad
97157561Simp/* .fi
98157561Simp/* .IP "\fBtls_random_source (see 'postconf -d' output)\fR"
99157561Simp/*	The external entropy source for the in-memory \fBtlsmgr\fR(8) pseudo
100157561Simp/*	random number generator (PRNG) pool.
101157561Simp/* .IP "\fBtls_random_bytes (32)\fR"
102157561Simp/*	The number of bytes that \fBtlsmgr\fR(8) reads from $tls_random_source
103157561Simp/*	when (re)seeding the in-memory pseudo random number generator (PRNG)
104157561Simp/*	pool.
105157561Simp/* .IP "\fBtls_random_exchange_name (see 'postconf -d' output)\fR"
106157561Simp/*	Name of the pseudo random number generator (PRNG) state file
107157561Simp/*	that is maintained by \fBtlsmgr\fR(8).
108157561Simp/* .IP "\fBtls_random_prng_update_period (3600s)\fR"
109157561Simp/*	The time between attempts by \fBtlsmgr\fR(8) to save the state of
110157561Simp/*	the pseudo random number generator (PRNG) to the file specified
111157561Simp/*	with $tls_random_exchange_name.
112157561Simp/* .IP "\fBtls_random_reseed_period (3600s)\fR"
113157561Simp/*	The maximal time between attempts by \fBtlsmgr\fR(8) to re-seed the
114157561Simp/*	in-memory pseudo random number generator (PRNG) pool from external
115157561Simp/*	sources.
116157561Simp/* MISCELLANEOUS CONTROLS
117155324Simp/* .ad
118155324Simp/* .fi
119155324Simp/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
120155324Simp/*	The default location of the Postfix main.cf and master.cf
121155324Simp/*	configuration files.
122155324Simp/* .IP "\fBdata_directory (see 'postconf -d' output)\fR"
123155324Simp/*	The directory with Postfix-writable data files (for example:
124155324Simp/*	caches, pseudo-random numbers).
125155324Simp/* .IP "\fBdaemon_timeout (18000s)\fR"
126155324Simp/*	How much time a Postfix daemon process may take to handle a
127155324Simp/*	request before it is terminated by a built-in watchdog timer.
128155324Simp/* .IP "\fBprocess_id (read-only)\fR"
129155324Simp/*	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/* AUTHOR(S)
157/*	Lutz Jaenicke
158/*	BTU Cottbus
159/*	Allgemeine Elektrotechnik
160/*	Universitaetsplatz 3-4
161/*	D-03044 Cottbus, Germany
162/*
163/*	Adapted by:
164/*	Wietse Venema
165/*	IBM T.J. Watson Research
166/*	P.O. Box 704
167/*	Yorktown Heights, NY 10598, USA
168/*--*/
169
170/* System library. */
171
172#include <sys_defs.h>
173#include <sys/stat.h>
174#include <stdlib.h>
175#include <unistd.h>
176#include <ctype.h>
177#include <errno.h>
178#include <string.h>
179#include <sys/time.h>			/* gettimeofday, not POSIX */
180#include <limits.h>
181
182#ifndef UCHAR_MAX
183#define UCHAR_MAX 0xff
184#endif
185
186/* OpenSSL library. */
187
188#ifdef USE_TLS
189#include <openssl/rand.h>		/* For the PRNG */
190#endif
191
192/* Utility library. */
193
194#include <msg.h>
195#include <events.h>
196#include <stringops.h>
197#include <mymalloc.h>
198#include <iostuff.h>
199#include <vstream.h>
200#include <vstring.h>
201#include <vstring_vstream.h>
202#include <attr.h>
203#include <set_eugid.h>
204#include <htable.h>
205
206/* Global library. */
207
208#include <mail_conf.h>
209#include <mail_params.h>
210#include <mail_version.h>
211#include <tls_mgr.h>
212#include <mail_proto.h>
213#include <data_redirect.h>
214
215/* Master process interface. */
216
217#include <master_proto.h>
218#include <mail_server.h>
219
220/* TLS library. */
221
222#ifdef USE_TLS
223#include <tls.h>			/* TLS_MGR_SCACHE_<type> */
224#include <tls_prng.h>
225#include <tls_scache.h>
226
227/* Application-specific. */
228
229 /*
230  * Tunables.
231  */
232char   *var_tls_rand_source;
233int     var_tls_rand_bytes;
234int     var_tls_reseed_period;
235int     var_tls_prng_exch_period;
236int     var_smtpd_tls_loglevel;
237char   *var_smtpd_tls_scache_db;
238int     var_smtpd_tls_scache_timeout;
239int     var_smtp_tls_loglevel;
240char   *var_smtp_tls_scache_db;
241int     var_smtp_tls_scache_timeout;
242int     var_lmtp_tls_loglevel;
243char   *var_lmtp_tls_scache_db;
244int     var_lmtp_tls_scache_timeout;
245char   *var_tls_rand_exch_name;
246
247 /*
248  * Bound the time that we are willing to wait for an I/O operation. This
249  * produces better error messages than waiting until the watchdog timer
250  * kills the process.
251  */
252#define TLS_MGR_TIMEOUT	10
253
254 /*
255  * State for updating the PRNG exchange file.
256  */
257static TLS_PRNG_SRC *rand_exch;
258
259 /*
260  * State for seeding the internal PRNG from external source.
261  */
262static TLS_PRNG_SRC *rand_source_dev;
263static TLS_PRNG_SRC *rand_source_egd;
264static TLS_PRNG_SRC *rand_source_file;
265
266 /*
267  * The external entropy source type is encoded in the source name. The
268  * obvious alternative is to have separate configuration parameters per
269  * source type, so that one process can query multiple external sources.
270  */
271#define DEV_PREF "dev:"
272#define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
273#define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
274
275#define EGD_PREF "egd:"
276#define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
277#define EGD_PATH(egd) ((egd) + EGD_PREF_LEN)
278
279 /*
280  * State for TLS session caches.
281  */
282typedef struct {
283    char   *cache_label;		/* cache short-hand name */
284    TLS_SCACHE *cache_info;		/* cache handle */
285    int     cache_active;		/* cache status */
286    char  **cache_db;			/* main.cf parameter value */
287    int    *cache_loglevel;		/* main.cf parameter value */
288    int    *cache_timeout;		/* main.cf parameter value */
289} TLSMGR_SCACHE;
290
291TLSMGR_SCACHE cache_table[] = {
292    TLS_MGR_SCACHE_SMTPD, 0, 0, &var_smtpd_tls_scache_db,
293    &var_smtpd_tls_loglevel, &var_smtpd_tls_scache_timeout,
294    TLS_MGR_SCACHE_SMTP, 0, 0, &var_smtp_tls_scache_db,
295    &var_smtp_tls_loglevel, &var_smtp_tls_scache_timeout,
296    TLS_MGR_SCACHE_LMTP, 0, 0, &var_lmtp_tls_scache_db,
297    &var_lmtp_tls_loglevel, &var_lmtp_tls_scache_timeout,
298    0,
299};
300
301 /*
302  * SLMs.
303  */
304#define STR(x)		vstring_str(x)
305#define LEN(x)		VSTRING_LEN(x)
306#define STREQ(x, y)	(strcmp((x), (y)) == 0)
307
308/* tlsmgr_prng_exch_event - update PRNG exchange file */
309
310static void tlsmgr_prng_exch_event(int unused_event, char *dummy)
311{
312    const char *myname = "tlsmgr_prng_exch_event";
313    unsigned char randbyte;
314    int     next_period;
315    struct stat st;
316
317    if (msg_verbose)
318	msg_info("%s: update PRNG exchange file", myname);
319
320    /*
321     * Sanity check. If the PRNG exchange file was removed, there is no point
322     * updating it further. Restart the process and update the new file.
323     */
324    if (fstat(rand_exch->fd, &st) < 0)
325	msg_fatal("cannot fstat() the PRNG exchange file: %m");
326    if (st.st_nlink == 0) {
327	msg_warn("PRNG exchange file was removed -- exiting to reopen");
328	sleep(1);
329	exit(0);
330    }
331    tls_prng_exch_update(rand_exch);
332
333    /*
334     * Make prediction difficult for outsiders and calculate the time for the
335     * next execution randomly.
336     */
337    RAND_bytes(&randbyte, 1);
338    next_period = (var_tls_prng_exch_period * randbyte) / UCHAR_MAX;
339    event_request_timer(tlsmgr_prng_exch_event, dummy, next_period);
340}
341
342/* tlsmgr_reseed_event - re-seed the internal PRNG pool */
343
344static void tlsmgr_reseed_event(int unused_event, char *dummy)
345{
346    int     next_period;
347    unsigned char randbyte;
348    int     must_exit = 0;
349
350    /*
351     * Reseed the internal PRNG from external source. Errors are recoverable.
352     * We simply restart and reconnect without making a fuss. This is OK
353     * because we do require that exchange file updates succeed. The exchange
354     * file is the only entropy source that really matters in the long term.
355     *
356     * If the administrator specifies an external randomness source that we
357     * could not open upon start-up, restart to see if we can open it now
358     * (and log a nagging warning if we can't).
359     */
360    if (*var_tls_rand_source) {
361
362	/*
363	 * Source is a random device.
364	 */
365	if (rand_source_dev) {
366	    if (tls_prng_dev_read(rand_source_dev, var_tls_rand_bytes) <= 0) {
367		msg_info("cannot read from entropy device %s: %m -- "
368			 "exiting to reopen", DEV_PATH(var_tls_rand_source));
369		must_exit = 1;
370	    }
371	}
372
373	/*
374	 * Source is an EGD compatible socket.
375	 */
376	else if (rand_source_egd) {
377	    if (tls_prng_egd_read(rand_source_egd, var_tls_rand_bytes) <= 0) {
378		msg_info("lost connection to EGD server %s -- "
379		     "exiting to reconnect", EGD_PATH(var_tls_rand_source));
380		must_exit = 1;
381	    }
382	}
383
384	/*
385	 * Source is a regular file. Read the content once and close the
386	 * file.
387	 */
388	else if (rand_source_file) {
389	    if (tls_prng_file_read(rand_source_file, var_tls_rand_bytes) <= 0)
390		msg_warn("cannot read from entropy file %s: %m",
391			 var_tls_rand_source);
392	    tls_prng_file_close(rand_source_file);
393	    rand_source_file = 0;
394	    var_tls_rand_source[0] = 0;
395	}
396
397	/*
398	 * Could not open the external source upon start-up. See if we can
399	 * open it this time. Save PRNG state before we exit.
400	 */
401	else {
402	    msg_info("exiting to reopen external entropy source %s",
403		     var_tls_rand_source);
404	    must_exit = 1;
405	}
406    }
407
408    /*
409     * Save PRNG state in case we must exit.
410     */
411    if (must_exit) {
412	if (rand_exch)
413	    tls_prng_exch_update(rand_exch);
414	sleep(1);
415	exit(0);
416    }
417
418    /*
419     * Make prediction difficult for outsiders and calculate the time for the
420     * next execution randomly.
421     */
422    RAND_bytes(&randbyte, 1);
423    next_period = (var_tls_reseed_period * randbyte) / UCHAR_MAX;
424    event_request_timer(tlsmgr_reseed_event, dummy, next_period);
425}
426
427/* tlsmgr_cache_run_event - start TLS session cache scan */
428
429static void tlsmgr_cache_run_event(int unused_event, char *ctx)
430{
431    const char *myname = "tlsmgr_cache_run_event";
432    TLSMGR_SCACHE *cache = (TLSMGR_SCACHE *) ctx;
433
434    /*
435     * This routine runs when it is time for another TLS session cache scan.
436     * Make sure this routine gets called again in the future.
437     *
438     * Don't start a new scan when the timer goes off while cache cleanup is
439     * still in progress.
440     */
441    if (cache->cache_info->verbose)
442	msg_info("%s: start TLS %s session cache cleanup",
443		 myname, cache->cache_label);
444
445    if (cache->cache_active == 0)
446	cache->cache_active =
447	    tls_scache_sequence(cache->cache_info, DICT_SEQ_FUN_FIRST,
448				TLS_SCACHE_SEQUENCE_NOTHING);
449
450    event_request_timer(tlsmgr_cache_run_event, (char *) cache,
451			cache->cache_info->timeout);
452}
453
454/* tlsmgr_loop - TLS manager main loop */
455
456static int tlsmgr_loop(char *unused_name, char **unused_argv)
457{
458    struct timeval tv;
459    int     active = 0;
460    TLSMGR_SCACHE *ent;
461
462    /*
463     * Update the PRNG pool with the time of day. We do it here after every
464     * event (including internal timer events and external client request
465     * events), instead of doing it in individual event call-back routines.
466     */
467    GETTIMEOFDAY(&tv);
468    RAND_seed(&tv, sizeof(struct timeval));
469
470    /*
471     * This routine runs as part of the event handling loop, after the event
472     * manager has delivered a timer or I/O event, or after it has waited for
473     * a specified amount of time. The result value of tlsmgr_loop()
474     * specifies how long the event manager should wait for the next event.
475     *
476     * We use this loop to interleave TLS session cache cleanup with other
477     * activity. Interleaved processing is needed when we use a client-server
478     * protocol for entropy and session state exchange with smtp(8) and
479     * smtpd(8) processes.
480     */
481#define DONT_WAIT	0
482#define WAIT_FOR_EVENT	(-1)
483
484    for (ent = cache_table; ent->cache_label; ++ent) {
485	if (ent->cache_info && ent->cache_active)
486	    active |= ent->cache_active =
487		tls_scache_sequence(ent->cache_info, DICT_SEQ_FUN_NEXT,
488				    TLS_SCACHE_SEQUENCE_NOTHING);
489    }
490
491    return (active ? DONT_WAIT : WAIT_FOR_EVENT);
492}
493
494/* tlsmgr_request_receive - receive request */
495
496static int tlsmgr_request_receive(VSTREAM *client_stream, VSTRING *request)
497{
498    int     count;
499
500    /*
501     * Kluge: choose the protocol depending on the request size.
502     */
503    if (read_wait(vstream_fileno(client_stream), var_ipc_timeout) < 0) {
504	msg_warn("timeout while waiting for data from %s",
505		 VSTREAM_PATH(client_stream));
506	return (-1);
507    }
508    if ((count = peekfd(vstream_fileno(client_stream))) < 0) {
509	msg_warn("cannot examine read buffer of %s: %m",
510		 VSTREAM_PATH(client_stream));
511	return (-1);
512    }
513
514    /*
515     * Short request: master trigger. Use the string+null protocol.
516     */
517    if (count <= 2) {
518	if (vstring_get_null(request, client_stream) == VSTREAM_EOF) {
519	    msg_warn("end-of-input while reading request from %s: %m",
520		     VSTREAM_PATH(client_stream));
521	    return (-1);
522	}
523    }
524
525    /*
526     * Long request: real tlsmgr client. Use the attribute list protocol.
527     */
528    else {
529	if (attr_scan(client_stream,
530		      ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
531		      ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, request,
532		      ATTR_TYPE_END) != 1) {
533	    return (-1);
534	}
535    }
536    return (0);
537}
538
539/* tlsmgr_service - respond to external request */
540
541static void tlsmgr_service(VSTREAM *client_stream, char *unused_service,
542			           char **argv)
543{
544    static VSTRING *request = 0;
545    static VSTRING *cache_type = 0;
546    static VSTRING *cache_id = 0;
547    static VSTRING *buffer = 0;
548    int     len;
549    static char wakeup[] = {		/* master wakeup request */
550	TRIGGER_REQ_WAKEUP,
551	0,
552    };
553    TLSMGR_SCACHE *ent;
554    int     status = TLS_MGR_STAT_FAIL;
555
556    /*
557     * Sanity check. This service takes no command-line arguments.
558     */
559    if (argv[0])
560	msg_fatal("unexpected command-line argument: %s", argv[0]);
561
562    /*
563     * Initialize. We're select threaded, so we can use static buffers.
564     */
565    if (request == 0) {
566	request = vstring_alloc(10);
567	cache_type = vstring_alloc(10);
568	cache_id = vstring_alloc(10);
569	buffer = vstring_alloc(10);
570    }
571
572    /*
573     * This routine runs whenever a client connects to the socket dedicated
574     * to the tlsmgr service (including wake up events sent by the master).
575     * All connection-management stuff is handled by the common code in
576     * multi_server.c.
577     */
578    if (tlsmgr_request_receive(client_stream, request) == 0) {
579
580	/*
581	 * Load session from cache.
582	 */
583	if (STREQ(STR(request), TLS_MGR_REQ_LOOKUP)) {
584	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
585			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
586			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
587			  ATTR_TYPE_END) == 2) {
588		for (ent = cache_table; ent->cache_label; ++ent)
589		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
590			break;
591		if (ent->cache_label == 0) {
592		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
593			     STR(cache_type), TLS_MGR_REQ_LOOKUP);
594		    VSTRING_RESET(buffer);
595		} else if (ent->cache_info == 0) {
596
597		    /*
598		     * Cache type valid, but not enabled
599		     */
600		    VSTRING_RESET(buffer);
601		} else {
602		    status = tls_scache_lookup(ent->cache_info,
603					       STR(cache_id), buffer) ?
604			TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
605		}
606	    }
607	    attr_print(client_stream, ATTR_FLAG_NONE,
608		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
609		       ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION,
610		       LEN(buffer), STR(buffer),
611		       ATTR_TYPE_END);
612	}
613
614	/*
615	 * Save session to cache.
616	 */
617	else if (STREQ(STR(request), TLS_MGR_REQ_UPDATE)) {
618	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
619			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
620			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
621			  ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buffer,
622			  ATTR_TYPE_END) == 3) {
623		for (ent = cache_table; ent->cache_label; ++ent)
624		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
625			break;
626		if (ent->cache_label == 0) {
627		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
628			     STR(cache_type), TLS_MGR_REQ_UPDATE);
629		} else if (ent->cache_info != 0) {
630		    status =
631			tls_scache_update(ent->cache_info, STR(cache_id),
632					  STR(buffer), LEN(buffer)) ?
633			TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
634		}
635	    }
636	    attr_print(client_stream, ATTR_FLAG_NONE,
637		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
638		       ATTR_TYPE_END);
639	}
640
641	/*
642	 * Delete session from cache.
643	 */
644	else if (STREQ(STR(request), TLS_MGR_REQ_DELETE)) {
645	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
646			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
647			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
648			  ATTR_TYPE_END) == 2) {
649		for (ent = cache_table; ent->cache_label; ++ent)
650		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
651			break;
652		if (ent->cache_label == 0) {
653		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
654			     STR(cache_type), TLS_MGR_REQ_DELETE);
655		} else if (ent->cache_info != 0) {
656		    status = tls_scache_delete(ent->cache_info,
657					       STR(cache_id)) ?
658			TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
659		}
660	    }
661	    attr_print(client_stream, ATTR_FLAG_NONE,
662		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
663		       ATTR_TYPE_END);
664	}
665
666	/*
667	 * Entropy request.
668	 */
669	else if (STREQ(STR(request), TLS_MGR_REQ_SEED)) {
670	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
671			  ATTR_TYPE_INT, TLS_MGR_ATTR_SIZE, &len,
672			  ATTR_TYPE_END) == 1) {
673		VSTRING_RESET(buffer);
674		if (len <= 0 || len > 255) {
675		    msg_warn("bogus seed length \"%d\" in \"%s\" request",
676			     len, TLS_MGR_REQ_SEED);
677		} else {
678		    VSTRING_SPACE(buffer, len);
679		    RAND_bytes((unsigned char *) STR(buffer), len);
680		    VSTRING_AT_OFFSET(buffer, len);	/* XXX not part of the
681							 * official interface */
682		    status = TLS_MGR_STAT_OK;
683		}
684	    }
685	    attr_print(client_stream, ATTR_FLAG_NONE,
686		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
687		       ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED,
688		       LEN(buffer), STR(buffer),
689		       ATTR_TYPE_END);
690	}
691
692	/*
693	 * Caching policy request.
694	 */
695	else if (STREQ(STR(request), TLS_MGR_REQ_POLICY)) {
696	    int     cachable = 0;
697
698	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
699			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
700			  ATTR_TYPE_END) == 1) {
701		for (ent = cache_table; ent->cache_label; ++ent)
702		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
703			break;
704		if (ent->cache_label == 0) {
705		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
706			     STR(cache_type), TLS_MGR_REQ_POLICY);
707		} else {
708		    cachable = (ent->cache_info != 0) ? 1 : 0;
709		    status = TLS_MGR_STAT_OK;
710		}
711	    }
712	    attr_print(client_stream, ATTR_FLAG_NONE,
713		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
714		       ATTR_TYPE_INT, TLS_MGR_ATTR_CACHABLE, cachable,
715		       ATTR_TYPE_END);
716	}
717
718	/*
719	 * Master trigger. Normally, these triggers arrive only after some
720	 * other process requested the tlsmgr's service. The purpose is to
721	 * restart the tlsmgr after it aborted due to a fatal run-time error,
722	 * so that it can continue its housekeeping even while nothing is
723	 * using TLS.
724	 *
725	 * XXX Which begs the question, if TLS isn't used often, do we need a
726	 * tlsmgr background process? It could terminate when the session
727	 * caches are empty.
728	 */
729	else if (STREQ(STR(request), wakeup)) {
730	    if (msg_verbose)
731		msg_info("received master trigger");
732	    multi_server_disconnect(client_stream);
733	    return;				/* NOT: vstream_fflush */
734	}
735    }
736
737    /*
738     * Protocol error.
739     */
740    else {
741	attr_print(client_stream, ATTR_FLAG_NONE,
742		   ATTR_TYPE_INT, MAIL_ATTR_STATUS, TLS_MGR_STAT_FAIL,
743		   ATTR_TYPE_END);
744    }
745    vstream_fflush(client_stream);
746}
747
748/* tlsmgr_pre_init - pre-jail initialization */
749
750static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
751{
752    char   *path;
753    struct timeval tv;
754    TLSMGR_SCACHE *ent;
755    VSTRING *redirect;
756    HTABLE *dup_filter;
757    const char *dup_label;
758
759    /*
760     * If nothing else works then at least this will get us a few bits of
761     * entropy.
762     *
763     * XXX This is our first call into the OpenSSL library. We should find out
764     * if this can be moved to the post-jail initialization phase, without
765     * breaking compatibility with existing installations.
766     */
767    GETTIMEOFDAY(&tv);
768    tv.tv_sec ^= getpid();
769    RAND_seed(&tv, sizeof(struct timeval));
770
771    /*
772     * Open the external entropy source. We will not be able to open it again
773     * after we are sent to chroot jail, so we keep it open. Errors are not
774     * fatal. The exchange file (see below) is the only entropy source that
775     * really matters in the long run.
776     *
777     * Security note: we open the entropy source while privileged, but we don't
778     * access the source until after we release privileges. This way, none of
779     * the OpenSSL code gets to execute while we are privileged.
780     */
781    if (*var_tls_rand_source) {
782
783	/*
784	 * Source is a random device.
785	 */
786	if (!strncmp(var_tls_rand_source, DEV_PREF, DEV_PREF_LEN)) {
787	    path = DEV_PATH(var_tls_rand_source);
788	    rand_source_dev = tls_prng_dev_open(path, TLS_MGR_TIMEOUT);
789	    if (rand_source_dev == 0)
790		msg_warn("cannot open entropy device %s: %m", path);
791	}
792
793	/*
794	 * Source is an EGD compatible socket.
795	 */
796	else if (!strncmp(var_tls_rand_source, EGD_PREF, EGD_PREF_LEN)) {
797	    path = EGD_PATH(var_tls_rand_source);
798	    rand_source_egd = tls_prng_egd_open(path, TLS_MGR_TIMEOUT);
799	    if (rand_source_egd == 0)
800		msg_warn("cannot connect to EGD server %s: %m", path);
801	}
802
803	/*
804	 * Source is regular file. We read this only once.
805	 */
806	else {
807	    rand_source_file =
808		tls_prng_file_open(var_tls_rand_source, TLS_MGR_TIMEOUT);
809	}
810    } else {
811	msg_warn("no entropy source specified with parameter %s",
812		 VAR_TLS_RAND_SOURCE);
813	msg_warn("encryption keys etc. may be predictable");
814    }
815
816    /*
817     * Security: don't create root-owned files that contain untrusted data.
818     * And don't create Postfix-owned files in root-owned directories,
819     * either. We want a correct relationship between (file/directory)
820     * ownership and (file/directory) content.
821     */
822    SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
823    redirect = vstring_alloc(100);
824
825    /*
826     * Open the PRNG exchange file before going to jail, but don't use root
827     * privileges. Start the exchange file read/update pseudo thread after
828     * dropping privileges.
829     */
830    if (*var_tls_rand_exch_name) {
831	rand_exch =
832	    tls_prng_exch_open(data_redirect_file(redirect,
833						  var_tls_rand_exch_name));
834	if (rand_exch == 0)
835	    msg_fatal("cannot open PRNG exchange file %s: %m",
836		      var_tls_rand_exch_name);
837    }
838
839    /*
840     * Open the session cache files and discard old information before going
841     * to jail, but don't use root privilege. Start the cache maintenance
842     * pseudo threads after dropping privileges.
843     */
844    dup_filter = htable_create(sizeof(cache_table) / sizeof(cache_table[0]));
845    for (ent = cache_table; ent->cache_label; ++ent) {
846	if (**ent->cache_db) {
847	    if ((dup_label = htable_find(dup_filter, *ent->cache_db)) != 0)
848		msg_fatal("do not use the same TLS cache file %s for %s and %s",
849			  *ent->cache_db, dup_label, ent->cache_label);
850	    htable_enter(dup_filter, *ent->cache_db, ent->cache_label);
851	    ent->cache_info =
852		tls_scache_open(data_redirect_map(redirect, *ent->cache_db),
853				ent->cache_label,
854				*ent->cache_loglevel >= 2,
855				*ent->cache_timeout);
856	}
857    }
858    htable_free(dup_filter, (void (*) (char *)) 0);
859
860    /*
861     * Clean up and restore privilege.
862     */
863    vstring_free(redirect);
864    RESTORE_SAVED_EUGID();
865}
866
867/* tlsmgr_post_init - post-jail initialization */
868
869static void tlsmgr_post_init(char *unused_name, char **unused_argv)
870{
871    TLSMGR_SCACHE *ent;
872
873#define NULL_EVENT	(0)
874#define NULL_CONTEXT	((char *) 0)
875
876    /*
877     * This routine runs after the skeleton code has entered the chroot jail,
878     * but before any client requests are serviced. Prevent automatic process
879     * suicide after a limited number of client requests or after a limited
880     * amount of idle time.
881     */
882    var_use_limit = 0;
883    var_idle_limit = 0;
884
885    /*
886     * Start the internal PRNG re-seeding pseudo thread first.
887     */
888    if (*var_tls_rand_source) {
889	if (var_tls_reseed_period > INT_MAX / UCHAR_MAX)
890	    var_tls_reseed_period = INT_MAX / UCHAR_MAX;
891	tlsmgr_reseed_event(NULL_EVENT, NULL_CONTEXT);
892    }
893
894    /*
895     * Start the exchange file read/update pseudo thread.
896     */
897    if (*var_tls_rand_exch_name) {
898	if (var_tls_prng_exch_period > INT_MAX / UCHAR_MAX)
899	    var_tls_prng_exch_period = INT_MAX / UCHAR_MAX;
900	tlsmgr_prng_exch_event(NULL_EVENT, NULL_CONTEXT);
901    }
902
903    /*
904     * Start the cache maintenance pseudo threads last. Strictly speaking
905     * there is nothing to clean up after we truncate the database to zero
906     * length, but early cleanup makes verbose logging more informative (we
907     * get positive confirmation that the cleanup threads are running).
908     */
909    for (ent = cache_table; ent->cache_label; ++ent)
910	if (ent->cache_info)
911	    tlsmgr_cache_run_event(NULL_EVENT, (char *) ent);
912}
913
914/* tlsmgr_before_exit - save PRNG state before exit */
915
916static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
917{
918
919    /*
920     * Save state before we exit after "postfix reload".
921     */
922    if (rand_exch)
923	tls_prng_exch_update(rand_exch);
924}
925
926MAIL_VERSION_STAMP_DECLARE;
927
928/* main - the main program */
929
930int     main(int argc, char **argv)
931{
932    static const CONFIG_STR_TABLE str_table[] = {
933	VAR_TLS_RAND_SOURCE, DEF_TLS_RAND_SOURCE, &var_tls_rand_source, 0, 0,
934	VAR_TLS_RAND_EXCH_NAME, DEF_TLS_RAND_EXCH_NAME, &var_tls_rand_exch_name, 0, 0,
935	VAR_SMTPD_TLS_SCACHE_DB, DEF_SMTPD_TLS_SCACHE_DB, &var_smtpd_tls_scache_db, 0, 0,
936	VAR_SMTP_TLS_SCACHE_DB, DEF_SMTP_TLS_SCACHE_DB, &var_smtp_tls_scache_db, 0, 0,
937	VAR_LMTP_TLS_SCACHE_DB, DEF_LMTP_TLS_SCACHE_DB, &var_lmtp_tls_scache_db, 0, 0,
938	0,
939    };
940    static const CONFIG_TIME_TABLE time_table[] = {
941	VAR_TLS_RESEED_PERIOD, DEF_TLS_RESEED_PERIOD, &var_tls_reseed_period, 1, 0,
942	VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_exch_period, 1, 0,
943	VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, 0,
944	VAR_SMTP_TLS_SCACHTIME, DEF_SMTP_TLS_SCACHTIME, &var_smtp_tls_scache_timeout, 0, 0,
945	VAR_LMTP_TLS_SCACHTIME, DEF_LMTP_TLS_SCACHTIME, &var_lmtp_tls_scache_timeout, 0, 0,
946	0,
947    };
948    static const CONFIG_INT_TABLE int_table[] = {
949	VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 1, 0,
950	VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
951	VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0,
952	VAR_LMTP_TLS_LOGLEVEL, DEF_LMTP_TLS_LOGLEVEL, &var_lmtp_tls_loglevel, 0, 0,
953	0,
954    };
955
956    /*
957     * Fingerprint executables and core dumps.
958     */
959    MAIL_VERSION_STAMP_ALLOCATE;
960
961    /*
962     * Use the multi service skeleton, and require that no-one else is
963     * monitoring our service port while this process runs.
964     */
965    multi_server_main(argc, argv, tlsmgr_service,
966		      MAIL_SERVER_TIME_TABLE, time_table,
967		      MAIL_SERVER_INT_TABLE, int_table,
968		      MAIL_SERVER_STR_TABLE, str_table,
969		      MAIL_SERVER_PRE_INIT, tlsmgr_pre_init,
970		      MAIL_SERVER_POST_INIT, tlsmgr_post_init,
971		      MAIL_SERVER_EXIT, tlsmgr_before_exit,
972		      MAIL_SERVER_LOOP, tlsmgr_loop,
973		      MAIL_SERVER_SOLITARY,
974		      0);
975}
976
977#else
978
979/* tlsmgr_service - respond to external trigger(s), non-TLS version */
980
981static void tlsmgr_service(VSTREAM *unused_stream, char *unused_service,
982			           char **unused_argv)
983{
984    msg_info("TLS support is not compiled in -- exiting");
985}
986
987/* main - the main program, non-TLS version */
988
989int     main(int argc, char **argv)
990{
991
992    /*
993     * 200411 We can't simply use msg_fatal() here, because the logging
994     * hasn't been initialized. The text would disappear because stderr is
995     * redirected to /dev/null.
996     *
997     * We invoke multi_server_main() to complete program initialization
998     * (including logging) and then invoke the tlsmgr_service() routine to
999     * log the message that says why this program will not run.
1000     */
1001    multi_server_main(argc, argv, tlsmgr_service,
1002		      0);
1003}
1004
1005#endif
1006