]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Tweak DNSSEC timestamp code to create file later, removing need to chown it.
authorSimon Kelley <simon@thekelleys.org.uk>
Sat, 7 Mar 2015 18:28:06 +0000 (18:28 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Sat, 7 Mar 2015 18:28:06 +0000 (18:28 +0000)
man/dnsmasq.8
src/dnsmasq.c
src/dnsmasq.h
src/dnssec.c

index 097e7d75145c4ae58a75f277d8215517124d7a06..2db780d90987f675fe70d72f9333aa1fd41bbf98 100644 (file)
@@ -678,7 +678,8 @@ which have not been throughly checked.
 Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the 
 system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and 
 its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried 
-over system restarts. 
+over system restarts. The timestamp file is created after dnsmasq has dropped root, so it must be in a location writable by the 
+unprivileged user that dnsmasq runs as.
 .TP
 .B --proxy-dnssec
 Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it.  This is an 
index 9e05c0e31569b6320f2e1e3a5668639b078f8423..f3e5bcffec4f8cd2b054b53eba616a7f25cef1cb 100644 (file)
@@ -58,9 +58,6 @@ int main (int argc, char **argv)
   struct dhcp_context *context;
   struct dhcp_relay *relay;
 #endif
-#ifdef HAVE_DNSSEC
-  int badtime;
-#endif
 
 #ifdef LOCALEDIR
   setlocale(LC_ALL, "");
@@ -156,10 +153,10 @@ int main (int argc, char **argv)
     {
 #ifdef HAVE_DNSSEC
       if (!daemon->ds)
-       die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
+       die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
       
       if (daemon->cachesize < CACHESIZ)
-       die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
+       die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
 #else 
       die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
 #endif
@@ -172,10 +169,10 @@ int main (int argc, char **argv)
 
 #ifdef HAVE_CONNTRACK
   if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
-    die (_("Cannot use --conntrack AND --query-port"), NULL, EC_BADCONF); 
+    die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF); 
 #else
   if (option_bool(OPT_CONNTRACK))
-    die(_("Conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
+    die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
 #endif
 
 #ifdef HAVE_SOLARIS_NETWORK
@@ -195,7 +192,7 @@ int main (int argc, char **argv)
 
 #ifndef HAVE_LOOP
   if (option_bool(OPT_LOOP_DETECT))
-    die(_("Loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
+    die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
 #endif
   
   now = dnsmasq_time();
@@ -373,10 +370,6 @@ int main (int argc, char **argv)
   if (baduser)
     die(_("unknown user or group: %s"), baduser, EC_BADCONF);
 
-#ifdef HAVE_DNSSEC  
-  badtime = setup_timestamp(ent_pw);
-#endif
-
   /* implement group defaults, "dip" if available, or group associated with uid */
   if (!daemon->group_set && !gp)
     {
@@ -693,10 +686,23 @@ int main (int argc, char **argv)
 #ifdef HAVE_DNSSEC
   if (option_bool(OPT_DNSSEC_VALID))
     {
+      int rc;
+
+      /* Delay creating the timestamp file until here, after we've changed user, so that
+        it has the correct owner to allow updating the mtime later. 
+        This means we have to report fatal errors via the pipe. */
+      if ((rc = setup_timestamp()) == -1)
+       {
+         send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
+         _exit(0);
+       }
+      
       my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
+      
       if (option_bool(OPT_DNSSEC_TIME))
        my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
-      if (badtime)
+      
+      if (rc == 1)
        my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
     }
 #endif
@@ -1170,6 +1176,9 @@ static void fatal_event(struct event_desc *ev, char *msg)
 
     case EVENT_TFTP_ERR:
       die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
+    
+    case EVENT_TIME_ERR:
+      die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
     }
 }      
       
index a451cb4dd03c394e1d1e80df2894f4fabba861d6..fc7259881358cbcb3abef65cf117bfe4482fa4f5 100644 (file)
@@ -167,6 +167,7 @@ struct event_desc {
 #define EVENT_INIT      21
 #define EVENT_NEWADDR   22
 #define EVENT_NEWROUTE  23
+#define EVENT_TIME_ERR  24
 
 /* Exit codes. */
 #define EC_GOOD        0
@@ -1152,7 +1153,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
 int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
 size_t filter_rrsigs(struct dns_header *header, size_t plen);
 unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
-int setup_timestamp(struct passwd *ent_pw);
+int setup_timestamp(void);
 
 /* util.c */
 void rand_init(void);
index c60eacf73c6bc8d0729e416c13e3233bb11b4ccc..ad0d6f072ba2fa9068717a2e805a8c437def7783 100644 (file)
@@ -397,18 +397,21 @@ static int serial_compare_32(unsigned long s1, unsigned long s2)
 
 /* Called at startup. If the timestamp file is configured and exists, put its mtime on
    timestamp_time. If it doesn't exist, create it, and set the mtime to 1-1-2015.
-   Change the ownership to the user we'll be running as, so that we can update the mtime.
+   return -1 -> Cannot create file.
+           0 -> not using timestamp, or timestamp exists and is in past.
+           1 -> timestamp exists and is in future.
 */
+
 static time_t timestamp_time;
 static int back_to_the_future;
 
-int setup_timestamp(struct passwd *ent_pw)
+int setup_timestamp(void)
 {
   struct stat statbuf;
   
   back_to_the_future = 0;
   
-  if (!option_bool(OPT_DNSSEC_VALID) || !daemon->timestamp_file)
+  if (!daemon->timestamp_file)
     return 0;
   
   if (stat(daemon->timestamp_file, &statbuf) != -1)
@@ -428,7 +431,8 @@ int setup_timestamp(struct passwd *ent_pw)
   
   if (errno == ENOENT)
     {
-      int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666);
+      /* NB. for explanation of O_EXCL flag, see comment on pidfile in dnsmasq.c */ 
+      int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK | O_EXCL, 0666);
       if (fd != -1)
        {
          struct utimbuf timbuf;
@@ -436,14 +440,12 @@ int setup_timestamp(struct passwd *ent_pw)
          close(fd);
          
          timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
-         if (utime(daemon->timestamp_file, &timbuf) == 0 &&
-             (!ent_pw || getuid() != 0 || chown(daemon->timestamp_file, ent_pw->pw_uid, -1) == 0))
+         if (utime(daemon->timestamp_file, &timbuf) == 0)
            goto check_and_exit;
        }
     }
 
-  die(_("Cannot create timestamp file %s: %s" ), daemon->timestamp_file, EC_BADCONF);
-  return 0;
+  return -1;
 }
 
 /* Check whether today/now is between date_start and date_end */