Author: des
Date: Mon Jan  5 14:59:18 2015
New Revision: 276699
URL: https://svnweb.freebsd.org/changeset/base/276699

Log:
  mfv (r276698): support for remote control over local sockets.

Modified:
  head/contrib/unbound/config.h
  head/contrib/unbound/config.h.in
  head/contrib/unbound/configure.ac
  head/contrib/unbound/daemon/remote.c
  head/contrib/unbound/daemon/remote.h
  head/contrib/unbound/daemon/unbound.c
  head/contrib/unbound/doc/unbound.conf.5
  head/contrib/unbound/doc/unbound.conf.5.in
  head/contrib/unbound/services/listen_dnsport.c
  head/contrib/unbound/services/listen_dnsport.h
  head/contrib/unbound/smallapp/unbound-checkconf.c
  head/contrib/unbound/smallapp/unbound-control.c
  head/contrib/unbound/util/config_file.c
  head/contrib/unbound/util/config_file.h
  head/contrib/unbound/util/configlexer.lex
  head/contrib/unbound/util/configparser.y
  head/contrib/unbound/util/net_help.c
Directory Properties:
  head/contrib/unbound/   (props changed)

Modified: head/contrib/unbound/config.h
==============================================================================
--- head/contrib/unbound/config.h       Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/config.h       Mon Jan  5 14:59:18 2015        
(r276699)
@@ -381,6 +381,9 @@
 /* Define to 1 if you have the <sys/uio.h> header file. */
 #define HAVE_SYS_UIO_H 1
 
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
 /* Define to 1 if you have the <sys/wait.h> header file. */
 #define HAVE_SYS_WAIT_H 1
 
@@ -429,7 +432,8 @@
 /* if lex has yylex_destroy */
 #define LEX_HAS_YYLEX_DESTROY 1
 
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
 #define LT_OBJDIR ".libs/"
 
 /* Define to the maximum message length to pass to syslog. */

Modified: head/contrib/unbound/config.h.in
==============================================================================
--- head/contrib/unbound/config.h.in    Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/config.h.in    Mon Jan  5 14:59:18 2015        
(r276699)
@@ -380,6 +380,9 @@
 /* Define to 1 if you have the <sys/uio.h> header file. */
 #undef HAVE_SYS_UIO_H
 
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
 /* Define to 1 if you have the <sys/wait.h> header file. */
 #undef HAVE_SYS_WAIT_H
 
@@ -428,7 +431,8 @@
 /* if lex has yylex_destroy */
 #undef LEX_HAS_YYLEX_DESTROY
 
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
 #undef LT_OBJDIR
 
 /* Define to the maximum message length to pass to syslog. */

Modified: head/contrib/unbound/configure.ac
==============================================================================
--- head/contrib/unbound/configure.ac   Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/configure.ac   Mon Jan  5 14:59:18 2015        
(r276699)
@@ -266,7 +266,7 @@ AC_CHECK_TOOL(STRIP, strip)
 ACX_LIBTOOL_C_ONLY
 
 # Checks for header files.
-AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h 
sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h 
grp.h login_cap.h winsock2.h ws2tcpip.h endian.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h 
sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h 
glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h],,, 
[AC_INCLUDES_DEFAULT])
 
 # check for types.  
 # Using own tests for int64* because autoconf builtin only give 32bit.

Modified: head/contrib/unbound/daemon/remote.c
==============================================================================
--- head/contrib/unbound/daemon/remote.c        Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/daemon/remote.c        Mon Jan  5 14:59:18 2015        
(r276699)
@@ -46,6 +46,10 @@
 #ifdef HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
 #endif
+#ifndef HEADER_DH_H
+#include <openssl/dh.h>
+#endif
+
 #include <ctype.h>
 #include "daemon/remote.h"
 #include "daemon/worker.h"
@@ -82,6 +86,9 @@
 #ifdef HAVE_SYS_TYPES_H
 #  include <sys/types.h>
 #endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
@@ -131,6 +138,39 @@ timeval_divide(struct timeval* avg, cons
 #endif
 }
 
+/*
+ * The following function was generated using the openssl utility, using
+ * the command : "openssl dhparam -dsaparam -C 512"
+ */
+DH *get_dh512()
+{
+       static unsigned char dh512_p[]={
+               0xC9,0xD7,0x05,0xDA,0x5F,0xAB,0x14,0xE8,0x11,0x56,0x77,0x85,
+               0xB1,0x24,0x2C,0x95,0x60,0xEA,0xE2,0x10,0x6F,0x0F,0x84,0xEC,
+               0xF4,0x45,0xE8,0x90,0x7A,0xA7,0x03,0xFF,0x5B,0x88,0x53,0xDE,
+               0xC4,0xDE,0xBC,0x42,0x78,0x71,0x23,0x7E,0x24,0xA5,0x5E,0x4E,
+               0xEF,0x6F,0xFF,0x5F,0xAF,0xBE,0x8A,0x77,0x62,0xB4,0x65,0x82,
+               0x7E,0xC9,0xED,0x2F,
+       };
+       static unsigned char dh512_g[]={
+               0x8D,0x3A,0x52,0xBC,0x8A,0x71,0x94,0x33,0x2F,0xE1,0xE8,0x4C,
+               0x73,0x47,0x03,0x4E,0x7D,0x40,0xE5,0x84,0xA0,0xB5,0x6D,0x10,
+               0x6F,0x90,0x43,0x05,0x1A,0xF9,0x0B,0x6A,0xD1,0x2A,0x9C,0x25,
+               0x0A,0xB9,0xD1,0x14,0xDC,0x35,0x1C,0x48,0x7C,0xC6,0x0C,0x6D,
+               0x32,0x1D,0xD3,0xC8,0x10,0xA8,0x82,0x14,0xA2,0x1C,0xF4,0x53,
+               0x23,0x3B,0x1C,0xB9,
+       };
+       DH *dh;
+
+       if ((dh=DH_new()) == NULL) return(NULL);
+       dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
+       dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
+       if ((dh->p == NULL) || (dh->g == NULL))
+       { DH_free(dh); return(NULL); }
+       dh->length = 160;
+       return(dh);
+}
+
 struct daemon_remote*
 daemon_remote_create(struct config_file* cfg)
 {
@@ -165,6 +205,24 @@ daemon_remote_create(struct config_file*
                daemon_remote_delete(rc);
                return NULL;
        }
+
+       if (cfg->remote_control_use_cert == 0) {
+               /* No certificates are requested */
+               if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) {
+                       log_crypto_err("Failed to set aNULL cipher list");
+                       return NULL;
+               }
+
+               /* Since we have no certificates and hence no source of
+                * DH params, let's generate and set them
+                */
+               if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh512())) {
+                       log_crypto_err("Wanted to set DH param, but failed");
+                       return NULL;
+               }
+               return rc;
+       }
+       rc->use_cert = 1;
        s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
        s_key = fname_after_chroot(cfg->server_key_file, cfg, 1);
        if(!s_cert || !s_key) {
@@ -244,7 +302,8 @@ void daemon_remote_delete(struct daemon_
  * @return false on failure.
  */
 static int
-add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
+add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
+       struct config_file* cfg)
 {
        struct addrinfo hints;
        struct addrinfo* res;
@@ -255,29 +314,46 @@ add_open(const char* ip, int nr, struct 
        snprintf(port, sizeof(port), "%d", nr);
        port[sizeof(port)-1]=0;
        memset(&hints, 0, sizeof(hints));
-       hints.ai_socktype = SOCK_STREAM;
-       hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-       if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
-#ifdef USE_WINSOCK
-               if(!noproto_is_err && r == EAI_NONAME) {
-                       /* tried to lookup the address as name */
-                       return 1; /* return success, but do nothing */
+
+       if(ip[0] == '/') {
+               /* This looks like a local socket */
+               fd = create_local_accept_sock(ip, &noproto);
+               /*
+                * Change socket ownership and permissions so users other
+                * than root can access it provided they are in the same
+                * group as the user we run as.
+                */
+               if(fd != -1) {
+                       if (cfg->username && cfg->username[0])
+                               chown(ip, cfg->uid, cfg->gid);
+                       chmod(ip, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
                }
+       } else {
+               hints.ai_socktype = SOCK_STREAM;
+               hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+               if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
+#ifdef USE_WINSOCK
+                       if(!noproto_is_err && r == EAI_NONAME) {
+                               /* tried to lookup the address as name */
+                               return 1; /* return success, but do nothing */
+                       }
 #endif /* USE_WINSOCK */
-                log_err("control interface %s:%s getaddrinfo: %s %s",
-                       ip?ip:"default", port, gai_strerror(r),
+                       log_err("control interface %s:%s getaddrinfo: %s %s",
+                               ip?ip:"default", port, gai_strerror(r),
 #ifdef EAI_SYSTEM
-                       r==EAI_SYSTEM?(char*)strerror(errno):""
+                               r==EAI_SYSTEM?(char*)strerror(errno):""
 #else
-                       ""
+                               ""
 #endif
                        );
-               return 0;
+                       return 0;
+               }
+
+               /* open fd */
+               fd = create_tcp_accept_sock(res, 1, &noproto, 0);
+               freeaddrinfo(res);
        }
 
-       /* open fd */
-       fd = create_tcp_accept_sock(res, 1, &noproto, 0);
-       freeaddrinfo(res);
        if(fd == -1 && noproto) {
                if(!noproto_is_err)
                        return 1; /* return success, but do nothing */
@@ -314,7 +390,7 @@ struct listen_port* daemon_remote_open_p
        if(cfg->control_ifs) {
                struct config_strlist* p;
                for(p = cfg->control_ifs; p; p = p->next) {
-                       if(!add_open(p->str, cfg->control_port, &l, 1)) {
+                       if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) {
                                listening_ports_free(l);
                                return NULL;
                        }
@@ -322,12 +398,12 @@ struct listen_port* daemon_remote_open_p
        } else {
                /* defaults */
                if(cfg->do_ip6 &&
-                       !add_open("::1", cfg->control_port, &l, 0)) {
+                       !add_open("::1", cfg->control_port, &l, 0, cfg)) {
                        listening_ports_free(l);
                        return NULL;
                }
                if(cfg->do_ip4 &&
-                       !add_open("127.0.0.1", cfg->control_port, &l, 1)) {
+                       !add_open("127.0.0.1", cfg->control_port, &l, 1, cfg)) {
                        listening_ports_free(l);
                        return NULL;
                }
@@ -2434,7 +2510,9 @@ int remote_control_callback(struct comm_
        s->shake_state = rc_none;
 
        /* once handshake has completed, check authentication */
-       if(SSL_get_verify_result(s->ssl) == X509_V_OK) {
+       if (!rc->use_cert) {
+               verbose(VERB_ALGO, "unauthenticated remote control connection");
+       } else if(SSL_get_verify_result(s->ssl) == X509_V_OK) {
                X509* x = SSL_get_peer_certificate(s->ssl);
                if(!x) {
                        verbose(VERB_DETAIL, "remote control connection "

Modified: head/contrib/unbound/daemon/remote.h
==============================================================================
--- head/contrib/unbound/daemon/remote.h        Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/daemon/remote.h        Mon Jan  5 14:59:18 2015        
(r276699)
@@ -89,6 +89,8 @@ struct daemon_remote {
        struct worker* worker;
        /** commpoints for accepting remote control connections */
        struct listen_list* accept_list;
+       /* if certificates are used */
+       int use_cert;
        /** number of active commpoints that are handling remote control */
        int active;
        /** max active commpoints */

Modified: head/contrib/unbound/daemon/unbound.c
==============================================================================
--- head/contrib/unbound/daemon/unbound.c       Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/daemon/unbound.c       Mon Jan  5 14:59:18 2015        
(r276699)
@@ -441,20 +441,14 @@ static void
 perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
        const char** cfgfile)
 {
+       log_assert(cfg);
+
 #ifdef HAVE_GETPWNAM
        struct passwd *pwd = NULL;
-       uid_t uid;
-       gid_t gid;
-       /* initialize, but not to 0 (root) */
-       memset(&uid, 112, sizeof(uid));
-       memset(&gid, 112, sizeof(gid));
-       log_assert(cfg);
 
        if(cfg->username && cfg->username[0]) {
                if((pwd = getpwnam(cfg->username)) == NULL)
                        fatal_exit("user '%s' does not exist.", cfg->username);
-               uid = pwd->pw_uid;
-               gid = pwd->pw_gid;
                /* endpwent below, in case we need pwd for setusercontext */
        }
 #endif
@@ -511,18 +505,11 @@ perform_setup(struct daemon* daemon, str
 #ifdef HAVE_KILL
        if(cfg->pidfile && cfg->pidfile[0]) {
                writepid(daemon->pidfile, getpid());
-               if(!(cfg->chrootdir && cfg->chrootdir[0]) || 
-                       (cfg->chrootdir && cfg->chrootdir[0] && 
-                       strncmp(daemon->pidfile, cfg->chrootdir, 
-                       strlen(cfg->chrootdir))==0)) {
-                       /* delete of pidfile could potentially work,
-                        * chown to get permissions */
-                       if(cfg->username && cfg->username[0]) {
-                         if(chown(daemon->pidfile, uid, gid) == -1) {
+               if(cfg->username && cfg->username[0]) {
+                       if(chown(daemon->pidfile, cfg->uid, cfg->gid) == -1) {
                                log_err("cannot chown %u.%u %s: %s",
-                                       (unsigned)uid, (unsigned)gid,
+                                       (unsigned)cfg->uid, (unsigned)cfg->gid,
                                        daemon->pidfile, strerror(errno));
-                         }
                        }
                }
        }
@@ -537,7 +524,7 @@ perform_setup(struct daemon* daemon, str
                /* setusercontext does initgroups, setuid, setgid, and
                 * also resource limits from login config, but we
                 * still call setresuid, setresgid to be sure to set all uid*/
-               if(setusercontext(NULL, pwd, uid, (unsigned)
+               if(setusercontext(NULL, pwd, cfg->uid, (unsigned)
                        LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
                        log_warn("unable to setusercontext %s: %s",
                                cfg->username, strerror(errno));
@@ -601,27 +588,27 @@ perform_setup(struct daemon* daemon, str
 #ifdef HAVE_GETPWNAM
        if(cfg->username && cfg->username[0]) {
 #  ifdef HAVE_INITGROUPS
-               if(initgroups(cfg->username, gid) != 0)
+               if(initgroups(cfg->username, cfg->gid) != 0)
                        log_warn("unable to initgroups %s: %s",
                                cfg->username, strerror(errno));
 #  endif /* HAVE_INITGROUPS */
                endpwent();
 
 #ifdef HAVE_SETRESGID
-               if(setresgid(gid,gid,gid) != 0)
+               if(setresgid(cfg->gid,cfg->gid,cfg->gid) != 0)
 #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
-               if(setregid(gid,gid) != 0)
+               if(setregid(cfg->gid,cfg->gid) != 0)
 #else /* use setgid */
-               if(setgid(gid) != 0)
+               if(setgid(cfg->gid) != 0)
 #endif /* HAVE_SETRESGID */
                        fatal_exit("unable to set group id of %s: %s", 
                                cfg->username, strerror(errno));
 #ifdef HAVE_SETRESUID
-               if(setresuid(uid,uid,uid) != 0)
+               if(setresuid(cfg->uid,cfg->uid,cfg->uid) != 0)
 #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
-               if(setreuid(uid,uid) != 0)
+               if(setreuid(cfg->uid,cfg->uid) != 0)
 #else /* use setuid */
-               if(setuid(uid) != 0)
+               if(setuid(cfg->uid) != 0)
 #endif /* HAVE_SETRESUID */
                        fatal_exit("unable to set user id of %s: %s", 
                                cfg->username, strerror(errno));

Modified: head/contrib/unbound/doc/unbound.conf.5
==============================================================================
--- head/contrib/unbound/doc/unbound.conf.5     Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/doc/unbound.conf.5     Mon Jan  5 14:59:18 2015        
(r276699)
@@ -958,36 +958,47 @@ to setup SSLv3 / TLSv1 security for the 
 section for options.  To setup the correct self\-signed certificates use the
 \fIunbound\-control\-setup\fR(8) utility.
 .TP 5
-.B control\-enable:     \fI<yes or no>
+.B control\-enable: \fI<yes or no>
 The option is used to enable remote control, default is "no".
 If turned off, the server does not listen for control commands.
 .TP 5
-.B control\-interface: <ip address>
-Give IPv4 or IPv6 addresses to listen on for control commands.
+.B control\-interface: \fI<ip address or path>
+Give IPv4 or IPv6 addresses or local socket path to listen on for
+control commands.
 By default localhost (127.0.0.1 and ::1) is listened to.
 Use 0.0.0.0 and ::0 to listen to all interfaces.
+If you change this and permissions have been dropped, you must restart
+the server for the change to take effect.
 .TP 5
-.B control\-port: <port number>
-The port number to listen on for control commands, default is 8953.
-If you change this port number, and permissions have been dropped,
-a reload is not sufficient to open the port again, you must then restart.
+.B control\-port: \fI<port number>
+The port number to listen on for IPv4 or IPv6 control interfaces,
+default is 8953.
+If you change this and permissions have been dropped, you must restart
+the server for the change to take effect.
+.TP 5
+.B control-use-cert: \fI<yes or no>
+Whether to require certificate authentication of control connections.
+The default is "yes".
+This should not be changed unless there are other mechanisms in place
+to prevent untrusted users from accessing the remote control
+interface.
 .TP 5
-.B server\-key\-file: "<private key file>"
+.B server\-key\-file: \fI<private key file>
 Path to the server private key, by default unbound_server.key.
 This file is generated by the \fIunbound\-control\-setup\fR utility.
 This file is used by the unbound server, but not by \fIunbound\-control\fR.
 .TP 5
-.B server\-cert\-file: "<certificate file.pem>"
+.B server\-cert\-file: \fI<certificate file.pem>
 Path to the server self signed certificate, by default unbound_server.pem.
 This file is generated by the \fIunbound\-control\-setup\fR utility.
 This file is used by the unbound server, and also by \fIunbound\-control\fR.
 .TP 5
-.B control\-key\-file: "<private key file>"
+.B control\-key\-file: \fI<private key file>
 Path to the control client private key, by default unbound_control.key.
 This file is generated by the \fIunbound\-control\-setup\fR utility.
 This file is used by \fIunbound\-control\fR.
 .TP 5
-.B control\-cert\-file: "<certificate file.pem>"
+.B control\-cert\-file: \fI<certificate file.pem>
 Path to the control client certificate, by default unbound_control.pem.
 This certificate has to be signed with the server certificate.
 This file is generated by the \fIunbound\-control\-setup\fR utility.

Modified: head/contrib/unbound/doc/unbound.conf.5.in
==============================================================================
--- head/contrib/unbound/doc/unbound.conf.5.in  Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/doc/unbound.conf.5.in  Mon Jan  5 14:59:18 2015        
(r276699)
@@ -958,36 +958,47 @@ to setup SSLv3 / TLSv1 security for the 
 section for options.  To setup the correct self\-signed certificates use the
 \fIunbound\-control\-setup\fR(8) utility.
 .TP 5
-.B control\-enable:     \fI<yes or no>
+.B control\-enable: \fI<yes or no>
 The option is used to enable remote control, default is "no".
 If turned off, the server does not listen for control commands.
 .TP 5
-.B control\-interface: <ip address>
-Give IPv4 or IPv6 addresses to listen on for control commands.
+.B control\-interface: \fI<ip address or path>
+Give IPv4 or IPv6 addresses or local socket path to listen on for
+control commands.
 By default localhost (127.0.0.1 and ::1) is listened to.
 Use 0.0.0.0 and ::0 to listen to all interfaces.
+If you change this and permissions have been dropped, you must restart
+the server for the change to take effect.
 .TP 5
-.B control\-port: <port number>
-The port number to listen on for control commands, default is 8953.
-If you change this port number, and permissions have been dropped,
-a reload is not sufficient to open the port again, you must then restart.
+.B control\-port: \fI<port number>
+The port number to listen on for IPv4 or IPv6 control interfaces,
+default is 8953.
+If you change this and permissions have been dropped, you must restart
+the server for the change to take effect.
+.TP 5
+.B control-use-cert: \fI<yes or no>
+Whether to require certificate authentication of control connections.
+The default is "yes".
+This should not be changed unless there are other mechanisms in place
+to prevent untrusted users from accessing the remote control
+interface.
 .TP 5
-.B server\-key\-file: "<private key file>"
+.B server\-key\-file: \fI<private key file>
 Path to the server private key, by default unbound_server.key.
 This file is generated by the \fIunbound\-control\-setup\fR utility.
 This file is used by the unbound server, but not by \fIunbound\-control\fR.
 .TP 5
-.B server\-cert\-file: "<certificate file.pem>"
+.B server\-cert\-file: \fI<certificate file.pem>
 Path to the server self signed certificate, by default unbound_server.pem.
 This file is generated by the \fIunbound\-control\-setup\fR utility.
 This file is used by the unbound server, and also by \fIunbound\-control\fR.
 .TP 5
-.B control\-key\-file: "<private key file>"
+.B control\-key\-file: \fI<private key file>
 Path to the control client private key, by default unbound_control.key.
 This file is generated by the \fIunbound\-control\-setup\fR utility.
 This file is used by \fIunbound\-control\fR.
 .TP 5
-.B control\-cert\-file: "<certificate file.pem>"
+.B control\-cert\-file: \fI<certificate file.pem>
 Path to the control client certificate, by default unbound_control.pem.
 This certificate has to be signed with the server certificate.
 This file is generated by the \fIunbound\-control\-setup\fR utility.

Modified: head/contrib/unbound/services/listen_dnsport.c
==============================================================================
--- head/contrib/unbound/services/listen_dnsport.c      Mon Jan  5 14:55:52 
2015        (r276698)
+++ head/contrib/unbound/services/listen_dnsport.c      Mon Jan  5 14:59:18 
2015        (r276699)
@@ -56,6 +56,10 @@
 #endif
 #include <fcntl.h>
 
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
 /** number of queued TCP connections for listen() */
 #define TCP_BACKLOG 256 
 
@@ -571,6 +575,56 @@ create_tcp_accept_sock(struct addrinfo *
        return s;
 }
 
+int
+create_local_accept_sock(char *path, int* noproto)
+{
+#ifdef HAVE_SYS_UN_H
+       int s;
+       struct sockaddr_un sun;
+
+       sun.sun_len = sizeof(sun);
+       sun.sun_family = AF_LOCAL;
+       strlcpy(sun.sun_path, path, 104);
+
+       if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {
+               log_err("Cannot create local socket %s (%s)",
+                       path, strerror(errno));
+               return -1;
+       }
+
+       if (unlink(path) && errno != ENOENT) {
+               /* The socket already exists and cannot be removed */
+               log_err("Cannot remove old local socket %s (%s)",
+                       path, strerror(errno));
+               return -1;
+       }
+
+       if (bind(s, (struct sockaddr *)&sun,
+               sizeof(struct sockaddr_un)) == -1) {
+               log_err("Cannot bind local socket %s (%s)",
+                       path, strerror(errno));
+               return -1;
+       }
+
+       if (!fd_set_nonblock(s)) {
+               log_err("Cannot set non-blocking mode");
+               return -1;
+       }
+
+       if (listen(s, TCP_BACKLOG) == -1) {
+               log_err("can't listen: %s", strerror(errno));
+               return -1;
+       }
+
+       return s;
+#else
+       log_err("Local sockets are not supported");
+       *noproto = 1;
+       return -1;
+#endif
+}
+
+
 /**
  * Create socket from getaddrinfo results
  */

Modified: head/contrib/unbound/services/listen_dnsport.h
==============================================================================
--- head/contrib/unbound/services/listen_dnsport.h      Mon Jan  5 14:55:52 
2015        (r276698)
+++ head/contrib/unbound/services/listen_dnsport.h      Mon Jan  5 14:59:18 
2015        (r276699)
@@ -207,4 +207,13 @@ int create_udp_sock(int family, int sock
 int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
        int* reuseport);
 
+/**
+ * Create and bind local listening socket
+ * @param path: path to the socket.
+ * @param noproto: on error, this is set true if cause is that local sockets
+ *     are not supported.
+ * @return: the socket. -1 on error.
+ */
+int create_local_accept_sock(char* path, int* noproto);
+
 #endif /* LISTEN_DNSPORT_H */

Modified: head/contrib/unbound/smallapp/unbound-checkconf.c
==============================================================================
--- head/contrib/unbound/smallapp/unbound-checkconf.c   Mon Jan  5 14:55:52 
2015        (r276698)
+++ head/contrib/unbound/smallapp/unbound-checkconf.c   Mon Jan  5 14:59:18 
2015        (r276699)
@@ -416,7 +416,7 @@ morechecks(struct config_file* cfg, cons
                endpwent();
        }
 #endif
-       if(cfg->remote_control_enable) {
+       if(cfg->remote_control_enable && cfg->remote_control_use_cert) {
                check_chroot_string("server-key-file", &cfg->server_key_file,
                        cfg->chrootdir, cfg);
                check_chroot_string("server-cert-file", &cfg->server_cert_file,

Modified: head/contrib/unbound/smallapp/unbound-control.c
==============================================================================
--- head/contrib/unbound/smallapp/unbound-control.c     Mon Jan  5 14:55:52 
2015        (r276698)
+++ head/contrib/unbound/smallapp/unbound-control.c     Mon Jan  5 14:59:18 
2015        (r276699)
@@ -59,6 +59,10 @@
 #include "util/locks.h"
 #include "util/net_help.h"
 
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
 /** Give unbound-control usage, and exit (1). */
 static void
 usage()
@@ -139,29 +143,37 @@ setup_ctx(struct config_file* cfg)
        char* s_cert, *c_key, *c_cert;
        SSL_CTX* ctx;
 
-       s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
-       c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
-       c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
-       if(!s_cert || !c_key || !c_cert)
-               fatal_exit("out of memory");
+       if(cfg->remote_control_use_cert) {
+               s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
+               c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
+               c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
+               if(!s_cert || !c_key || !c_cert)
+                       fatal_exit("out of memory");
+       }
         ctx = SSL_CTX_new(SSLv23_client_method());
        if(!ctx)
                ssl_err("could not allocate SSL_CTX pointer");
         if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2))
                ssl_err("could not set SSL_OP_NO_SSLv2");
-        if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3))
-               ssl_err("could not set SSL_OP_NO_SSLv3");
-       if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) ||
-               !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
-               || !SSL_CTX_check_private_key(ctx))
-               ssl_err("Error setting up SSL_CTX client key and cert");
-       if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
-               ssl_err("Error setting up SSL_CTX verify, server cert");
-       SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
-
-       free(s_cert);
-       free(c_key);
-       free(c_cert);
+        if(cfg->remote_control_use_cert) {
+               if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & 
SSL_OP_NO_SSLv3))
+                       ssl_err("could not set SSL_OP_NO_SSLv3");
+               if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) ||
+                   !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
+                   || !SSL_CTX_check_private_key(ctx))
+                       ssl_err("Error setting up SSL_CTX client key and cert");
+               if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
+                       ssl_err("Error setting up SSL_CTX verify, server cert");
+               SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+
+               free(s_cert);
+               free(c_key);
+               free(c_cert);
+       } else {
+               /* Use ciphers that don't require authentication  */
+               if(!SSL_CTX_set_cipher_list(ctx, "aNULL"))
+                       ssl_err("Error setting NULL cipher!");
+       }
        return ctx;
 }
 
@@ -171,6 +183,7 @@ contact_server(const char* svr, struct c
 {
        struct sockaddr_storage addr;
        socklen_t addrlen;
+       int addrfamily = 0;
        int fd;
        /* use svr or the first config entry */
        if(!svr) {
@@ -189,12 +202,23 @@ contact_server(const char* svr, struct c
        if(strchr(svr, '@')) {
                if(!extstrtoaddr(svr, &addr, &addrlen))
                        fatal_exit("could not parse IP@port: %s", svr);
+#ifdef HAVE_SYS_UN_H
+       } else if(svr[0] == '/') {
+               struct sockaddr_un* sun = (struct sockaddr_un *) &addr;
+               sun->sun_family = AF_LOCAL;
+               sun->sun_len = sizeof(sun);
+               strlcpy(sun->sun_path, svr, 104);
+               addrlen = sizeof(struct sockaddr_un);
+               addrfamily = AF_LOCAL;
+#endif
        } else {
                if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
                        fatal_exit("could not parse IP: %s", svr);
        }
-       fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET, 
-               SOCK_STREAM, 0);
+
+       if(addrfamily == 0)
+               addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
+       fd = socket(addrfamily, SOCK_STREAM, 0);
        if(fd == -1) {
 #ifndef USE_WINSOCK
                fatal_exit("socket: %s", strerror(errno));
@@ -223,7 +247,7 @@ contact_server(const char* svr, struct c
 
 /** setup SSL on the connection */
 static SSL*
-setup_ssl(SSL_CTX* ctx, int fd)
+setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
 {
        SSL* ssl;
        X509* x;
@@ -249,10 +273,13 @@ setup_ssl(SSL_CTX* ctx, int fd)
        /* check authenticity of server */
        if(SSL_get_verify_result(ssl) != X509_V_OK)
                ssl_err("SSL verification failed");
-       x = SSL_get_peer_certificate(ssl);
-       if(!x)
-               ssl_err("Server presented no peer certificate");
-       X509_free(x);
+       if(cfg->remote_control_use_cert) {
+               x = SSL_get_peer_certificate(ssl);
+               if(!x)
+                       ssl_err("Server presented no peer certificate");
+               X509_free(x);
+       }
+
        return ssl;
 }
 
@@ -330,11 +357,11 @@ go(const char* cfgfile, char* svr, int q
        if(!cfg->remote_control_enable)
                log_warn("control-enable is 'no' in the config file.");
        ctx = setup_ctx(cfg);
-       
+
        /* contact server */
        fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0);
-       ssl = setup_ssl(ctx, fd);
-       
+       ssl = setup_ssl(ctx, fd, cfg);
+
        /* send command */
        ret = go_cmd(ssl, quiet, argc, argv);
 

Modified: head/contrib/unbound/util/config_file.c
==============================================================================
--- head/contrib/unbound/util/config_file.c     Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/util/config_file.c     Mon Jan  5 14:59:18 2015        
(r276699)
@@ -60,6 +60,9 @@
 #ifdef HAVE_GLOB_H
 # include <glob.h>
 #endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
 
 /** global config during parsing */
 struct config_parser_state* cfg_parser = 0;
@@ -131,6 +134,8 @@ config_create(void)
                goto error_exit;
        init_outgoing_availports(cfg->outgoing_avail_ports, 65536);
        if(!(cfg->username = strdup(UB_USERNAME))) goto error_exit;
+       cfg->uid = (uid_t)-1;
+       cfg->gid = (gid_t)-1;
 #ifdef HAVE_CHROOT
        if(!(cfg->chrootdir = strdup(CHROOT_DIR))) goto error_exit;
 #endif
@@ -799,6 +804,17 @@ config_read(struct config_file* cfg, con
                errno=EINVAL;
                return 0;
        }
+
+#ifdef HAVE_GETPWNAM
+       /* translate username into uid and gid */
+       if(cfg->username && cfg->username[0]) {
+               struct passwd *pwd;
+               if((pwd = getpwnam(cfg->username)) == NULL)
+                       log_err("user '%s' does not exist.", cfg->username);
+               cfg->uid = pwd->pw_uid;
+               cfg->gid = pwd->pw_gid;
+       }
+#endif
        return 1;
 }
 

Modified: head/contrib/unbound/util/config_file.h
==============================================================================
--- head/contrib/unbound/util/config_file.h     Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/util/config_file.h     Mon Jan  5 14:59:18 2015        
(r276699)
@@ -192,6 +192,8 @@ struct config_file {
        char* chrootdir;
        /** username to change to, if not "". */
        char* username;
+       uid_t uid;
+       gid_t gid;
        /** working directory */
        char* directory;
        /** filename to log to. */
@@ -282,6 +284,8 @@ struct config_file {
        struct config_strlist* control_ifs;
        /** port number for the control port */
        int control_port;
+       /** use certificates for remote control */
+       int remote_control_use_cert;
        /** private key file for server */
        char* server_key_file;
        /** certificate file for server */

Modified: head/contrib/unbound/util/configlexer.lex
==============================================================================
--- head/contrib/unbound/util/configlexer.lex   Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/util/configlexer.lex   Mon Jan  5 14:59:18 2015        
(r276699)
@@ -317,6 +317,7 @@ remote-control{COLON}               { YDVAR(0, VAR_RE
 control-enable{COLON}          { YDVAR(1, VAR_CONTROL_ENABLE) }
 control-interface{COLON}       { YDVAR(1, VAR_CONTROL_INTERFACE) }
 control-port{COLON}            { YDVAR(1, VAR_CONTROL_PORT) }
+control-use-cert{COLON}                { YDVAR(1, VAR_CONTROL_USE_CERT) }
 server-key-file{COLON}         { YDVAR(1, VAR_SERVER_KEY_FILE) }
 server-cert-file{COLON}                { YDVAR(1, VAR_SERVER_CERT_FILE) }
 control-key-file{COLON}                { YDVAR(1, VAR_CONTROL_KEY_FILE) }

Modified: head/contrib/unbound/util/configparser.y
==============================================================================
--- head/contrib/unbound/util/configparser.y    Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/util/configparser.y    Mon Jan  5 14:59:18 2015        
(r276699)
@@ -95,6 +95,7 @@ extern struct config_parser_state* cfg_p
 %token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
 %token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
 %token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
+%token VAR_CONTROL_USE_CERT
 %token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT
 %token VAR_STUB_PRIME VAR_UNWANTED_REPLY_THRESHOLD VAR_LOG_TIME_ASCII
 %token VAR_DOMAIN_INSECURE VAR_PYTHON VAR_PYTHON_SCRIPT VAR_VAL_SIG_SKEW_MIN
@@ -1270,7 +1271,7 @@ contents_rc: contents_rc content_rc 
        | ;
 content_rc: rc_control_enable | rc_control_interface | rc_control_port |
        rc_server_key_file | rc_server_cert_file | rc_control_key_file |
-       rc_control_cert_file
+       rc_control_cert_file | rc_control_use_cert
        ;
 rc_control_enable: VAR_CONTROL_ENABLE STRING_ARG
        {
@@ -1298,6 +1299,16 @@ rc_control_interface: VAR_CONTROL_INTERF
                        yyerror("out of memory");
        }
        ;
+rc_control_use_cert: VAR_CONTROL_USE_CERT STRING_ARG
+       {
+               OUTYY(("P(control_use_cert:%s)\n", $2));
+               if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+                       yyerror("expected yes or no.");
+               else cfg_parser->cfg->remote_control_use_cert =
+                       (strcmp($2, "yes")==0);
+               free($2);
+       }
+       ;
 rc_server_key_file: VAR_SERVER_KEY_FILE STRING_ARG
        {
                OUTYY(("P(rc_server_key_file:%s)\n", $2));

Modified: head/contrib/unbound/util/net_help.c
==============================================================================
--- head/contrib/unbound/util/net_help.c        Mon Jan  5 14:55:52 2015        
(r276698)
+++ head/contrib/unbound/util/net_help.c        Mon Jan  5 14:59:18 2015        
(r276699)
@@ -156,7 +156,7 @@ log_addr(enum verbosity_value v, const c
                case AF_INET6: family="ip6";
                        sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
                        break;
-               case AF_UNIX: family="unix"; break;
+               case AF_LOCAL: family="local"; break;
                default: break;
        }
        if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
@@ -313,7 +313,7 @@ void log_name_addr(enum verbosity_value 
                case AF_INET6: family="";
                        sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
                        break;
-               case AF_UNIX: family="unix_family "; break;
+               case AF_LOCAL: family="local "; break;
                default: break;
        }
        if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to