No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / tlsmgr / tlsmgr.c
blob98b90a97a2a50c115c03f78f498e533e330286a7
1 /* $NetBSD$ */
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.
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.
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.
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.
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.
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.
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
163 /* Adapted by:
164 /* Wietse Venema
165 /* IBM T.J. Watson Research
166 /* P.O. Box 704
167 /* Yorktown Heights, NY 10598, USA
168 /*--*/
170 /* System library. */
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>
182 #ifndef UCHAR_MAX
183 #define UCHAR_MAX 0xff
184 #endif
186 /* OpenSSL library. */
188 #ifdef USE_TLS
189 #include <openssl/rand.h> /* For the PRNG */
190 #endif
192 /* Utility library. */
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>
206 /* Global library. */
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>
215 /* Master process interface. */
217 #include <master_proto.h>
218 #include <mail_server.h>
220 /* TLS library. */
222 #ifdef USE_TLS
223 #include <tls.h> /* TLS_MGR_SCACHE_<type> */
224 #include <tls_prng.h>
225 #include <tls_scache.h>
227 /* Application-specific. */
230 * Tunables.
232 char *var_tls_rand_source;
233 int var_tls_rand_bytes;
234 int var_tls_reseed_period;
235 int var_tls_prng_exch_period;
236 int var_smtpd_tls_loglevel;
237 char *var_smtpd_tls_scache_db;
238 int var_smtpd_tls_scache_timeout;
239 int var_smtp_tls_loglevel;
240 char *var_smtp_tls_scache_db;
241 int var_smtp_tls_scache_timeout;
242 int var_lmtp_tls_loglevel;
243 char *var_lmtp_tls_scache_db;
244 int var_lmtp_tls_scache_timeout;
245 char *var_tls_rand_exch_name;
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.
252 #define TLS_MGR_TIMEOUT 10
255 * State for updating the PRNG exchange file.
257 static TLS_PRNG_SRC *rand_exch;
260 * State for seeding the internal PRNG from external source.
262 static TLS_PRNG_SRC *rand_source_dev;
263 static TLS_PRNG_SRC *rand_source_egd;
264 static TLS_PRNG_SRC *rand_source_file;
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.
271 #define DEV_PREF "dev:"
272 #define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
273 #define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
275 #define EGD_PREF "egd:"
276 #define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
277 #define EGD_PATH(egd) ((egd) + EGD_PREF_LEN)
280 * State for TLS session caches.
282 typedef 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;
291 TLSMGR_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,
302 * SLMs.
304 #define STR(x) vstring_str(x)
305 #define LEN(x) VSTRING_LEN(x)
306 #define STREQ(x, y) (strcmp((x), (y)) == 0)
308 /* tlsmgr_prng_exch_event - update PRNG exchange file */
310 static void tlsmgr_prng_exch_event(int unused_event, char *dummy)
312 const char *myname = "tlsmgr_prng_exch_event";
313 unsigned char randbyte;
314 int next_period;
315 struct stat st;
317 if (msg_verbose)
318 msg_info("%s: update PRNG exchange file", myname);
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.
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);
331 tls_prng_exch_update(rand_exch);
334 * Make prediction difficult for outsiders and calculate the time for the
335 * next execution randomly.
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);
342 /* tlsmgr_reseed_event - re-seed the internal PRNG pool */
344 static void tlsmgr_reseed_event(int unused_event, char *dummy)
346 int next_period;
347 unsigned char randbyte;
348 int must_exit = 0;
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.
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).
360 if (*var_tls_rand_source) {
363 * Source is a random device.
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;
374 * Source is an EGD compatible socket.
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;
385 * Source is a regular file. Read the content once and close the
386 * file.
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;
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.
401 else {
402 msg_info("exiting to reopen external entropy source %s",
403 var_tls_rand_source);
404 must_exit = 1;
409 * Save PRNG state in case we must exit.
411 if (must_exit) {
412 if (rand_exch)
413 tls_prng_exch_update(rand_exch);
414 sleep(1);
415 exit(0);
419 * Make prediction difficult for outsiders and calculate the time for the
420 * next execution randomly.
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);
427 /* tlsmgr_cache_run_event - start TLS session cache scan */
429 static void tlsmgr_cache_run_event(int unused_event, char *ctx)
431 const char *myname = "tlsmgr_cache_run_event";
432 TLSMGR_SCACHE *cache = (TLSMGR_SCACHE *) ctx;
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.
438 * Don't start a new scan when the timer goes off while cache cleanup is
439 * still in progress.
441 if (cache->cache_info->verbose)
442 msg_info("%s: start TLS %s session cache cleanup",
443 myname, cache->cache_label);
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);
450 event_request_timer(tlsmgr_cache_run_event, (char *) cache,
451 cache->cache_info->timeout);
454 /* tlsmgr_loop - TLS manager main loop */
456 static int tlsmgr_loop(char *unused_name, char **unused_argv)
458 struct timeval tv;
459 int active = 0;
460 TLSMGR_SCACHE *ent;
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.
467 GETTIMEOFDAY(&tv);
468 RAND_seed(&tv, sizeof(struct timeval));
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.
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.
481 #define DONT_WAIT 0
482 #define WAIT_FOR_EVENT (-1)
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);
491 return (active ? DONT_WAIT : WAIT_FOR_EVENT);
494 /* tlsmgr_request_receive - receive request */
496 static int tlsmgr_request_receive(VSTREAM *client_stream, VSTRING *request)
498 int count;
501 * Kluge: choose the protocol depending on the request size.
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);
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);
515 * Short request: master trigger. Use the string+null protocol.
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);
526 * Long request: real tlsmgr client. Use the attribute list protocol.
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);
536 return (0);
539 /* tlsmgr_service - respond to external request */
541 static void tlsmgr_service(VSTREAM *client_stream, char *unused_service,
542 char **argv)
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,
553 TLSMGR_SCACHE *ent;
554 int status = TLS_MGR_STAT_FAIL;
557 * Sanity check. This service takes no command-line arguments.
559 if (argv[0])
560 msg_fatal("unexpected command-line argument: %s", argv[0]);
563 * Initialize. We're select threaded, so we can use static buffers.
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);
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.
578 if (tlsmgr_request_receive(client_stream, request) == 0) {
581 * Load session from cache.
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) {
598 * Cache type valid, but not enabled
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;
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);
615 * Save session to cache.
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;
636 attr_print(client_stream, ATTR_FLAG_NONE,
637 ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
638 ATTR_TYPE_END);
642 * Delete session from cache.
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;
661 attr_print(client_stream, ATTR_FLAG_NONE,
662 ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
663 ATTR_TYPE_END);
667 * Entropy request.
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;
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);
693 * Caching policy request.
695 else if (STREQ(STR(request), TLS_MGR_REQ_POLICY)) {
696 int cachable = 0;
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;
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);
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.
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.
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 */
738 * Protocol error.
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);
745 vstream_fflush(client_stream);
748 /* tlsmgr_pre_init - pre-jail initialization */
750 static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
752 char *path;
753 struct timeval tv;
754 TLSMGR_SCACHE *ent;
755 VSTRING *redirect;
756 HTABLE *dup_filter;
757 const char *dup_label;
760 * If nothing else works then at least this will get us a few bits of
761 * entropy.
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.
767 GETTIMEOFDAY(&tv);
768 tv.tv_sec ^= getpid();
769 RAND_seed(&tv, sizeof(struct timeval));
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.
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.
781 if (*var_tls_rand_source) {
784 * Source is a random device.
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);
794 * Source is an EGD compatible socket.
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);
804 * Source is regular file. We read this only once.
806 else {
807 rand_source_file =
808 tls_prng_file_open(var_tls_rand_source, TLS_MGR_TIMEOUT);
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");
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.
822 SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
823 redirect = vstring_alloc(100);
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.
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);
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.
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);
858 htable_free(dup_filter, (void (*) (char *)) 0);
861 * Clean up and restore privilege.
863 vstring_free(redirect);
864 RESTORE_SAVED_EUGID();
867 /* tlsmgr_post_init - post-jail initialization */
869 static void tlsmgr_post_init(char *unused_name, char **unused_argv)
871 TLSMGR_SCACHE *ent;
873 #define NULL_EVENT (0)
874 #define NULL_CONTEXT ((char *) 0)
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.
882 var_use_limit = 0;
883 var_idle_limit = 0;
886 * Start the internal PRNG re-seeding pseudo thread first.
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);
895 * Start the exchange file read/update pseudo thread.
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);
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).
909 for (ent = cache_table; ent->cache_label; ++ent)
910 if (ent->cache_info)
911 tlsmgr_cache_run_event(NULL_EVENT, (char *) ent);
914 /* tlsmgr_before_exit - save PRNG state before exit */
916 static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
920 * Save state before we exit after "postfix reload".
922 if (rand_exch)
923 tls_prng_exch_update(rand_exch);
926 MAIL_VERSION_STAMP_DECLARE;
928 /* main - the main program */
930 int main(int argc, char **argv)
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,
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,
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,
957 * Fingerprint executables and core dumps.
959 MAIL_VERSION_STAMP_ALLOCATE;
962 * Use the multi service skeleton, and require that no-one else is
963 * monitoring our service port while this process runs.
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,
977 #else
979 /* tlsmgr_service - respond to external trigger(s), non-TLS version */
981 static void tlsmgr_service(VSTREAM *unused_stream, char *unused_service,
982 char **unused_argv)
984 msg_info("TLS support is not compiled in -- exiting");
987 /* main - the main program, non-TLS version */
989 int main(int argc, char **argv)
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.
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.
1001 multi_server_main(argc, argv, tlsmgr_service,
1005 #endif