Hi,
we have another feature suggestion for unbound server :-)

Currently, unbound-control interacts with unbound using SSL-protected IP port. 
For this to function properly, certain SSL-related files should be generated 
and then maintained. These include client and server certificates and private 
keys.
However, when unbound-control and unbound both reside on the same machine, 
then using SSL may be an overkill. Of course, not always :) But in our case, 
when we have a product that contains unbound server and needs to interact 
with it using unbound-control, we would really like to turn SSL off.

Actually, it's enough to use an SSL algorithm that does not require 
authentication, in this case we don't need certificates and keys. A list of 
such algorithms may be seen by typing 'openssl ciphers -v "aNULL"'.

Attached patch forces using any algorithm that doesn't require authentication 
when a certain option is present in the config file. I have called 
it 'control-use-cert', it may be "yes" or "no". With this option it's 
possible to have such configuration:
>>>>>>>>>>>>>>>>>>>>>>>>
remote-control:
        control-enable: yes
        control-use-cert: no
>>>>>>>>>>>>>>>>>>>>>>>>
Note that connection is still encrypted, but not authenticated. And we don't 
need to maintain any additional SSL-related files, that's good :-)

Another approach is disabling SSL completely, but that requires many 
additional if's in the source code, that's why I thought that modifying SSL 
parameters is the way to go.

Please review attached patch and post your suggestions!

Thanks!

--
Best regards,
Ilya Bakulin

genua
Gesellschaft fuer Netzwerk- und Unix-Administration mbH
Domagkstrasse 7, 85551 Kirchheim bei Muenchen
tel +49 89 991950-0, fax -999, www.genua.de
Geschaeftsfuehrer: Dr. Magnus Harlander, Dr. Michaela Harlander,
Bernhard Schneck. Amtsgericht Muenchen HRB 98238
diff --git a/daemon/remote.c b/daemon/remote.c
index a2b2204..981a135 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 <ldns/ldns.h>
 #include "daemon/remote.h"
@@ -127,11 +131,45 @@ 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)
 {
 	char* s_cert;
 	char* s_key;
+
 	struct daemon_remote* rc = (struct daemon_remote*)calloc(1, 
 		sizeof(*rc));
 	if(!rc) {
@@ -156,40 +194,59 @@ daemon_remote_create(struct config_file* cfg)
 		daemon_remote_delete(rc);
 		return NULL;
 	}
-	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) {
+
+	if (cfg->remote_control_use_cert != 0) {
+	    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) {
 		log_err("out of memory in remote control fname");
 		goto setup_error;
-	}
-	verbose(VERB_ALGO, "setup SSL certificates");
-	if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) {
+	    }
+	    verbose(VERB_ALGO, "setup SSL certificates");
+	    if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) {
 		log_err("Error for server-cert-file: %s", s_cert);
 		log_crypto_err("Error in SSL_CTX use_certificate_file");
 		goto setup_error;
-	}
-	if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) {
+	    }
+	    if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) {
 		log_err("Error for server-key-file: %s", s_key);
 		log_crypto_err("Error in SSL_CTX use_PrivateKey_file");
 		goto setup_error;
-	}
-	if(!SSL_CTX_check_private_key(rc->ctx)) {
+	    }
+	    if(!SSL_CTX_check_private_key(rc->ctx)) {
 		log_err("Error for server-key-file: %s", s_key);
 		log_crypto_err("Error in SSL_CTX check_private_key");
 		goto setup_error;
-	}
-	if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
+	    }
+	    if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
 		log_crypto_err("Error setting up SSL_CTX verify locations");
-	setup_error:
+	    setup_error:
 		free(s_cert);
 		free(s_key);
 		daemon_remote_delete(rc);
 		return NULL;
+	    }
+	    SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
+	    SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
+	    free(s_cert);
+	    free(s_key);
+
+	} else {
+	    /* 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;
+	    }
 	}
-	SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
-	SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
-	free(s_cert);
-	free(s_key);
 
 	return rc;
 }
@@ -1950,6 +2007,8 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
 
 	/* once handshake has completed, check authentication */
 	if(SSL_get_verify_result(s->ssl) == X509_V_OK) {
+	    /* If we use certificates, check peer validity */
+	    if (rc->use_cert) {
 		X509* x = SSL_get_peer_certificate(s->ssl);
 		if(!x) {
 			verbose(VERB_DETAIL, "remote control connection "
@@ -1959,6 +2018,7 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
 		}
 		verbose(VERB_ALGO, "remote control connection authenticated");
 		X509_free(x);
+	    }
 	} else {
 		verbose(VERB_DETAIL, "remote control connection failed to "
 			"authenticate with client certificate");
diff --git a/daemon/remote.h b/daemon/remote.h
index 1edc1b8..c45102a 100644
--- a/daemon/remote.h
+++ b/daemon/remote.h
@@ -87,6 +87,8 @@ struct daemon_remote {
 	struct worker* worker;
 	/** commpoints for accepting remote control connections */
 	struct listen_list* accept_list;
+	/* if certificates are used */
+	uint8_t use_cert;
 	/** number of active commpoints that are handling remote control */
 	int active;
 	/** max active commpoints */
diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c
index 8b56f96..a2903cb 100644
--- a/smallapp/unbound-checkconf.c
+++ b/smallapp/unbound-checkconf.c
@@ -407,7 +407,7 @@ morechecks(struct config_file* cfg, const char* fname)
 		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,
diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c
index a872f92..20c3e67 100644
--- a/smallapp/unbound-control.c
+++ b/smallapp/unbound-control.c
@@ -128,27 +128,38 @@ 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)
+	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_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))
+
+	if(cfg->remote_control_use_cert) {
+	    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)
+	    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);
+	    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+
+	} else {
+	    /* No fucking encryption */
+	    if(!SSL_CTX_set_cipher_list(ctx, "aNULL")) {
+		ssl_err("Error setting NULL cipher!");
+	    }
+	}
 
-	free(s_cert);
-	free(c_key);
-	free(c_cert);
 	return ctx;
 }
 
@@ -211,7 +222,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
 
 /** 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;
@@ -237,10 +248,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)
+	if(cfg->remote_control_use_cert) {
+	    x = SSL_get_peer_certificate(ssl);
+	    if(!x)
 		ssl_err("Server presented no peer certificate");
-	X509_free(x);
+	    X509_free(x);
+	}
+
 	return ssl;
 }
 
@@ -318,7 +332,7 @@ go(const char* cfgfile, char* svr, int argc, char* argv[])
 	
 	/* 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, argc, argv);
@@ -406,9 +420,7 @@ int main(int argc, char* argv[])
 				strerror(errno));
 		}
 	}
-
 	ret = go(cfgfile, svr, argc, argv);
-
 #ifdef USE_WINSOCK
         WSACleanup();
 #endif
diff --git a/util/config_file.h b/util/config_file.h
index 050c3a0..288267f 100644
--- a/util/config_file.h
+++ b/util/config_file.h
@@ -276,6 +276,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 */
diff --git a/util/configlexer.lex b/util/configlexer.lex
index 2661ffd..ad6bddc 100644
--- a/util/configlexer.lex
+++ b/util/configlexer.lex
@@ -232,6 +232,7 @@ remote-control{COLON}		{ YDVAR(0, VAR_REMOTE_CONTROL) }
 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) }
diff --git a/util/configparser.y b/util/configparser.y
index 09f77c5..0d89c99 100644
--- a/util/configparser.y
+++ b/util/configparser.y
@@ -104,6 +104,7 @@ extern struct config_parser_state* cfg_parser;
 %token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_HARDEN_BELOW_NXDOMAIN
 %token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
 %token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT
+%token VAR_CONTROL_USE_CERT
 
 %%
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -1162,7 +1163,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
 	{
@@ -1190,6 +1191,16 @@ rc_control_interface: VAR_CONTROL_INTERFACE STRING_ARG
 			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));

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Unbound-users mailing list
[email protected]
http://unbound.nlnetlabs.nl/mailman/listinfo/unbound-users

Reply via email to