182 #include <sys/stat.h>
188 #include <sys/time.h>
192 #define UCHAR_MAX 0xff
198 #include <openssl/rand.h>
246 int var_tls_prng_exch_period;
263 #define TLS_MGR_TIMEOUT 10
282 #define DEV_PREF "dev:"
283 #define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
284 #define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
286 #define EGD_PREF "egd:"
287 #define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
288 #define EGD_PATH(egd) ((egd) + EGD_PREF_LEN)
298 const char *log_param;
303 static TLSMGR_SCACHE cache_table[] = {
316 #define smtpd_cache (cache_table[0])
321 #define STR(x) vstring_str(x)
322 #define LEN(x) VSTRING_LEN(x)
323 #define STREQ(x, y) (strcmp((x), (y)) == 0)
327 static void tlsmgr_prng_exch_event(
int unused_event,
void *dummy)
329 const char *myname =
"tlsmgr_prng_exch_event";
330 unsigned char randbyte;
335 msg_info(
"%s: update PRNG exchange file", myname);
341 if (
fstat(rand_exch->
fd, &st) < 0)
342 msg_fatal(
"cannot fstat() the PRNG exchange file: %m");
343 if (st.st_nlink == 0) {
344 msg_warn(
"PRNG exchange file was removed -- exiting to reopen");
354 RAND_bytes(&randbyte, 1);
355 next_period = (var_tls_prng_exch_period * randbyte) /
UCHAR_MAX;
361 static void tlsmgr_reseed_event(
int unused_event,
void *dummy)
364 unsigned char randbyte;
382 if (rand_source_dev) {
384 msg_info(
"cannot read from entropy device %s: %m -- "
393 else if (rand_source_egd) {
395 msg_info(
"lost connection to EGD server %s -- "
405 else if (rand_source_file) {
407 msg_warn(
"cannot read from entropy file %s: %m",
410 rand_source_file = 0;
419 msg_info(
"exiting to reopen external entropy source %s",
439 RAND_bytes(&randbyte, 1);
446 static void tlsmgr_cache_run_event(
int unused_event,
void *ctx)
448 const char *myname =
"tlsmgr_cache_run_event";
449 TLSMGR_SCACHE *cache = (TLSMGR_SCACHE *) ctx;
458 if (cache->cache_info->verbose)
459 msg_info(
"%s: start TLS %s session cache cleanup",
460 myname, cache->cache_label);
462 if (cache->cache_active == 0)
463 cache->cache_active =
468 cache->cache_info->timeout);
473 static int tlsmgr_key(
VSTRING *buffer,
int timeout)
478 time_t now = time((time_t *) 0);
481 name =
LEN(buffer) ? (
unsigned char *)
STR(buffer) : 0;
497 tmp.
tout = now + timeout - 1;
511 static int tlsmgr_loop(
char *unused_name,
char **unused_argv)
523 RAND_seed(&tv,
sizeof(
struct timeval));
537 #define WAIT_FOR_EVENT (-1)
539 for (ent = cache_table; ent->cache_label; ++ent) {
540 if (ent->cache_info && ent->cache_active)
541 active |= ent->cache_active =
551 static int tlsmgr_request_receive(
VSTREAM *client_stream,
VSTRING *request)
559 msg_warn(
"timeout while waiting for data from %s",
564 msg_warn(
"cannot examine read buffer of %s: %m",
574 msg_warn(
"end-of-input while reading request from %s: %m",
596 static void tlsmgr_service(
VSTREAM *client_stream,
char *unused_service,
600 static VSTRING *cache_type = 0;
604 static char wakeup[] = {
615 msg_fatal(
"unexpected command-line argument: %s", argv[0]);
633 if (tlsmgr_request_receive(client_stream, request) == 0) {
643 for (ent = cache_table; ent->cache_label; ++ent)
644 if (strcmp(ent->cache_label,
STR(cache_type)) == 0)
646 if (ent->cache_label == 0) {
647 msg_warn(
"bogus cache type \"%s\" in \"%s\" request",
650 }
else if (ent->cache_info == 0) {
658 STR(cache_id), buffer) ?
665 LEN(buffer),
STR(buffer)),
678 for (ent = cache_table; ent->cache_label; ++ent)
679 if (strcmp(ent->cache_label,
STR(cache_type)) == 0)
681 if (ent->cache_label == 0) {
682 msg_warn(
"bogus cache type \"%s\" in \"%s\" request",
684 }
else if (ent->cache_info != 0) {
687 STR(buffer),
LEN(buffer)) ?
704 for (ent = cache_table; ent->cache_label; ++ent)
705 if (strcmp(ent->cache_label,
STR(cache_type)) == 0)
707 if (ent->cache_label == 0) {
708 msg_warn(
"bogus cache type \"%s\" in \"%s\" request",
710 }
else if (ent->cache_info != 0) {
729 msg_warn(
"invalid session ticket key name length: %ld",
732 }
else if (*smtpd_cache.cache_timeout <= 0) {
736 status = tlsmgr_key(buffer, *smtpd_cache.cache_timeout);
742 LEN(buffer),
STR(buffer)),
754 if (len <= 0 || len > 255) {
755 msg_warn(
"bogus seed length \"%d\" in \"%s\" request",
759 RAND_bytes((
unsigned char *)
STR(buffer), len);
768 LEN(buffer),
STR(buffer)),
782 for (ent = cache_table; ent->cache_label; ++ent)
783 if (strcmp(ent->cache_label,
STR(cache_type)) == 0)
785 if (ent->cache_label == 0) {
786 msg_warn(
"bogus cache type \"%s\" in \"%s\" request",
789 cachable = (ent->cache_info != 0) ? 1 : 0;
790 timeout = *ent->cache_timeout;
812 else if (
STREQ(
STR(request), wakeup)) {
814 msg_info(
"received master trigger");
833 static void tlsmgr_pre_init(
char *unused_name,
char **unused_argv)
840 const char *dup_label;
851 tv.tv_sec ^= getpid();
852 RAND_seed(&tv,
sizeof(
struct timeval));
872 if (rand_source_dev == 0)
873 msg_warn(
"cannot open entropy device %s: %m", path);
882 if (rand_source_egd == 0)
883 msg_warn(
"cannot connect to EGD server %s: %m", path);
894 msg_warn(
"no entropy source specified with parameter %s",
896 msg_warn(
"encryption keys etc. may be predictable");
918 msg_fatal(
"cannot open PRNG exchange file %s: %m",
927 dup_filter =
htable_create(
sizeof(cache_table) /
sizeof(cache_table[0]));
928 for (ent = cache_table; ent->cache_label; ++ent) {
930 if (*ent->cache_timeout > 0) {
934 *ent->cache_timeout = 0;
937 if (*ent->cache_timeout > 0 && **ent->cache_db) {
938 if ((dup_label =
htable_find(dup_filter, *ent->cache_db)) != 0)
939 msg_fatal(
"do not use the same TLS cache file %s for %s and %s",
940 *ent->cache_db, dup_label, ent->cache_label);
941 htable_enter(dup_filter, *ent->cache_db, ent->cache_label);
945 tls_log_mask(ent->log_param,
946 *ent->log_level) & TLS_LOG_CACHE,
947 *ent->cache_timeout);
961 static void tlsmgr_post_init(
char *unused_name,
char **unused_argv)
965 #define NULL_EVENT (0)
966 #define NULL_CONTEXT ((char *) 0)
983 tlsmgr_reseed_event(NULL_EVENT, NULL_CONTEXT);
990 if (var_tls_prng_exch_period > INT_MAX /
UCHAR_MAX)
991 var_tls_prng_exch_period = INT_MAX /
UCHAR_MAX;
992 tlsmgr_prng_exch_event(NULL_EVENT, NULL_CONTEXT);
1001 for (ent = cache_table; ent->cache_label; ++ent)
1002 if (ent->cache_info)
1003 tlsmgr_cache_run_event(NULL_EVENT, (
void *) ent);
1008 static void tlsmgr_before_exit(
char *unused_service_name,
char **unused_argv)
1022 int main(
int argc,
char **argv)
1073 static void tlsmgr_service(
VSTREAM *unused_stream,
char *unused_service,
1076 msg_info(
"TLS support is not compiled in -- exiting");
void htable_free(HTABLE *table, void(*free_fn)(void *))
#define VAR_TLS_RAND_BYTES
#define RESTORE_SAVED_EUGID()
TLS_PRNG_SRC * tls_prng_file_open(const char *, int)
#define TLS_MGR_ATTR_SIZE
char * var_tls_rand_source
#define MAIL_VERSION_STAMP_DECLARE
TLS_PRNG_SRC * tls_prng_exch_open(const char *)
int vstring_get_null(VSTRING *vp, VSTREAM *fp)
#define VAR_TLS_PRNG_UPD_PERIOD
#define VAR_LMTP_TLS_LOGLEVEL
int var_lmtp_tls_scache_timeout
#define TLS_TICKET_NAMELEN
#define DICT_SEQ_FUN_FIRST
#define VAR_SMTPD_TLS_SCACHTIME
#define MAX_SMTP_TLS_SCACHETIME
int var_tls_reseed_period
#define TLS_SCACHE_SEQUENCE_NOTHING
#define CA_MAIL_SERVER_STR_TABLE(v)
int tls_prng_file_close(TLS_PRNG_SRC *)
#define DEF_SMTPD_TLS_SCACHE_DB
#define DICT_SEQ_FUN_NEXT
char * data_redirect_map(VSTRING *result, const char *map)
#define VAR_SMTP_TLS_LOGLEVEL
#define TLS_MGR_REQ_TKTKEY
#define SAVE_AND_SET_EUGID(uid, gid)
#define DEF_SMTPD_TLS_LOGLEVEL
TLS_TICKET_KEY * tls_scache_key_rotate(TLS_TICKET_KEY *)
#define CA_MAIL_SERVER_EXIT(v)
#define CA_MAIL_SERVER_LOOP(v)
int tls_scache_sequence(TLS_SCACHE *, int, char **, VSTRING *)
#define RECV_ATTR_INT(name, val)
void multi_server_disconnect(VSTREAM *)
int var_smtpd_tls_scache_timeout
char * var_smtpd_tls_scache_db
char * var_smtp_tls_loglevel
#define DEF_TLS_RAND_EXCH_NAME
#define DEF_LMTP_TLS_SCACHE_DB
NORETURN multi_server_main(int, char **, MULTI_SERVER_FN,...)
char * var_tls_rand_exch_name
unsigned char hmac[TLS_TICKET_MACLEN]
TLS_SCACHE * tls_scache_open(const char *, const char *, int, int)
#define TLS_MGR_ATTR_SESSION
#define TLS_MGR_ATTR_SESSTOUT
#define TLS_MGR_ATTR_SEED
HTABLE * htable_create(ssize_t size)
#define VAR_SMTP_TLS_SCACHTIME
#define VAR_LMTP_TLS_SCACHTIME
#define CA_MAIL_SERVER_POST_INIT(v)
#define CA_MAIL_SERVER_INT_TABLE(v)
int tls_scache_lookup(TLS_SCACHE *, const char *, VSTRING *)
#define TLS_MGR_ATTR_KEYBUF
#define DEF_SMTP_TLS_LOGLEVEL
#define VAR_SMTPD_TLS_LOGLEVEL
unsigned char name[TLS_TICKET_NAMELEN]
#define TLS_MGR_REQ_DELETE
char * var_lmtp_tls_loglevel
int var_smtp_tls_scache_timeout
TLS_TICKET_KEY * tls_scache_key(unsigned char *, time_t, int)
char * var_lmtp_tls_scache_db
TLS_PRNG_SRC * tls_prng_dev_open(const char *, int)
#define DEF_TLS_PRNG_UPD_PERIOD
#define TLS_MGR_ATTR_KEYNAME
int tls_scache_update(TLS_SCACHE *, const char *, const char *, ssize_t)
#define VSTRING_RESET(vp)
#define read_wait(fd, timeout)
void msg_warn(const char *fmt,...)
#define VAR_LMTP_TLS_SCACHE_DB
#define RECV_ATTR_DATA(name, val)
VSTRING * vstring_alloc(ssize_t len)
#define MAIL_VERSION_STAMP_ALLOCATE
#define TLS_MGR_STAT_FAIL
void * htable_find(HTABLE *table, const char *key)
ssize_t tls_prng_file_read(TLS_PRNG_SRC *, size_t)
#define TLS_MGR_REQ_LOOKUP
#define VAR_SMTPD_TLS_SCACHE_DB
#define VAR_TLS_RAND_EXCH_NAME
#define CA_MAIL_SERVER_TIME_TABLE(v)
#define SEND_ATTR_INT(name, val)
#define DEF_TLS_RAND_BYTES
char * data_redirect_file(VSTRING *result, const char *path)
#define VAR_TLS_RESEED_PERIOD
NORETURN msg_fatal(const char *fmt,...)
#define VAR_SMTP_TLS_SCACHE_DB
#define DEF_TLS_RAND_SOURCE
#define MAX_SMTPD_TLS_SCACHETIME
#define VAR_TLS_RAND_SOURCE
char * var_smtpd_tls_loglevel
#define TLS_MGR_REQ_UPDATE
int vstream_fflush(VSTREAM *stream)
unsigned char bits[TLS_TICKET_KEYLEN]
#define MAX_LMTP_TLS_SCACHETIME
#define VSTRING_SPACE(vp, len)
ssize_t tls_prng_egd_read(TLS_PRNG_SRC *, size_t)
#define DEF_LMTP_TLS_LOGLEVEL
#define TRIGGER_REQ_WAKEUP
#define DEF_TLS_RESEED_PERIOD
VSTRING * vstring_free(VSTRING *vp)
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
char * var_smtp_tls_scache_db
#define TLS_TICKET_MACLEN
#define TLS_MGR_ATTR_CACHE_TYPE
#define CA_MAIL_SERVER_SOLITARY
#define vstream_fileno(vp)
#define VSTRING_AT_OFFSET(vp, offset)
TLS_PRNG_SRC * tls_prng_egd_open(const char *, int)
int tls_scache_delete(TLS_SCACHE *, const char *)
#define DEF_LMTP_TLS_SCACHTIME
#define TLS_MGR_ATTR_CACHE_ID
#define TLS_TICKET_KEYLEN
#define DEF_SMTP_TLS_SCACHE_DB
VSTRING * vstring_memcpy(VSTRING *vp, const char *src, ssize_t len)
ssize_t tls_prng_dev_read(TLS_PRNG_SRC *, size_t)
#define TLS_MGR_ATTR_CACHABLE
void tls_prng_exch_update(TLS_PRNG_SRC *)
#define TLS_SESSION_LIFEMIN
#define DEF_SMTP_TLS_SCACHTIME
#define SEND_ATTR_DATA(name, len, val)
#define TLS_MGR_REQ_POLICY
#define DEF_SMTPD_TLS_SCACHTIME
#define CA_MAIL_SERVER_PRE_INIT(v)
#define RECV_ATTR_STR(name, val)
int main(int argc, char **argv)
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
void msg_info(const char *fmt,...)