diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2018-09-10 16:31:49 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2018-09-10 16:31:49 +0000 |
commit | 4aea2433fa04a7a86c8972869bd021b7a3622dc8 (patch) | |
tree | 7f4f9830855c0cb429f2c902b18e688a8020f299 /smallapp/unbound-control.c | |
parent | 7b6fdf425a9ef38fe9e16779b3af25863104d9c0 (diff) | |
download | src-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.c | 196 |
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; } |