1 From 360f2513ab12a9bf1e262d388dd2ea8a566590a3 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Sat, 7 Mar 2015 18:28:06 +0000
4 Subject: [PATCH 057/113] Tweak DNSSEC timestamp code to create file later,
5 removing need to chown it.
9 src/dnsmasq.c | 35 ++++++++++++++++++++++-------------
11 src/dnssec.c | 18 ++++++++++--------
12 4 files changed, 36 insertions(+), 23 deletions(-)
14 diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
15 index 097e7d75145c..2db780d90987 100644
18 @@ -678,7 +678,8 @@ which have not been throughly checked.
19 Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
20 system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and
21 its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried
22 -over system restarts.
23 +over system restarts. The timestamp file is created after dnsmasq has dropped root, so it must be in a location writable by the
24 +unprivileged user that dnsmasq runs as.
27 Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
28 diff --git a/src/dnsmasq.c b/src/dnsmasq.c
29 index 9e05c0e31569..f3e5bcffec4f 100644
32 @@ -58,9 +58,6 @@ int main (int argc, char **argv)
33 struct dhcp_context *context;
34 struct dhcp_relay *relay;
41 setlocale(LC_ALL, "");
42 @@ -156,10 +153,10 @@ int main (int argc, char **argv)
46 - die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
47 + die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
49 if (daemon->cachesize < CACHESIZ)
50 - die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
51 + die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
53 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
55 @@ -172,10 +169,10 @@ int main (int argc, char **argv)
58 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
59 - die (_("Cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
60 + die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
62 if (option_bool(OPT_CONNTRACK))
63 - die(_("Conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
64 + die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
67 #ifdef HAVE_SOLARIS_NETWORK
68 @@ -195,7 +192,7 @@ int main (int argc, char **argv)
71 if (option_bool(OPT_LOOP_DETECT))
72 - die(_("Loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
73 + die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
77 @@ -373,10 +370,6 @@ int main (int argc, char **argv)
79 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
82 - badtime = setup_timestamp(ent_pw);
85 /* implement group defaults, "dip" if available, or group associated with uid */
86 if (!daemon->group_set && !gp)
88 @@ -693,10 +686,23 @@ int main (int argc, char **argv)
90 if (option_bool(OPT_DNSSEC_VALID))
94 + /* Delay creating the timestamp file until here, after we've changed user, so that
95 + it has the correct owner to allow updating the mtime later.
96 + This means we have to report fatal errors via the pipe. */
97 + if ((rc = setup_timestamp()) == -1)
99 + send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
103 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
105 if (option_bool(OPT_DNSSEC_TIME))
106 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
110 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
113 @@ -1170,6 +1176,9 @@ static void fatal_event(struct event_desc *ev, char *msg)
116 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
118 + case EVENT_TIME_ERR:
119 + die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
123 diff --git a/src/dnsmasq.h b/src/dnsmasq.h
124 index a451cb4dd03c..fc7259881358 100644
127 @@ -167,6 +167,7 @@ struct event_desc {
128 #define EVENT_INIT 21
129 #define EVENT_NEWADDR 22
130 #define EVENT_NEWROUTE 23
131 +#define EVENT_TIME_ERR 24
135 @@ -1152,7 +1153,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
136 int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
137 size_t filter_rrsigs(struct dns_header *header, size_t plen);
138 unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
139 -int setup_timestamp(struct passwd *ent_pw);
140 +int setup_timestamp(void);
143 void rand_init(void);
144 diff --git a/src/dnssec.c b/src/dnssec.c
145 index c60eacf73c6b..ad0d6f072ba2 100644
148 @@ -397,18 +397,21 @@ static int serial_compare_32(unsigned long s1, unsigned long s2)
150 /* Called at startup. If the timestamp file is configured and exists, put its mtime on
151 timestamp_time. If it doesn't exist, create it, and set the mtime to 1-1-2015.
152 - Change the ownership to the user we'll be running as, so that we can update the mtime.
153 + return -1 -> Cannot create file.
154 + 0 -> not using timestamp, or timestamp exists and is in past.
155 + 1 -> timestamp exists and is in future.
158 static time_t timestamp_time;
159 static int back_to_the_future;
161 -int setup_timestamp(struct passwd *ent_pw)
162 +int setup_timestamp(void)
166 back_to_the_future = 0;
168 - if (!option_bool(OPT_DNSSEC_VALID) || !daemon->timestamp_file)
169 + if (!daemon->timestamp_file)
172 if (stat(daemon->timestamp_file, &statbuf) != -1)
173 @@ -428,7 +431,8 @@ int setup_timestamp(struct passwd *ent_pw)
177 - int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666);
178 + /* NB. for explanation of O_EXCL flag, see comment on pidfile in dnsmasq.c */
179 + int fd = open(daemon->timestamp_file, O_WRONLY | O_CREAT | O_NONBLOCK | O_EXCL, 0666);
182 struct utimbuf timbuf;
183 @@ -436,14 +440,12 @@ int setup_timestamp(struct passwd *ent_pw)
186 timestamp_time = timbuf.actime = timbuf.modtime = 1420070400; /* 1-1-2015 */
187 - if (utime(daemon->timestamp_file, &timbuf) == 0 &&
188 - (!ent_pw || getuid() != 0 || chown(daemon->timestamp_file, ent_pw->pw_uid, -1) == 0))
189 + if (utime(daemon->timestamp_file, &timbuf) == 0)
194 - die(_("Cannot create timestamp file %s: %s" ), daemon->timestamp_file, EC_BADCONF);
199 /* Check whether today/now is between date_start and date_end */