summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2015-03-07 18:28:06 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2015-03-07 18:28:06 +0000
commit360f2513ab12a9bf1e262d388dd2ea8a566590a3 (patch)
tree47782c5050ca3564975134f3416e1372cd95eefb
parent4c960fa90a975d20f75a1ecabd217247f1922c8f (diff)
downloaddnsmasq-domain_lookup.tar.gz
Tweak DNSSEC timestamp code to create file later, removing need to chown it.domain_lookup
-rw-r--r--man/dnsmasq.83
-rw-r--r--src/dnsmasq.c35
-rw-r--r--src/dnsmasq.h3
-rw-r--r--src/dnssec.c18
4 files changed, 36 insertions, 23 deletions
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 097e7d7..2db780d 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -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
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 9e05c0e..f3e5bcf 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -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);
}
}
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index a451cb4..fc72598 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -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);
diff --git a/src/dnssec.c b/src/dnssec.c
index c60eacf..ad0d6f0 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -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 */