]>
Commit | Line | Data |
---|---|---|
e5f58910 MT |
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 | |
d54a2ce4 | 4 | Subject: [PATCH 57/78] Tweak DNSSEC timestamp code to create file later, |
e5f58910 MT |
5 | removing need to chown it. |
6 | ||
7 | --- | |
8 | man/dnsmasq.8 | 3 ++- | |
9 | src/dnsmasq.c | 35 ++++++++++++++++++++++------------- | |
10 | src/dnsmasq.h | 3 ++- | |
11 | src/dnssec.c | 18 ++++++++++-------- | |
12 | 4 files changed, 36 insertions(+), 23 deletions(-) | |
13 | ||
14 | diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 | |
15 | index 097e7d75145c..2db780d90987 100644 | |
16 | --- a/man/dnsmasq.8 | |
17 | +++ b/man/dnsmasq.8 | |
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. | |
25 | .TP | |
26 | .B --proxy-dnssec | |
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 | |
30 | --- a/src/dnsmasq.c | |
31 | +++ b/src/dnsmasq.c | |
32 | @@ -58,9 +58,6 @@ int main (int argc, char **argv) | |
33 | struct dhcp_context *context; | |
34 | struct dhcp_relay *relay; | |
35 | #endif | |
36 | -#ifdef HAVE_DNSSEC | |
37 | - int badtime; | |
38 | -#endif | |
39 | ||
40 | #ifdef LOCALEDIR | |
41 | setlocale(LC_ALL, ""); | |
42 | @@ -156,10 +153,10 @@ int main (int argc, char **argv) | |
43 | { | |
44 | #ifdef HAVE_DNSSEC | |
45 | if (!daemon->ds) | |
46 | - die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF); | |
47 | + die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF); | |
48 | ||
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); | |
52 | #else | |
53 | die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF); | |
54 | #endif | |
55 | @@ -172,10 +169,10 @@ int main (int argc, char **argv) | |
56 | ||
57 | #ifdef HAVE_CONNTRACK | |
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); | |
61 | #else | |
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); | |
65 | #endif | |
66 | ||
67 | #ifdef HAVE_SOLARIS_NETWORK | |
68 | @@ -195,7 +192,7 @@ int main (int argc, char **argv) | |
69 | ||
70 | #ifndef HAVE_LOOP | |
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); | |
74 | #endif | |
75 | ||
76 | now = dnsmasq_time(); | |
77 | @@ -373,10 +370,6 @@ int main (int argc, char **argv) | |
78 | if (baduser) | |
79 | die(_("unknown user or group: %s"), baduser, EC_BADCONF); | |
80 | ||
81 | -#ifdef HAVE_DNSSEC | |
82 | - badtime = setup_timestamp(ent_pw); | |
83 | -#endif | |
84 | - | |
85 | /* implement group defaults, "dip" if available, or group associated with uid */ | |
86 | if (!daemon->group_set && !gp) | |
87 | { | |
88 | @@ -693,10 +686,23 @@ int main (int argc, char **argv) | |
89 | #ifdef HAVE_DNSSEC | |
90 | if (option_bool(OPT_DNSSEC_VALID)) | |
91 | { | |
92 | + int rc; | |
93 | + | |
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) | |
98 | + { | |
99 | + send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file); | |
100 | + _exit(0); | |
101 | + } | |
102 | + | |
103 | my_syslog(LOG_INFO, _("DNSSEC validation enabled")); | |
104 | + | |
105 | if (option_bool(OPT_DNSSEC_TIME)) | |
106 | my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload")); | |
107 | - if (badtime) | |
108 | + | |
109 | + if (rc == 1) | |
110 | my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid")); | |
111 | } | |
112 | #endif | |
113 | @@ -1170,6 +1176,9 @@ static void fatal_event(struct event_desc *ev, char *msg) | |
114 | ||
115 | case EVENT_TFTP_ERR: | |
116 | die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE); | |
117 | + | |
118 | + case EVENT_TIME_ERR: | |
119 | + die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF); | |
120 | } | |
121 | } | |
122 | ||
123 | diff --git a/src/dnsmasq.h b/src/dnsmasq.h | |
124 | index a451cb4dd03c..fc7259881358 100644 | |
125 | --- a/src/dnsmasq.h | |
126 | +++ b/src/dnsmasq.h | |
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 | |
132 | ||
133 | /* Exit codes. */ | |
134 | #define EC_GOOD 0 | |
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); | |
141 | ||
142 | /* util.c */ | |
143 | void rand_init(void); | |
144 | diff --git a/src/dnssec.c b/src/dnssec.c | |
145 | index c60eacf73c6b..ad0d6f072ba2 100644 | |
146 | --- a/src/dnssec.c | |
147 | +++ b/src/dnssec.c | |
148 | @@ -397,18 +397,21 @@ static int serial_compare_32(unsigned long s1, unsigned long s2) | |
149 | ||
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. | |
156 | */ | |
157 | + | |
158 | static time_t timestamp_time; | |
159 | static int back_to_the_future; | |
160 | ||
161 | -int setup_timestamp(struct passwd *ent_pw) | |
162 | +int setup_timestamp(void) | |
163 | { | |
164 | struct stat statbuf; | |
165 | ||
166 | back_to_the_future = 0; | |
167 | ||
168 | - if (!option_bool(OPT_DNSSEC_VALID) || !daemon->timestamp_file) | |
169 | + if (!daemon->timestamp_file) | |
170 | return 0; | |
171 | ||
172 | if (stat(daemon->timestamp_file, &statbuf) != -1) | |
173 | @@ -428,7 +431,8 @@ int setup_timestamp(struct passwd *ent_pw) | |
174 | ||
175 | if (errno == ENOENT) | |
176 | { | |
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); | |
180 | if (fd != -1) | |
181 | { | |
182 | struct utimbuf timbuf; | |
183 | @@ -436,14 +440,12 @@ int setup_timestamp(struct passwd *ent_pw) | |
184 | close(fd); | |
185 | ||
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) | |
190 | goto check_and_exit; | |
191 | } | |
192 | } | |
193 | ||
194 | - die(_("Cannot create timestamp file %s: %s" ), daemon->timestamp_file, EC_BADCONF); | |
195 | - return 0; | |
196 | + return -1; | |
197 | } | |
198 | ||
199 | /* Check whether today/now is between date_start and date_end */ | |
200 | -- | |
201 | 2.1.0 | |
202 |