X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftls.c;h=ddee95de2136962cd238407a2dddcf600198434b;hb=7411ebe05198d5365557b6c982b76ceb9e843894;hp=d213fefd69b9fc1454d095e8bac9f440dc6bc1f4;hpb=c3bb5a29480ecbd971e206a1efbd4ad3d23e6e93;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/tls.c b/src/src/tls.c index d213fefd6..ddee95de2 100644 --- a/src/src/tls.c +++ b/src/src/tls.c @@ -38,7 +38,7 @@ functions from the OpenSSL or GNU TLS libraries. */ static void tls_per_lib_daemon_init(void); static void tls_per_lib_daemon_tick(void); -static void tls_server_creds_init(void); +static unsigned tls_server_creds_init(void); static void tls_server_creds_invalidate(void); static void tls_client_creds_init(transport_instance *, BOOL); static void tls_client_creds_invalidate(transport_instance *); @@ -82,6 +82,8 @@ static struct kevent kev[KEV_SIZE]; static int kev_used = 0; #endif +static unsigned tls_creds_expire = 0; + /************************************************* * Expand string; give error on failure * *************************************************/ @@ -159,21 +161,26 @@ return FALSE; uschar * s; int fd1, fd2, i, cnt = 0; struct stat sb; +#ifdef OpenBSD +struct kevent k_dummy; +struct timespec ts = {0}; +#endif errno = 0; if (Ustrcmp(filename, "system,cache") == 0) return TRUE; for (;;) { - if (!(s = Ustrrchr(filename, '/'))) return FALSE; - if ((lstat(CCS filename, &sb)) < 0) { s = US"lstat"; goto bad; } if (kev_used > KEV_SIZE-2) { s = US"out of kev space"; goto bad; } + if (!(s = Ustrrchr(filename, '/'))) return FALSE; + s = string_copyn(filename, s - filename); /* mem released by tls_set_watch */ /* The dir open will fail if there is a symlink on the path. Fine; it's too much effort to handle all possible cases; just refuse the preload. */ if ((fd2 = open(CCS s, O_RDONLY | O_NOFOLLOW)) < 0) { s = US"open dir"; goto bad; } + if ((lstat(CCS filename, &sb)) < 0) { s = US"lstat"; goto bad; } if (!S_ISLNK(sb.st_mode)) { if ((fd1 = open(CCS filename, O_RDONLY | O_NOFOLLOW)) < 0) @@ -203,14 +210,19 @@ for (;;) if (!(S_ISLNK(sb.st_mode))) break; s = store_get(1024, FALSE); - if ((i = readlink(CCS filename, s, 1024)) < 0) { s = US"readlink"; goto bad; } + if ((i = readlink(CCS filename, (void *)s, 1024)) < 0) { s = US"readlink"; goto bad; } filename = s; *(s += i) = '\0'; store_release_above(s+1); } +#ifdef OpenBSD +if (kevent(tls_watch_fd, &kev[kev_used-cnt], cnt, &k_dummy, 1, &ts) >= 0) + return TRUE; +#else if (kevent(tls_watch_fd, &kev[kev_used-cnt], cnt, NULL, 0, NULL) >= 0) return TRUE; +#endif s = US"kevent"; bad: @@ -281,20 +293,6 @@ struct timespec t = {0}; (void) kevent(fd, NULL, 0, &kev, 1, &t); #endif } - -/* Called, after a delay for multiple file ops to get done, from -the daemon when any of the watches added (above) fire. - -Dump the set of watches and arrange to reload cached creds (which -will set up new watches). */ - -static void -tls_watch_triggered(void) -{ -DEBUG(D_tls) debug_printf("watch triggered\n"); - -tls_daemon_creds_reload(); -} #endif /*EXIM_HAVE_INOTIFY*/ @@ -317,7 +315,7 @@ if (tls_watch_fd < 0) return; #ifdef EXIM_HAVE_KEVENT /* Close the files we had open for kevent */ -for (int fd, i = 0; i < kev_used; i++) +for (int i = 0; i < kev_used; i++) { (void) close((int) kev[i].ident); kev[i].ident = (uintptr_t)-1; @@ -333,12 +331,15 @@ tls_watch_fd = -1; static void tls_daemon_creds_reload(void) { +unsigned lifetime; + #ifdef EXIM_HAVE_KEVENT tls_watch_invalidate(); #endif tls_server_creds_invalidate(); -tls_server_creds_init(); +tls_creds_expire = (lifetime = tls_server_creds_init()) + ? time(NULL) + lifetime : 0; tls_client_creds_reload(TRUE); } @@ -362,10 +363,26 @@ tls_daemon_tick(void) { tls_per_lib_daemon_tick(); #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT) -if (tls_watch_trigger_time && time(NULL) >= tls_watch_trigger_time + 5) +if (tls_creds_expire && time(NULL) >= tls_creds_expire) + { + /* The server cert is a selfsign, with limited lifetime. Dump it and + generate a new one. Reload the rest of the creds also as the machinery + is all there. */ + + DEBUG(D_tls) debug_printf("selfsign cert rotate\n"); + tls_creds_expire = 0; + tls_daemon_creds_reload(); + } +else if (tls_watch_trigger_time && time(NULL) >= tls_watch_trigger_time + 5) { - tls_watch_trigger_time = 0; - tls_watch_triggered(); + /* Called, after a delay for multiple file ops to get done, from + the daemon when any of the watches added (above) fire. + Dump the set of watches and arrange to reload cached creds (which + will set up new watches). */ + + DEBUG(D_tls) debug_printf("watch triggered\n"); + tls_watch_trigger_time = tls_creds_expire = 0; + tls_daemon_creds_reload(); } #endif }