aboutsummaryrefslogtreecommitdiff
path: root/daemon/remote.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/remote.c')
-rw-r--r--daemon/remote.c111
1 files changed, 98 insertions, 13 deletions
diff --git a/daemon/remote.c b/daemon/remote.c
index 64057a57b326..923ddefa4f29 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -130,7 +130,7 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
{
#ifndef S_SPLINT_S
size_t leftover;
- if(d == 0) {
+ if(d <= 0) {
avg->tv_sec = 0;
avg->tv_usec = 0;
return;
@@ -139,7 +139,13 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
avg->tv_usec = sum->tv_usec / d;
/* handle fraction from seconds divide */
leftover = sum->tv_sec - avg->tv_sec*d;
- avg->tv_usec += (leftover*1000000)/d;
+ if(leftover <= 0)
+ leftover = 0;
+ avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
+ if(avg->tv_sec < 0)
+ avg->tv_sec = 0;
+ if(avg->tv_usec < 0)
+ avg->tv_usec = 0;
#endif
}
@@ -364,13 +370,20 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
struct listen_port* l = NULL;
log_assert(cfg->remote_control_enable && cfg->control_port);
if(cfg->control_ifs.first) {
- struct config_strlist* p;
- for(p = cfg->control_ifs.first; p; p = p->next) {
- if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) {
+ char** rcif = NULL;
+ int i, num_rcif = 0;
+ if(!resolve_interface_names(NULL, 0, cfg->control_ifs.first,
+ &rcif, &num_rcif)) {
+ return NULL;
+ }
+ for(i=0; i<num_rcif; i++) {
+ if(!add_open(rcif[i], cfg->control_port, &l, 1, cfg)) {
listening_ports_free(l);
+ config_del_strarray(rcif, num_rcif);
return NULL;
}
}
+ config_del_strarray(rcif, num_rcif);
} else {
/* defaults */
if(cfg->do_ip6 &&
@@ -1291,10 +1304,35 @@ do_zones_remove(RES* ssl, struct local_zones* zones)
(void)ssl_printf(ssl, "removed %d zones\n", num);
}
+/** check syntax of newly added RR */
+static int
+check_RR_syntax(RES* ssl, char* str, int line)
+{
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len = sizeof(rr), dname_len = 0;
+ int s = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600,
+ NULL, 0, NULL, 0);
+ if(s != 0) {
+ char linestr[32];
+ if(line == 0)
+ linestr[0]=0;
+ else snprintf(linestr, sizeof(linestr), "line %d ", line);
+ if(!ssl_printf(ssl, "error parsing local-data at %sposition %d '%s': %s\n",
+ linestr, LDNS_WIREPARSE_OFFSET(s), str,
+ sldns_get_errorstr_parse(s)))
+ return 0;
+ return 0;
+ }
+ return 1;
+}
+
/** Add new RR data */
static int
-perform_data_add(RES* ssl, struct local_zones* zones, char* arg)
+perform_data_add(RES* ssl, struct local_zones* zones, char* arg, int line)
{
+ if(!check_RR_syntax(ssl, arg, line)) {
+ return 0;
+ }
if(!local_zones_add_RR(zones, arg)) {
ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg);
return 0;
@@ -1306,7 +1344,7 @@ perform_data_add(RES* ssl, struct local_zones* zones, char* arg)
static void
do_data_add(RES* ssl, struct local_zones* zones, char* arg)
{
- if(!perform_data_add(ssl, zones, arg))
+ if(!perform_data_add(ssl, zones, arg, 0))
return;
send_ok(ssl);
}
@@ -1316,15 +1354,12 @@ static void
do_datas_add(RES* ssl, struct local_zones* zones)
{
char buf[2048];
- int num = 0;
+ int num = 0, line = 0;
while(ssl_read_line(ssl, buf, sizeof(buf))) {
if(buf[0] == 0x04 && buf[1] == 0)
break; /* end of transmission */
- if(!perform_data_add(ssl, zones, buf)) {
- if(!ssl_printf(ssl, "error for input line: %s\n", buf))
- return;
- }
- else
+ line++;
+ if(perform_data_add(ssl, zones, buf, line))
num++;
}
(void)ssl_printf(ssl, "added %d datas\n", num);
@@ -2510,6 +2545,8 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
uint8_t* nm = NULL;
struct auth_zones* az = worker->env.auth_zones;
struct auth_zone* z = NULL;
+ struct auth_xfer* xfr = NULL;
+ char* reason = NULL;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return;
if(az) {
@@ -2518,19 +2555,63 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
if(z) {
lock_rw_wrlock(&z->lock);
}
+ xfr = auth_xfer_find(az, nm, nmlen, LDNS_RR_CLASS_IN);
+ if(xfr) {
+ lock_basic_lock(&xfr->lock);
+ }
lock_rw_unlock(&az->lock);
}
free(nm);
if(!z) {
+ if(xfr) {
+ lock_basic_unlock(&xfr->lock);
+ }
(void)ssl_printf(ssl, "error no auth-zone %s\n", arg);
return;
}
if(!auth_zone_read_zonefile(z, worker->env.cfg)) {
lock_rw_unlock(&z->lock);
+ if(xfr) {
+ lock_basic_unlock(&xfr->lock);
+ }
(void)ssl_printf(ssl, "error failed to read %s\n", arg);
return;
}
+
+ z->zone_expired = 0;
+ if(xfr) {
+ xfr->zone_expired = 0;
+ if(!xfr_find_soa(z, xfr)) {
+ if(z->data.count == 0) {
+ lock_rw_unlock(&z->lock);
+ lock_basic_unlock(&xfr->lock);
+ (void)ssl_printf(ssl, "zone %s has no contents\n", arg);
+ return;
+ }
+ lock_rw_unlock(&z->lock);
+ lock_basic_unlock(&xfr->lock);
+ (void)ssl_printf(ssl, "error: no SOA in zone after read %s\n", arg);
+ return;
+ }
+ if(xfr->have_zone)
+ xfr->lease_time = *worker->env.now;
+ lock_basic_unlock(&xfr->lock);
+ }
+
+ auth_zone_verify_zonemd(z, &worker->env, &worker->env.mesh->mods,
+ &reason, 0, 0);
+ if(reason && z->zone_expired) {
+ lock_rw_unlock(&z->lock);
+ (void)ssl_printf(ssl, "error zonemd for %s failed: %s\n",
+ arg, reason);
+ free(reason);
+ return;
+ } else if(reason && strcmp(reason, "ZONEMD verification successful")
+ ==0) {
+ (void)ssl_printf(ssl, "%s: %s\n", arg, reason);
+ }
lock_rw_unlock(&z->lock);
+ free(reason);
send_ok(ssl);
}
@@ -3257,7 +3338,11 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
if (!rc->use_cert) {
verbose(VERB_ALGO, "unauthenticated remote control connection");
} else if(SSL_get_verify_result(s->ssl) == X509_V_OK) {
+#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
+ X509* x = SSL_get1_peer_certificate(s->ssl);
+#else
X509* x = SSL_get_peer_certificate(s->ssl);
+#endif
if(!x) {
verbose(VERB_DETAIL, "remote control connection "
"provided no client certificate");