Symlink following for TLS creds files
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 8 Aug 2022 18:46:03 +0000 (19:46 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 8 Aug 2022 20:48:43 +0000 (21:48 +0100)
doc/doc-txt/ChangeLog
src/src/tls.c

index 874d725f3ce6008f458a22b1a6cef87bd3e5f318..b813033c1ae914ca54f82b4381b45cc45b952112 100644 (file)
@@ -18,6 +18,11 @@ JH/04 Bug 2903: avoid exit on an attempt to rewrite a malformed address.
       Make the rewrite never match and keep the logging.  Trust the
       admin to be using verify=header-syntax (to actually reject the message).
 
+JH/05 Follow symlinks for placing a watch on TLS creds files.  This means
+      (under Linux) we watch the dir containing the final file; previously
+      it would be the dir with the first symlink.  We still do not monitor
+      the entire path.
+
 
 Exim version 4.96
 -----------------
index 3ed37bbb0680afd61c6cbe04e5f84769e39d2109..76e72b5f58a10f3da1bc0b5afd70d21428b8d545 100644 (file)
@@ -143,15 +143,29 @@ static BOOL
 tls_set_one_watch(const uschar * filename)
 # ifdef EXIM_HAVE_INOTIFY
 {
+uschar buf[PATH_MAX];
+ssize_t len;
 uschar * s;
 
 if (Ustrcmp(filename, "system,cache") == 0) return TRUE;
-
 if (!(s = Ustrrchr(filename, '/'))) return FALSE;
+
+for (unsigned loop = 20;
+     (len = readlink(CCS filename, CS buf, sizeof(buf))) >= 0; )
+  {                                            /* a symlink */
+  if (--loop == 0) { errno = ELOOP; return FALSE; }
+  filename = buf[0] == '/'
+    ? string_copyn(buf, (unsigned)len) /* mem released by tls_set_watch */
+    : string_sprintf("%.*s/%.*s", (int)(s - filename), (int)len);
+  s = Ustrrchr(filename, '/');
+  }
+if (errno != EINVAL)
+  return FALSE;                                        /* other error */
+
+/* not a symlink */
 s = string_copyn(filename, s - filename);      /* mem released by tls_set_watch */
-DEBUG(D_tls) debug_printf("watch dir '%s'\n", s);
 
-/*XXX unclear what effect symlinked files will have for inotify */
+DEBUG(D_tls) debug_printf("watch dir '%s'\n", s);
 
 if (inotify_add_watch(tls_watch_fd, CCS s,
       IN_ONESHOT | IN_CLOSE_WRITE | IN_DELETE | IN_DELETE_SELF