diff options
| -rw-r--r-- | config.h.in | 3 | ||||
| -rwxr-xr-x | configure | 18 | ||||
| -rw-r--r-- | configure.ac | 6 | ||||
| -rw-r--r-- | daemon/remote.c | 5 | ||||
| -rw-r--r-- | daemon/unbound.c | 3 | ||||
| -rw-r--r-- | doc/Changelog | 5 | ||||
| -rw-r--r-- | doc/unbound.conf.5.in | 2 | ||||
| -rw-r--r-- | services/listen_dnsport.c | 13 | ||||
| -rw-r--r-- | services/listen_dnsport.h | 2 | ||||
| -rw-r--r-- | smallapp/unbound-control.c | 10 | ||||
| -rw-r--r-- | util/config_file.c | 25 | ||||
| -rw-r--r-- | util/config_file.h | 6 | 
12 files changed, 74 insertions, 24 deletions
| diff --git a/config.h.in b/config.h.in index 7a8a5dd58e9c..a8fd05cb5286 100644 --- a/config.h.in +++ b/config.h.in @@ -350,6 +350,9 @@  /* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */  #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST +/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ +#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN +  /* Define if you have Swig libraries and header files. */  #undef HAVE_SWIG diff --git a/configure b/configure index bdfc14f22052..8c6c0785260c 100755 --- a/configure +++ b/configure @@ -13713,7 +13713,7 @@ CC="$lt_save_CC"  # Checks for header files. -for ac_header in 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 +for ac_header in 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  do :    as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`  ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default @@ -17820,6 +17820,22 @@ fi  fi +ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_len" "ac_cv_member_struct_sockaddr_un_sun_len" " +$ac_includes_default +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_un_sun_len" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 1 +_ACEOF + + +fi +  ac_fn_c_check_member "$LINENO" "struct in_pktinfo" "ipi_spec_dst" "ac_cv_member_struct_in_pktinfo_ipi_spec_dst" "  $ac_includes_default  #if HAVE_SYS_PARAM_H diff --git a/configure.ac b/configure.ac index 37e1bf6f4bca..e06c1d6690aa 100644 --- a/configure.ac +++ b/configure.ac @@ -938,6 +938,12 @@ if test $ac_cv_func_daemon = yes; then  ])  fi +AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +])  AC_CHECK_MEMBERS([struct in_pktinfo.ipi_spec_dst],,,[  AC_INCLUDES_DEFAULT  #if HAVE_SYS_PARAM_H diff --git a/daemon/remote.c b/daemon/remote.c index a1d2628a904a..a5be6d68c882 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -142,6 +142,7 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)   * The following function was generated using the openssl utility, using   * the command : "openssl dhparam -dsaparam -C 512"   */ +#ifndef S_SPLINT_S  DH *get_dh512()  {  	static unsigned char dh512_p[]={ @@ -170,6 +171,7 @@ DH *get_dh512()  	dh->length = 160;  	return(dh);  } +#endif /* SPLINT */  struct daemon_remote*  daemon_remote_create(struct config_file* cfg) @@ -299,6 +301,7 @@ void daemon_remote_delete(struct daemon_remote* rc)   * @param nr: port nr   * @param list: list head   * @param noproto_is_err: if lack of protocol support is an error. + * @param cfg: config with username for chown of unix-sockets.   * @return false on failure.   */  static int @@ -326,7 +329,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,  		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); +			chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));  		}  	} else {  		hints.ai_socktype = SOCK_STREAM; diff --git a/daemon/unbound.c b/daemon/unbound.c index e48a6b5ea951..a31b0392ffdb 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -441,8 +441,6 @@ 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; @@ -653,6 +651,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)  			log_warn("Continuing with default config settings");  		}  		apply_settings(daemon, cfg, cmdline_verbose, debug_mode); +		config_lookup_uid(cfg);  		/* prepare */  		if(!daemon_open_shared_ports(daemon)) diff --git a/doc/Changelog b/doc/Changelog index 192b87c84129..1bd19f19c436 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,11 @@  8 December 2014: Wouter  	- Fix CVE-2014-8602: denial of service by making resolver chase  	  endless series of delegations. +	- patch for remote control over local sockets, from Dag-Erling +	  Smorgrav, Ilya Bakulin.  Use control-interface: /path/sock and +	  control-use-cert: no. +	- Fixup that patch and uid lookup (only for daemon). +	- coded the default of control-use-cert, to yes.  1 December 2014: Wouter  	- Fix bug#632: unbound fails to build on AArch64, protects diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 9b23fd64da1b..d4420e26a0a4 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -976,7 +976,7 @@ 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> +.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 diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 69c68b2807ff..0ce0a6b7b175 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -576,15 +576,19 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,  }  int -create_local_accept_sock(char *path, int* noproto) +create_local_accept_sock(const char *path, int* noproto)  {  #ifdef HAVE_SYS_UN_H  	int s;  	struct sockaddr_un sun; -	sun.sun_len = sizeof(sun); +#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN +	/* this member exists on BSDs, not Linux */ +	sun.sun_len = (sa_family_t)sizeof(sun); +#endif  	sun.sun_family = AF_LOCAL; -	strlcpy(sun.sun_path, path, 104); +	/* length is 92-108, 104 on FreeBSD */ +	(void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path));  	if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {  		log_err("Cannot create local socket %s (%s)", @@ -600,7 +604,7 @@ create_local_accept_sock(char *path, int* noproto)  	}  	if (bind(s, (struct sockaddr *)&sun, -		sizeof(struct sockaddr_un)) == -1) { +		(socklen_t)sizeof(struct sockaddr_un)) == -1) {  		log_err("Cannot bind local socket %s (%s)",  			path, strerror(errno));  		return -1; @@ -616,6 +620,7 @@ create_local_accept_sock(char *path, int* noproto)  		return -1;  	} +	(void)noproto; /*unused*/  	return s;  #else  	log_err("Local sockets are not supported"); diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 0513b5d6c01b..e9883a8f4f97 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -214,6 +214,6 @@ int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,   *	are not supported.   * @return: the socket. -1 on error.   */ -int create_local_accept_sock(char* path, int* noproto); +int create_local_accept_sock(const char* path, int* noproto);  #endif /* LISTEN_DNSPORT_H */ diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index 37e840bad799..ac8d96857d47 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -140,7 +140,7 @@ static void ssl_err(const char* s)  static SSL_CTX*  setup_ctx(struct config_file* cfg)  { -	char* s_cert, *c_key, *c_cert; +	char* s_cert=NULL, *c_key=NULL, *c_cert=NULL;  	SSL_CTX* ctx;  	if(cfg->remote_control_use_cert) { @@ -206,9 +206,11 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)  	} 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); +#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN +		sun->sun_len = (sa_family_t)sizeof(sun); +#endif +		(void)strlcpy(sun->sun_path, svr, sizeof(sun->sun_path)); +		addrlen = (socklen_t)sizeof(struct sockaddr_un);  		addrfamily = AF_LOCAL;  #endif  	} else { diff --git a/util/config_file.c b/util/config_file.c index bb39cf9bd7a2..3554e3fa0505 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -201,6 +201,7 @@ config_create(void)  	cfg->remote_control_enable = 0;  	cfg->control_ifs = NULL;  	cfg->control_port = UNBOUND_CONTROL_PORT; +	cfg->remote_control_use_cert = 1;  	cfg->minimal_responses = 0;  	cfg->rrset_roundrobin = 0;  	cfg->max_udp_size = 4096; @@ -805,16 +806,6 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)  		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;  } @@ -1203,6 +1194,20 @@ config_apply(struct config_file* config)  	log_set_time_asc(config->log_time_ascii);  } +void config_lookup_uid(struct config_file* cfg) +{ +#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 +} +  /**    * Calculate string length of full pathname in original filesys   * @param fname: the path name to convert. diff --git a/util/config_file.h b/util/config_file.h index fd35d7863ae1..327eadc76f7b 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -427,6 +427,12 @@ void config_delete(struct config_file* config);  void config_apply(struct config_file* config);  /** + * Find username, sets uid and gid. + * @param config: the config structure. + */ +void config_lookup_uid(struct config_file* config); + +/**   * Set the given keyword to the given value.   * @param config: where to store config   * @param option: option name, including the ':' character. | 
