diff options
Diffstat (limited to 'daemon/remote.c')
| -rw-r--r-- | daemon/remote.c | 118 | 
1 files changed, 98 insertions, 20 deletions
diff --git a/daemon/remote.c b/daemon/remote.c index ff3d769d4e544..a1d2628a904a2 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -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, const struct timeval* sum, size_t d)  #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* cfg)  		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_remote* rc)   * @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 listen_port** list, int noproto_is_err)  	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_ports(struct config_file* cfg)  	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_ports(struct config_file* cfg)  	} 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_point* c, void* arg, int err,  	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 "  | 
