svn commit: r276699 - in head/contrib/unbound: . daemon doc services smallapp util

Dag-Erling Smørgrav des at FreeBSD.org
Mon Jan 5 14:59:24 UTC 2015


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 at 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) {


More information about the svn-src-all mailing list