summaryrefslogtreecommitdiff
path: root/smallapp/unbound-control.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-09-10 16:31:49 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-09-10 16:31:49 +0000
commit4aea2433fa04a7a86c8972869bd021b7a3622dc8 (patch)
tree7f4f9830855c0cb429f2c902b18e688a8020f299 /smallapp/unbound-control.c
parent7b6fdf425a9ef38fe9e16779b3af25863104d9c0 (diff)
downloadsrc-test2-e6e46365155b0e75fc53284159fd2e078101d24d.tar.gz
src-test2-e6e46365155b0e75fc53284159fd2e078101d24d.zip
Vendor import of Unbound 1.7.3.vendor/unbound/1.7.3
Diffstat (limited to 'smallapp/unbound-control.c')
-rw-r--r--smallapp/unbound-control.c196
1 files changed, 113 insertions, 83 deletions
diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c
index 2337e7a73728..d16541779190 100644
--- a/smallapp/unbound-control.c
+++ b/smallapp/unbound-control.c
@@ -451,47 +451,33 @@ setup_ctx(struct config_file* cfg)
char* s_cert=NULL, *c_key=NULL, *c_cert=NULL;
SSL_CTX* ctx;
- 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");
- }
+ if(!(options_remote_is_address(cfg) && cfg->control_use_cert))
+ return NULL;
+ 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_OP_NO_SSLv2)
ssl_err("could not set SSL_OP_NO_SSLv2");
- if(cfg->remote_control_use_cert) {
- if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
- != SSL_OP_NO_SSLv3)
- ssl_err("could not set SSL_OP_NO_SSLv3");
- if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert) ||
- !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 defined(SSL_OP_NO_TLSv1_3)
- /* in openssl 1.1.1, negotiation code for tls 1.3 does
- * not allow the unauthenticated aNULL and eNULL ciphers */
- SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_3);
-#endif
-#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
- SSL_CTX_set_security_level(ctx, 0);
-#endif
- if(!SSL_CTX_set_cipher_list(ctx, "aNULL:eNULL"))
- ssl_err("Error setting NULL cipher!");
- }
+ if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
+ != SSL_OP_NO_SSLv3)
+ ssl_err("could not set SSL_OP_NO_SSLv3");
+ if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert) ||
+ !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);
return ctx;
}
@@ -501,12 +487,12 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
{
struct sockaddr_storage addr;
socklen_t addrlen;
- int addrfamily = 0;
- int fd;
+ int addrfamily = 0, proto = IPPROTO_TCP;
+ int fd, useport = 1;
/* use svr or the first config entry */
if(!svr) {
- if(cfg->control_ifs) {
- svr = cfg->control_ifs->str;
+ if(cfg->control_ifs.first) {
+ svr = cfg->control_ifs.first->str;
} else if(cfg->do_ip4) {
svr = "127.0.0.1";
} else {
@@ -534,6 +520,8 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
(void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path));
addrlen = (socklen_t)sizeof(struct sockaddr_un);
addrfamily = AF_LOCAL;
+ useport = 0;
+ proto = 0;
#endif
} else {
if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
@@ -541,8 +529,8 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
}
if(addrfamily == 0)
- addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
- fd = socket(addrfamily, SOCK_STREAM, 0);
+ addrfamily = addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET;
+ fd = socket(addrfamily, SOCK_STREAM, proto);
if(fd == -1) {
#ifndef USE_WINSOCK
fatal_exit("socket: %s", strerror(errno));
@@ -552,14 +540,18 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
}
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
#ifndef USE_WINSOCK
- log_err_addr("connect", strerror(errno), &addr, addrlen);
- if(errno == ECONNREFUSED && statuscmd) {
+ int err = errno;
+ if(!useport) log_err("connect: %s for %s", strerror(err), svr);
+ else log_err_addr("connect", strerror(err), &addr, addrlen);
+ if(err == ECONNREFUSED && statuscmd) {
printf("unbound is stopped\n");
exit(3);
}
#else
- log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen);
- if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) {
+ int wsaerr = WSAGetLastError();
+ if(!useport) log_err("connect: %s for %s", wsa_strerror(wsaerr), svr);
+ else log_err_addr("connect", wsa_strerror(wsaerr), &addr, addrlen);
+ if(wsaerr == WSAECONNREFUSED && statuscmd) {
printf("unbound is stopped\n");
exit(3);
}
@@ -571,12 +563,13 @@ 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, struct config_file* cfg)
+setup_ssl(SSL_CTX* ctx, int fd)
{
SSL* ssl;
X509* x;
int r;
+ if(!ctx) return NULL;
ssl = SSL_new(ctx);
if(!ssl)
ssl_err("could not SSL_new");
@@ -597,78 +590,115 @@ setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
/* check authenticity of server */
if(SSL_get_verify_result(ssl) != X509_V_OK)
ssl_err("SSL verification failed");
- if(cfg->remote_control_use_cert) {
- x = SSL_get_peer_certificate(ssl);
- if(!x)
- ssl_err("Server presented no peer certificate");
- X509_free(x);
- }
+ x = SSL_get_peer_certificate(ssl);
+ if(!x)
+ ssl_err("Server presented no peer certificate");
+ X509_free(x);
return ssl;
}
+/** read from ssl or fd, fatalexit on error, 0 EOF, 1 success */
+static int
+remote_read(SSL* ssl, int fd, char* buf, size_t len)
+{
+ if(ssl) {
+ int r;
+ ERR_clear_error();
+ if((r = SSL_read(ssl, buf, (int)len-1)) <= 0) {
+ if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
+ /* EOF */
+ return 0;
+ }
+ ssl_err("could not SSL_read");
+ }
+ buf[r] = 0;
+ } else {
+ ssize_t rr = recv(fd, buf, len-1, 0);
+ if(rr <= 0) {
+ if(rr == 0) {
+ /* EOF */
+ return 0;
+ }
+#ifndef USE_WINSOCK
+ fatal_exit("could not recv: %s", strerror(errno));
+#else
+ fatal_exit("could not recv: %s", wsa_strerror(WSAGetLastError()));
+#endif
+ }
+ buf[rr] = 0;
+ }
+ return 1;
+}
+
+/** write to ssl or fd, fatalexit on error */
+static void
+remote_write(SSL* ssl, int fd, const char* buf, size_t len)
+{
+ if(ssl) {
+ if(SSL_write(ssl, buf, (int)len) <= 0)
+ ssl_err("could not SSL_write");
+ } else {
+ if(send(fd, buf, len, 0) < (ssize_t)len) {
+#ifndef USE_WINSOCK
+ fatal_exit("could not send: %s", strerror(errno));
+#else
+ fatal_exit("could not send: %s", wsa_strerror(WSAGetLastError()));
+#endif
+ }
+ }
+}
+
/** send stdin to server */
static void
-send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
+send_file(SSL* ssl, int fd, FILE* in, char* buf, size_t sz)
{
while(fgets(buf, (int)sz, in)) {
- if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0)
- ssl_err("could not SSL_write contents");
+ remote_write(ssl, fd, buf, strlen(buf));
}
}
/** send end-of-file marker to server */
static void
-send_eof(SSL* ssl)
+send_eof(SSL* ssl, int fd)
{
char e[] = {0x04, 0x0a};
- if(SSL_write(ssl, e, (int)sizeof(e)) <= 0)
- ssl_err("could not SSL_write end-of-file marker");
+ remote_write(ssl, fd, e, sizeof(e));
}
/** send command and display result */
static int
-go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
+go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
{
char pre[10];
const char* space=" ";
const char* newline="\n";
int was_error = 0, first_line = 1;
- int r, i;
+ int i;
char buf[1024];
snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
- if(SSL_write(ssl, pre, (int)strlen(pre)) <= 0)
- ssl_err("could not SSL_write");
+ remote_write(ssl, fd, pre, strlen(pre));
for(i=0; i<argc; i++) {
- if(SSL_write(ssl, space, (int)strlen(space)) <= 0)
- ssl_err("could not SSL_write");
- if(SSL_write(ssl, argv[i], (int)strlen(argv[i])) <= 0)
- ssl_err("could not SSL_write");
+ remote_write(ssl, fd, space, strlen(space));
+ remote_write(ssl, fd, argv[i], strlen(argv[i]));
}
- if(SSL_write(ssl, newline, (int)strlen(newline)) <= 0)
- ssl_err("could not SSL_write");
+ remote_write(ssl, fd, newline, strlen(newline));
if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
- send_file(ssl, stdin, buf, sizeof(buf));
+ send_file(ssl, fd, stdin, buf, sizeof(buf));
}
else if(argc == 1 && (strcmp(argv[0], "local_zones") == 0 ||
strcmp(argv[0], "local_zones_remove") == 0 ||
strcmp(argv[0], "local_datas") == 0 ||
strcmp(argv[0], "local_datas_remove") == 0)) {
- send_file(ssl, stdin, buf, sizeof(buf));
- send_eof(ssl);
+ send_file(ssl, fd, stdin, buf, sizeof(buf));
+ send_eof(ssl, fd);
}
while(1) {
- ERR_clear_error();
- if((r = SSL_read(ssl, buf, (int)sizeof(buf)-1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- /* EOF */
- break;
- }
- ssl_err("could not SSL_read");
+ if(remote_read(ssl, fd, buf, sizeof(buf)) == 0) {
+ break; /* EOF */
}
- buf[r] = 0;
if(first_line && strncmp(buf, "error", 5) == 0) {
printf("%s", buf);
was_error = 1;
@@ -703,18 +733,18 @@ go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[])
/* contact server */
fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0);
- ssl = setup_ssl(ctx, fd, cfg);
+ ssl = setup_ssl(ctx, fd);
/* send command */
- ret = go_cmd(ssl, quiet, argc, argv);
+ ret = go_cmd(ssl, fd, quiet, argc, argv);
- SSL_free(ssl);
+ if(ssl) SSL_free(ssl);
#ifndef USE_WINSOCK
close(fd);
#else
closesocket(fd);
#endif
- SSL_CTX_free(ctx);
+ if(ctx) SSL_CTX_free(ctx);
config_delete(cfg);
return ret;
}