]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
AXFR over TLS
authorWillem Toorop <willem@nlnetlabs.nl>
Sun, 24 Mar 2019 09:43:57 +0000 (10:43 +0100)
committerWillem Toorop <willem@nlnetlabs.nl>
Sun, 24 Mar 2019 09:43:57 +0000 (10:43 +0100)
Enable by specifying an auth name, like this:
```
auth-zone:
        name: nlnetlabs.nl
        master: 185.49.140.60#ns.nlnetlabs.nl
```

services/authzone.c
services/outside_network.c
services/outside_network.h

index a87c2274fb9eccacade2c42c3019f142b866e390..2649867ed8279a0e0eeece9607eaafc69e6eefd5 100644 (file)
@@ -5034,6 +5034,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
        struct sockaddr_storage addr;
        socklen_t addrlen = 0;
        struct auth_master* master = xfr->task_transfer->master;
+       char *auth_name = NULL;
        if(!master) return 0;
        if(master->allow_notify) return 0; /* only for notify */
 
@@ -5042,7 +5043,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
                addrlen = xfr->task_transfer->scan_addr->addrlen;
                memmove(&addr, &xfr->task_transfer->scan_addr->addr, addrlen);
        } else {
-               if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+               if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) {
                        /* the ones that are not in addr format are supposed
                         * to be looked up.  The lookup has failed however,
                         * so skip them */
@@ -5091,7 +5092,8 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
        /* connect on fd */
        xfr->task_transfer->cp = outnet_comm_point_for_tcp(env->outnet,
                auth_xfer_transfer_tcp_callback, xfr, &addr, addrlen,
-               env->scratch_buffer, AUTH_TRANSFER_TIMEOUT);
+               env->scratch_buffer, AUTH_TRANSFER_TIMEOUT,
+               auth_name != NULL, auth_name);
        if(!xfr->task_transfer->cp) {
                char zname[255+1];
                dname_str(xfr->name, zname);
@@ -5809,6 +5811,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
        struct timeval t;
        /* pick master */
        struct auth_master* master = xfr_probe_current_master(xfr);
+       char *auth_name = NULL;
        if(!master) return 0;
        if(master->allow_notify) return 0; /* only for notify */
        if(master->http) return 0; /* only masters get SOA UDP probe,
@@ -5819,7 +5822,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
                addrlen = xfr->task_probe->scan_addr->addrlen;
                memmove(&addr, &xfr->task_probe->scan_addr->addr, addrlen);
        } else {
-               if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+               if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) {
                        /* the ones that are not in addr format are supposed
                         * to be looked up.  The lookup has failed however,
                         * so skip them */
@@ -5829,6 +5832,18 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
                                zname, master->host);
                        return 0;
                }
+               if (auth_name != NULL) {
+                       if (addr.ss_family == AF_INET
+                       &&  ntohs(((struct sockaddr_in *)&addr)->sin_port)
+                           == 853)
+                               ((struct sockaddr_in *)&addr)->sin_port
+                                       = htons(53);
+                       else if (addr.ss_family == AF_INET6
+                       &&  ntohs(((struct sockaddr_in6 *)&addr)->sin6_port)
+                           == 853)
+                               ((struct sockaddr_in6 *)&addr)->sin6_port
+                                       = htons(853);
+               }
        }
 
        /* create packet */
index 3347c38e7aa9b3ded4ca3980104a756f07ca1e09..e687e405e536e972287ef3161931f2c336f7d71d 100644 (file)
@@ -2285,7 +2285,7 @@ struct comm_point*
 outnet_comm_point_for_tcp(struct outside_network* outnet,
        comm_point_callback_type* cb, void* cb_arg,
        struct sockaddr_storage* to_addr, socklen_t to_addrlen,
-       sldns_buffer* query, int timeout)
+       sldns_buffer* query, int timeout, int ssl, char* host)
 {
        struct comm_point* cp;
        int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
@@ -2305,6 +2305,53 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
        }
        cp->repinfo.addrlen = to_addrlen;
        memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+
+       /* setup for SSL (if needed) */
+       if(ssl) {
+               cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
+               if(!cp->ssl) {
+                       log_err("cannot setup https");
+                       comm_point_delete(cp);
+                       return NULL;
+               }
+#ifdef USE_WINSOCK
+               comm_point_tcp_win_bio_cb(cp, cp->ssl);
+#endif
+               cp->ssl_shake_state = comm_ssl_shake_write;
+               /* https verification */
+#ifdef HAVE_SSL_SET1_HOST
+               if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+                       /* because we set SSL_VERIFY_PEER, in netevent in
+                        * ssl_handshake, it'll check if the certificate
+                        * verification has succeeded */
+                       /* SSL_VERIFY_PEER is set on the sslctx */
+                       /* and the certificates to verify with are loaded into
+                        * it with SSL_load_verify_locations or
+                        * SSL_CTX_set_default_verify_paths */
+                       /* setting the hostname makes openssl verify the
+                        * host name in the x509 certificate in the
+                        * SSL connection*/
+                       if(!SSL_set1_host(cp->ssl, host)) {
+                               log_err("SSL_set1_host failed");
+                               comm_point_delete(cp);
+                               return NULL;
+                       }
+               }
+#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+               /* openssl 1.0.2 has this function that can be used for
+                * set1_host like verification */
+               if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+                       X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
+                       X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+                       if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
+                               log_err("X509_VERIFY_PARAM_set1_host failed");
+                               comm_point_delete(cp);
+                               return NULL;
+                       }
+               }
+#endif /* HAVE_SSL_SET1_HOST */
+       }
+
        /* set timeout on TCP connection */
        comm_point_start_listening(cp, fd, timeout);
        /* copy scratch buffer to cp->buffer */
index 48ef03edba7cec2771248c544ca6485908038c47..79e32bcbfd50df0b0e28687cca10c3219f27a957 100644 (file)
@@ -575,7 +575,7 @@ struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
 struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
        comm_point_callback_type* cb, void* cb_arg,
        struct sockaddr_storage* to_addr, socklen_t to_addrlen,
-       struct sldns_buffer* query, int timeout);
+       struct sldns_buffer* query, int timeout, int ssl, char* host);
 
 /**
  * Create http commpoint suitable for communication to the destination.