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