xref: /netbsd-src/external/ibm-public/postfix/dist/src/tlsmgr/tlsmgr.c (revision 4391d5e9d4f291db41e3b3ba26a01b5e51364aae)
1 /*	$NetBSD: tlsmgr.c,v 1.1.1.2 2013/01/02 18:59:10 tron 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 /* 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 #include <warn_stat.h>
206 
207 /* Global library. */
208 
209 #include <mail_conf.h>
210 #include <mail_params.h>
211 #include <mail_version.h>
212 #include <tls_mgr.h>
213 #include <mail_proto.h>
214 #include <data_redirect.h>
215 
216 /* Master process interface. */
217 
218 #include <master_proto.h>
219 #include <mail_server.h>
220 
221 /* TLS library. */
222 
223 #ifdef USE_TLS
224 #define TLS_INTERNAL
225 #include <tls.h>			/* TLS_MGR_SCACHE_<type> */
226 #include <tls_prng.h>
227 #include <tls_scache.h>
228 
229 /* Application-specific. */
230 
231  /*
232   * Tunables.
233   */
234 char   *var_tls_rand_source;
235 int     var_tls_rand_bytes;
236 int     var_tls_reseed_period;
237 int     var_tls_prng_exch_period;
238 char   *var_smtpd_tls_loglevel;
239 char   *var_smtpd_tls_scache_db;
240 int     var_smtpd_tls_scache_timeout;
241 char   *var_smtp_tls_loglevel;
242 char   *var_smtp_tls_scache_db;
243 int     var_smtp_tls_scache_timeout;
244 char   *var_lmtp_tls_loglevel;
245 char   *var_lmtp_tls_scache_db;
246 int     var_lmtp_tls_scache_timeout;
247 char   *var_tls_rand_exch_name;
248 
249  /*
250   * Bound the time that we are willing to wait for an I/O operation. This
251   * produces better error messages than waiting until the watchdog timer
252   * kills the process.
253   */
254 #define TLS_MGR_TIMEOUT	10
255 
256  /*
257   * State for updating the PRNG exchange file.
258   */
259 static TLS_PRNG_SRC *rand_exch;
260 
261  /*
262   * State for seeding the internal PRNG from external source.
263   */
264 static TLS_PRNG_SRC *rand_source_dev;
265 static TLS_PRNG_SRC *rand_source_egd;
266 static TLS_PRNG_SRC *rand_source_file;
267 
268  /*
269   * The external entropy source type is encoded in the source name. The
270   * obvious alternative is to have separate configuration parameters per
271   * source type, so that one process can query multiple external sources.
272   */
273 #define DEV_PREF "dev:"
274 #define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
275 #define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
276 
277 #define EGD_PREF "egd:"
278 #define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
279 #define EGD_PATH(egd) ((egd) + EGD_PREF_LEN)
280 
281  /*
282   * State for TLS session caches.
283   */
284 typedef struct {
285     char   *cache_label;		/* cache short-hand name */
286     TLS_SCACHE *cache_info;		/* cache handle */
287     int     cache_active;		/* cache status */
288     char  **cache_db;			/* main.cf parameter value */
289     const char *log_param;		/* main.cf parameter name */
290     char  **log_level;			/* main.cf parameter value */
291     int    *cache_timeout;		/* main.cf parameter value */
292 } TLSMGR_SCACHE;
293 
294 TLSMGR_SCACHE cache_table[] = {
295     TLS_MGR_SCACHE_SMTPD, 0, 0, &var_smtpd_tls_scache_db,
296     VAR_SMTPD_TLS_LOGLEVEL,
297     &var_smtpd_tls_loglevel, &var_smtpd_tls_scache_timeout,
298     TLS_MGR_SCACHE_SMTP, 0, 0, &var_smtp_tls_scache_db,
299     VAR_SMTP_TLS_LOGLEVEL,
300     &var_smtp_tls_loglevel, &var_smtp_tls_scache_timeout,
301     TLS_MGR_SCACHE_LMTP, 0, 0, &var_lmtp_tls_scache_db,
302     VAR_LMTP_TLS_LOGLEVEL,
303     &var_lmtp_tls_loglevel, &var_lmtp_tls_scache_timeout,
304     0,
305 };
306 
307  /*
308   * SLMs.
309   */
310 #define STR(x)		vstring_str(x)
311 #define LEN(x)		VSTRING_LEN(x)
312 #define STREQ(x, y)	(strcmp((x), (y)) == 0)
313 
314 /* tlsmgr_prng_exch_event - update PRNG exchange file */
315 
316 static void tlsmgr_prng_exch_event(int unused_event, char *dummy)
317 {
318     const char *myname = "tlsmgr_prng_exch_event";
319     unsigned char randbyte;
320     int     next_period;
321     struct stat st;
322 
323     if (msg_verbose)
324 	msg_info("%s: update PRNG exchange file", myname);
325 
326     /*
327      * Sanity check. If the PRNG exchange file was removed, there is no point
328      * updating it further. Restart the process and update the new file.
329      */
330     if (fstat(rand_exch->fd, &st) < 0)
331 	msg_fatal("cannot fstat() the PRNG exchange file: %m");
332     if (st.st_nlink == 0) {
333 	msg_warn("PRNG exchange file was removed -- exiting to reopen");
334 	sleep(1);
335 	exit(0);
336     }
337     tls_prng_exch_update(rand_exch);
338 
339     /*
340      * Make prediction difficult for outsiders and calculate the time for the
341      * next execution randomly.
342      */
343     RAND_bytes(&randbyte, 1);
344     next_period = (var_tls_prng_exch_period * randbyte) / UCHAR_MAX;
345     event_request_timer(tlsmgr_prng_exch_event, dummy, next_period);
346 }
347 
348 /* tlsmgr_reseed_event - re-seed the internal PRNG pool */
349 
350 static void tlsmgr_reseed_event(int unused_event, char *dummy)
351 {
352     int     next_period;
353     unsigned char randbyte;
354     int     must_exit = 0;
355 
356     /*
357      * Reseed the internal PRNG from external source. Errors are recoverable.
358      * We simply restart and reconnect without making a fuss. This is OK
359      * because we do require that exchange file updates succeed. The exchange
360      * file is the only entropy source that really matters in the long term.
361      *
362      * If the administrator specifies an external randomness source that we
363      * could not open upon start-up, restart to see if we can open it now
364      * (and log a nagging warning if we can't).
365      */
366     if (*var_tls_rand_source) {
367 
368 	/*
369 	 * Source is a random device.
370 	 */
371 	if (rand_source_dev) {
372 	    if (tls_prng_dev_read(rand_source_dev, var_tls_rand_bytes) <= 0) {
373 		msg_info("cannot read from entropy device %s: %m -- "
374 			 "exiting to reopen", DEV_PATH(var_tls_rand_source));
375 		must_exit = 1;
376 	    }
377 	}
378 
379 	/*
380 	 * Source is an EGD compatible socket.
381 	 */
382 	else if (rand_source_egd) {
383 	    if (tls_prng_egd_read(rand_source_egd, var_tls_rand_bytes) <= 0) {
384 		msg_info("lost connection to EGD server %s -- "
385 		     "exiting to reconnect", EGD_PATH(var_tls_rand_source));
386 		must_exit = 1;
387 	    }
388 	}
389 
390 	/*
391 	 * Source is a regular file. Read the content once and close the
392 	 * file.
393 	 */
394 	else if (rand_source_file) {
395 	    if (tls_prng_file_read(rand_source_file, var_tls_rand_bytes) <= 0)
396 		msg_warn("cannot read from entropy file %s: %m",
397 			 var_tls_rand_source);
398 	    tls_prng_file_close(rand_source_file);
399 	    rand_source_file = 0;
400 	    var_tls_rand_source[0] = 0;
401 	}
402 
403 	/*
404 	 * Could not open the external source upon start-up. See if we can
405 	 * open it this time. Save PRNG state before we exit.
406 	 */
407 	else {
408 	    msg_info("exiting to reopen external entropy source %s",
409 		     var_tls_rand_source);
410 	    must_exit = 1;
411 	}
412     }
413 
414     /*
415      * Save PRNG state in case we must exit.
416      */
417     if (must_exit) {
418 	if (rand_exch)
419 	    tls_prng_exch_update(rand_exch);
420 	sleep(1);
421 	exit(0);
422     }
423 
424     /*
425      * Make prediction difficult for outsiders and calculate the time for the
426      * next execution randomly.
427      */
428     RAND_bytes(&randbyte, 1);
429     next_period = (var_tls_reseed_period * randbyte) / UCHAR_MAX;
430     event_request_timer(tlsmgr_reseed_event, dummy, next_period);
431 }
432 
433 /* tlsmgr_cache_run_event - start TLS session cache scan */
434 
435 static void tlsmgr_cache_run_event(int unused_event, char *ctx)
436 {
437     const char *myname = "tlsmgr_cache_run_event";
438     TLSMGR_SCACHE *cache = (TLSMGR_SCACHE *) ctx;
439 
440     /*
441      * This routine runs when it is time for another TLS session cache scan.
442      * Make sure this routine gets called again in the future.
443      *
444      * Don't start a new scan when the timer goes off while cache cleanup is
445      * still in progress.
446      */
447     if (cache->cache_info->verbose)
448 	msg_info("%s: start TLS %s session cache cleanup",
449 		 myname, cache->cache_label);
450 
451     if (cache->cache_active == 0)
452 	cache->cache_active =
453 	    tls_scache_sequence(cache->cache_info, DICT_SEQ_FUN_FIRST,
454 				TLS_SCACHE_SEQUENCE_NOTHING);
455 
456     event_request_timer(tlsmgr_cache_run_event, (char *) cache,
457 			cache->cache_info->timeout);
458 }
459 
460 /* tlsmgr_loop - TLS manager main loop */
461 
462 static int tlsmgr_loop(char *unused_name, char **unused_argv)
463 {
464     struct timeval tv;
465     int     active = 0;
466     TLSMGR_SCACHE *ent;
467 
468     /*
469      * Update the PRNG pool with the time of day. We do it here after every
470      * event (including internal timer events and external client request
471      * events), instead of doing it in individual event call-back routines.
472      */
473     GETTIMEOFDAY(&tv);
474     RAND_seed(&tv, sizeof(struct timeval));
475 
476     /*
477      * This routine runs as part of the event handling loop, after the event
478      * manager has delivered a timer or I/O event, or after it has waited for
479      * a specified amount of time. The result value of tlsmgr_loop()
480      * specifies how long the event manager should wait for the next event.
481      *
482      * We use this loop to interleave TLS session cache cleanup with other
483      * activity. Interleaved processing is needed when we use a client-server
484      * protocol for entropy and session state exchange with smtp(8) and
485      * smtpd(8) processes.
486      */
487 #define DONT_WAIT	0
488 #define WAIT_FOR_EVENT	(-1)
489 
490     for (ent = cache_table; ent->cache_label; ++ent) {
491 	if (ent->cache_info && ent->cache_active)
492 	    active |= ent->cache_active =
493 		tls_scache_sequence(ent->cache_info, DICT_SEQ_FUN_NEXT,
494 				    TLS_SCACHE_SEQUENCE_NOTHING);
495     }
496 
497     return (active ? DONT_WAIT : WAIT_FOR_EVENT);
498 }
499 
500 /* tlsmgr_request_receive - receive request */
501 
502 static int tlsmgr_request_receive(VSTREAM *client_stream, VSTRING *request)
503 {
504     int     count;
505 
506     /*
507      * Kluge: choose the protocol depending on the request size.
508      */
509     if (read_wait(vstream_fileno(client_stream), var_ipc_timeout) < 0) {
510 	msg_warn("timeout while waiting for data from %s",
511 		 VSTREAM_PATH(client_stream));
512 	return (-1);
513     }
514     if ((count = peekfd(vstream_fileno(client_stream))) < 0) {
515 	msg_warn("cannot examine read buffer of %s: %m",
516 		 VSTREAM_PATH(client_stream));
517 	return (-1);
518     }
519 
520     /*
521      * Short request: master trigger. Use the string+null protocol.
522      */
523     if (count <= 2) {
524 	if (vstring_get_null(request, client_stream) == VSTREAM_EOF) {
525 	    msg_warn("end-of-input while reading request from %s: %m",
526 		     VSTREAM_PATH(client_stream));
527 	    return (-1);
528 	}
529     }
530 
531     /*
532      * Long request: real tlsmgr client. Use the attribute list protocol.
533      */
534     else {
535 	if (attr_scan(client_stream,
536 		      ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
537 		      ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, request,
538 		      ATTR_TYPE_END) != 1) {
539 	    return (-1);
540 	}
541     }
542     return (0);
543 }
544 
545 /* tlsmgr_service - respond to external request */
546 
547 static void tlsmgr_service(VSTREAM *client_stream, char *unused_service,
548 			           char **argv)
549 {
550     static VSTRING *request = 0;
551     static VSTRING *cache_type = 0;
552     static VSTRING *cache_id = 0;
553     static VSTRING *buffer = 0;
554     int     len;
555     static char wakeup[] = {		/* master wakeup request */
556 	TRIGGER_REQ_WAKEUP,
557 	0,
558     };
559     TLSMGR_SCACHE *ent;
560     int     status = TLS_MGR_STAT_FAIL;
561 
562     /*
563      * Sanity check. This service takes no command-line arguments.
564      */
565     if (argv[0])
566 	msg_fatal("unexpected command-line argument: %s", argv[0]);
567 
568     /*
569      * Initialize. We're select threaded, so we can use static buffers.
570      */
571     if (request == 0) {
572 	request = vstring_alloc(10);
573 	cache_type = vstring_alloc(10);
574 	cache_id = vstring_alloc(10);
575 	buffer = vstring_alloc(10);
576     }
577 
578     /*
579      * This routine runs whenever a client connects to the socket dedicated
580      * to the tlsmgr service (including wake up events sent by the master).
581      * All connection-management stuff is handled by the common code in
582      * multi_server.c.
583      */
584     if (tlsmgr_request_receive(client_stream, request) == 0) {
585 
586 	/*
587 	 * Load session from cache.
588 	 */
589 	if (STREQ(STR(request), TLS_MGR_REQ_LOOKUP)) {
590 	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
591 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
592 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
593 			  ATTR_TYPE_END) == 2) {
594 		for (ent = cache_table; ent->cache_label; ++ent)
595 		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
596 			break;
597 		if (ent->cache_label == 0) {
598 		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
599 			     STR(cache_type), TLS_MGR_REQ_LOOKUP);
600 		    VSTRING_RESET(buffer);
601 		} else if (ent->cache_info == 0) {
602 
603 		    /*
604 		     * Cache type valid, but not enabled
605 		     */
606 		    VSTRING_RESET(buffer);
607 		} else {
608 		    status = tls_scache_lookup(ent->cache_info,
609 					       STR(cache_id), buffer) ?
610 			TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
611 		}
612 	    }
613 	    attr_print(client_stream, ATTR_FLAG_NONE,
614 		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
615 		       ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION,
616 		       LEN(buffer), STR(buffer),
617 		       ATTR_TYPE_END);
618 	}
619 
620 	/*
621 	 * Save session to cache.
622 	 */
623 	else if (STREQ(STR(request), TLS_MGR_REQ_UPDATE)) {
624 	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
625 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
626 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
627 			  ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buffer,
628 			  ATTR_TYPE_END) == 3) {
629 		for (ent = cache_table; ent->cache_label; ++ent)
630 		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
631 			break;
632 		if (ent->cache_label == 0) {
633 		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
634 			     STR(cache_type), TLS_MGR_REQ_UPDATE);
635 		} else if (ent->cache_info != 0) {
636 		    status =
637 			tls_scache_update(ent->cache_info, STR(cache_id),
638 					  STR(buffer), LEN(buffer)) ?
639 			TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
640 		}
641 	    }
642 	    attr_print(client_stream, ATTR_FLAG_NONE,
643 		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
644 		       ATTR_TYPE_END);
645 	}
646 
647 	/*
648 	 * Delete session from cache.
649 	 */
650 	else if (STREQ(STR(request), TLS_MGR_REQ_DELETE)) {
651 	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
652 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
653 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
654 			  ATTR_TYPE_END) == 2) {
655 		for (ent = cache_table; ent->cache_label; ++ent)
656 		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
657 			break;
658 		if (ent->cache_label == 0) {
659 		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
660 			     STR(cache_type), TLS_MGR_REQ_DELETE);
661 		} else if (ent->cache_info != 0) {
662 		    status = tls_scache_delete(ent->cache_info,
663 					       STR(cache_id)) ?
664 			TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
665 		}
666 	    }
667 	    attr_print(client_stream, ATTR_FLAG_NONE,
668 		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
669 		       ATTR_TYPE_END);
670 	}
671 
672 	/*
673 	 * Entropy request.
674 	 */
675 	else if (STREQ(STR(request), TLS_MGR_REQ_SEED)) {
676 	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
677 			  ATTR_TYPE_INT, TLS_MGR_ATTR_SIZE, &len,
678 			  ATTR_TYPE_END) == 1) {
679 		VSTRING_RESET(buffer);
680 		if (len <= 0 || len > 255) {
681 		    msg_warn("bogus seed length \"%d\" in \"%s\" request",
682 			     len, TLS_MGR_REQ_SEED);
683 		} else {
684 		    VSTRING_SPACE(buffer, len);
685 		    RAND_bytes((unsigned char *) STR(buffer), len);
686 		    VSTRING_AT_OFFSET(buffer, len);	/* XXX not part of the
687 							 * official interface */
688 		    status = TLS_MGR_STAT_OK;
689 		}
690 	    }
691 	    attr_print(client_stream, ATTR_FLAG_NONE,
692 		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
693 		       ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED,
694 		       LEN(buffer), STR(buffer),
695 		       ATTR_TYPE_END);
696 	}
697 
698 	/*
699 	 * Caching policy request.
700 	 */
701 	else if (STREQ(STR(request), TLS_MGR_REQ_POLICY)) {
702 	    int     cachable = 0;
703 
704 	    if (attr_scan(client_stream, ATTR_FLAG_STRICT,
705 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
706 			  ATTR_TYPE_END) == 1) {
707 		for (ent = cache_table; ent->cache_label; ++ent)
708 		    if (strcmp(ent->cache_label, STR(cache_type)) == 0)
709 			break;
710 		if (ent->cache_label == 0) {
711 		    msg_warn("bogus cache type \"%s\" in \"%s\" request",
712 			     STR(cache_type), TLS_MGR_REQ_POLICY);
713 		} else {
714 		    cachable = (ent->cache_info != 0) ? 1 : 0;
715 		    status = TLS_MGR_STAT_OK;
716 		}
717 	    }
718 	    attr_print(client_stream, ATTR_FLAG_NONE,
719 		       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
720 		       ATTR_TYPE_INT, TLS_MGR_ATTR_CACHABLE, cachable,
721 		       ATTR_TYPE_END);
722 	}
723 
724 	/*
725 	 * Master trigger. Normally, these triggers arrive only after some
726 	 * other process requested the tlsmgr's service. The purpose is to
727 	 * restart the tlsmgr after it aborted due to a fatal run-time error,
728 	 * so that it can continue its housekeeping even while nothing is
729 	 * using TLS.
730 	 *
731 	 * XXX Which begs the question, if TLS isn't used often, do we need a
732 	 * tlsmgr background process? It could terminate when the session
733 	 * caches are empty.
734 	 */
735 	else if (STREQ(STR(request), wakeup)) {
736 	    if (msg_verbose)
737 		msg_info("received master trigger");
738 	    multi_server_disconnect(client_stream);
739 	    return;				/* NOT: vstream_fflush */
740 	}
741     }
742 
743     /*
744      * Protocol error.
745      */
746     else {
747 	attr_print(client_stream, ATTR_FLAG_NONE,
748 		   ATTR_TYPE_INT, MAIL_ATTR_STATUS, TLS_MGR_STAT_FAIL,
749 		   ATTR_TYPE_END);
750     }
751     vstream_fflush(client_stream);
752 }
753 
754 /* tlsmgr_pre_init - pre-jail initialization */
755 
756 static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
757 {
758     char   *path;
759     struct timeval tv;
760     TLSMGR_SCACHE *ent;
761     VSTRING *redirect;
762     HTABLE *dup_filter;
763     const char *dup_label;
764 
765     /*
766      * If nothing else works then at least this will get us a few bits of
767      * entropy.
768      *
769      * XXX This is our first call into the OpenSSL library. We should find out
770      * if this can be moved to the post-jail initialization phase, without
771      * breaking compatibility with existing installations.
772      */
773     GETTIMEOFDAY(&tv);
774     tv.tv_sec ^= getpid();
775     RAND_seed(&tv, sizeof(struct timeval));
776 
777     /*
778      * Open the external entropy source. We will not be able to open it again
779      * after we are sent to chroot jail, so we keep it open. Errors are not
780      * fatal. The exchange file (see below) is the only entropy source that
781      * really matters in the long run.
782      *
783      * Security note: we open the entropy source while privileged, but we don't
784      * access the source until after we release privileges. This way, none of
785      * the OpenSSL code gets to execute while we are privileged.
786      */
787     if (*var_tls_rand_source) {
788 
789 	/*
790 	 * Source is a random device.
791 	 */
792 	if (!strncmp(var_tls_rand_source, DEV_PREF, DEV_PREF_LEN)) {
793 	    path = DEV_PATH(var_tls_rand_source);
794 	    rand_source_dev = tls_prng_dev_open(path, TLS_MGR_TIMEOUT);
795 	    if (rand_source_dev == 0)
796 		msg_warn("cannot open entropy device %s: %m", path);
797 	}
798 
799 	/*
800 	 * Source is an EGD compatible socket.
801 	 */
802 	else if (!strncmp(var_tls_rand_source, EGD_PREF, EGD_PREF_LEN)) {
803 	    path = EGD_PATH(var_tls_rand_source);
804 	    rand_source_egd = tls_prng_egd_open(path, TLS_MGR_TIMEOUT);
805 	    if (rand_source_egd == 0)
806 		msg_warn("cannot connect to EGD server %s: %m", path);
807 	}
808 
809 	/*
810 	 * Source is regular file. We read this only once.
811 	 */
812 	else {
813 	    rand_source_file =
814 		tls_prng_file_open(var_tls_rand_source, TLS_MGR_TIMEOUT);
815 	}
816     } else {
817 	msg_warn("no entropy source specified with parameter %s",
818 		 VAR_TLS_RAND_SOURCE);
819 	msg_warn("encryption keys etc. may be predictable");
820     }
821 
822     /*
823      * Security: don't create root-owned files that contain untrusted data.
824      * And don't create Postfix-owned files in root-owned directories,
825      * either. We want a correct relationship between (file/directory)
826      * ownership and (file/directory) content.
827      */
828     SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
829     redirect = vstring_alloc(100);
830 
831     /*
832      * Open the PRNG exchange file before going to jail, but don't use root
833      * privileges. Start the exchange file read/update pseudo thread after
834      * dropping privileges.
835      */
836     if (*var_tls_rand_exch_name) {
837 	rand_exch =
838 	    tls_prng_exch_open(data_redirect_file(redirect,
839 						  var_tls_rand_exch_name));
840 	if (rand_exch == 0)
841 	    msg_fatal("cannot open PRNG exchange file %s: %m",
842 		      var_tls_rand_exch_name);
843     }
844 
845     /*
846      * Open the session cache files and discard old information before going
847      * to jail, but don't use root privilege. Start the cache maintenance
848      * pseudo threads after dropping privileges.
849      */
850     dup_filter = htable_create(sizeof(cache_table) / sizeof(cache_table[0]));
851     for (ent = cache_table; ent->cache_label; ++ent) {
852 	if (**ent->cache_db) {
853 	    if ((dup_label = htable_find(dup_filter, *ent->cache_db)) != 0)
854 		msg_fatal("do not use the same TLS cache file %s for %s and %s",
855 			  *ent->cache_db, dup_label, ent->cache_label);
856 	    htable_enter(dup_filter, *ent->cache_db, ent->cache_label);
857 	    ent->cache_info =
858 		tls_scache_open(data_redirect_map(redirect, *ent->cache_db),
859 				ent->cache_label,
860 				tls_log_mask(ent->log_param,
861 					   *ent->log_level) & TLS_LOG_CACHE,
862 				*ent->cache_timeout);
863 	}
864     }
865     htable_free(dup_filter, (void (*) (char *)) 0);
866 
867     /*
868      * Clean up and restore privilege.
869      */
870     vstring_free(redirect);
871     RESTORE_SAVED_EUGID();
872 }
873 
874 /* tlsmgr_post_init - post-jail initialization */
875 
876 static void tlsmgr_post_init(char *unused_name, char **unused_argv)
877 {
878     TLSMGR_SCACHE *ent;
879 
880 #define NULL_EVENT	(0)
881 #define NULL_CONTEXT	((char *) 0)
882 
883     /*
884      * This routine runs after the skeleton code has entered the chroot jail,
885      * but before any client requests are serviced. Prevent automatic process
886      * suicide after a limited number of client requests or after a limited
887      * amount of idle time.
888      */
889     var_use_limit = 0;
890     var_idle_limit = 0;
891 
892     /*
893      * Start the internal PRNG re-seeding pseudo thread first.
894      */
895     if (*var_tls_rand_source) {
896 	if (var_tls_reseed_period > INT_MAX / UCHAR_MAX)
897 	    var_tls_reseed_period = INT_MAX / UCHAR_MAX;
898 	tlsmgr_reseed_event(NULL_EVENT, NULL_CONTEXT);
899     }
900 
901     /*
902      * Start the exchange file read/update pseudo thread.
903      */
904     if (*var_tls_rand_exch_name) {
905 	if (var_tls_prng_exch_period > INT_MAX / UCHAR_MAX)
906 	    var_tls_prng_exch_period = INT_MAX / UCHAR_MAX;
907 	tlsmgr_prng_exch_event(NULL_EVENT, NULL_CONTEXT);
908     }
909 
910     /*
911      * Start the cache maintenance pseudo threads last. Strictly speaking
912      * there is nothing to clean up after we truncate the database to zero
913      * length, but early cleanup makes verbose logging more informative (we
914      * get positive confirmation that the cleanup threads are running).
915      */
916     for (ent = cache_table; ent->cache_label; ++ent)
917 	if (ent->cache_info)
918 	    tlsmgr_cache_run_event(NULL_EVENT, (char *) ent);
919 }
920 
921 /* tlsmgr_before_exit - save PRNG state before exit */
922 
923 static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
924 {
925 
926     /*
927      * Save state before we exit after "postfix reload".
928      */
929     if (rand_exch)
930 	tls_prng_exch_update(rand_exch);
931 }
932 
933 MAIL_VERSION_STAMP_DECLARE;
934 
935 /* main - the main program */
936 
937 int     main(int argc, char **argv)
938 {
939     static const CONFIG_STR_TABLE str_table[] = {
940 	VAR_TLS_RAND_SOURCE, DEF_TLS_RAND_SOURCE, &var_tls_rand_source, 0, 0,
941 	VAR_TLS_RAND_EXCH_NAME, DEF_TLS_RAND_EXCH_NAME, &var_tls_rand_exch_name, 0, 0,
942 	VAR_SMTPD_TLS_SCACHE_DB, DEF_SMTPD_TLS_SCACHE_DB, &var_smtpd_tls_scache_db, 0, 0,
943 	VAR_SMTP_TLS_SCACHE_DB, DEF_SMTP_TLS_SCACHE_DB, &var_smtp_tls_scache_db, 0, 0,
944 	VAR_LMTP_TLS_SCACHE_DB, DEF_LMTP_TLS_SCACHE_DB, &var_lmtp_tls_scache_db, 0, 0,
945 	VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
946 	VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0,
947 	VAR_LMTP_TLS_LOGLEVEL, DEF_LMTP_TLS_LOGLEVEL, &var_lmtp_tls_loglevel, 0, 0,
948 	0,
949     };
950     static const CONFIG_TIME_TABLE time_table[] = {
951 	VAR_TLS_RESEED_PERIOD, DEF_TLS_RESEED_PERIOD, &var_tls_reseed_period, 1, 0,
952 	VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_exch_period, 1, 0,
953 	VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, 0,
954 	VAR_SMTP_TLS_SCACHTIME, DEF_SMTP_TLS_SCACHTIME, &var_smtp_tls_scache_timeout, 0, 0,
955 	VAR_LMTP_TLS_SCACHTIME, DEF_LMTP_TLS_SCACHTIME, &var_lmtp_tls_scache_timeout, 0, 0,
956 	0,
957     };
958     static const CONFIG_INT_TABLE int_table[] = {
959 	VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 1, 0,
960 	0,
961     };
962 
963     /*
964      * Fingerprint executables and core dumps.
965      */
966     MAIL_VERSION_STAMP_ALLOCATE;
967 
968     /*
969      * Use the multi service skeleton, and require that no-one else is
970      * monitoring our service port while this process runs.
971      */
972     multi_server_main(argc, argv, tlsmgr_service,
973 		      MAIL_SERVER_TIME_TABLE, time_table,
974 		      MAIL_SERVER_INT_TABLE, int_table,
975 		      MAIL_SERVER_STR_TABLE, str_table,
976 		      MAIL_SERVER_PRE_INIT, tlsmgr_pre_init,
977 		      MAIL_SERVER_POST_INIT, tlsmgr_post_init,
978 		      MAIL_SERVER_EXIT, tlsmgr_before_exit,
979 		      MAIL_SERVER_LOOP, tlsmgr_loop,
980 		      MAIL_SERVER_SOLITARY,
981 		      0);
982 }
983 
984 #else
985 
986 /* tlsmgr_service - respond to external trigger(s), non-TLS version */
987 
988 static void tlsmgr_service(VSTREAM *unused_stream, char *unused_service,
989 			           char **unused_argv)
990 {
991     msg_info("TLS support is not compiled in -- exiting");
992 }
993 
994 /* main - the main program, non-TLS version */
995 
996 int     main(int argc, char **argv)
997 {
998 
999     /*
1000      * 200411 We can't simply use msg_fatal() here, because the logging
1001      * hasn't been initialized. The text would disappear because stderr is
1002      * redirected to /dev/null.
1003      *
1004      * We invoke multi_server_main() to complete program initialization
1005      * (including logging) and then invoke the tlsmgr_service() routine to
1006      * log the message that says why this program will not run.
1007      */
1008     multi_server_main(argc, argv, tlsmgr_service,
1009 		      0);
1010 }
1011 
1012 #endif
1013