diff options
Diffstat (limited to 'src/s_client.c')
-rw-r--r-- | src/s_client.c | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/src/s_client.c b/src/s_client.c deleted file mode 100644 index cf7440d..0000000 --- a/src/s_client.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * s_client command - * - * Copyright (C) 2019 Libiquity LLC - * - * This file is part of wolfutil. - * - * wolfutil is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfutil is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with wolfutil. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> -#include <netdb.h> -#include <poll.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/socket.h> -#include <unistd.h> - -#include <wolfssl/options.h> -#include <wolfssl/ssl.h> -#include <wolfssl/wolfcrypt/settings.h> - -#include "commands.h" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#undef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#undef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -static _Bool -parse_host_port(char *hostport, char **host, char **port) -{ - *host = hostport; - /* XXX: Port is required. Otherwise, this will mangle IPv6 addresses - * without some more intelligent (and larger) code. */ - *port = strrchr(*host, ':'); - if (*port == NULL) { - fputs("Port is required\n", stderr); - return false; - } - **port = '\0'; - ++*port; - - return true; -} - -static int -connect_socket(const char *host, const char *port) -{ - struct addrinfo hints = {0}; - struct addrinfo *result; - int s; - struct addrinfo *rp; - int sfd; - - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - hints.ai_protocol = 0; - - s = getaddrinfo(host, port, &hints, &result); - if (s != 0) { - fprintf(stderr, "Failed to resolve host and port: %s\n", - gai_strerror(s)); - return -1; - } - - for (rp = result; rp != NULL; rp = rp->ai_next) { - sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sfd == -1) { - continue; - } - if (connect(sfd, rp->ai_addr, rp->ai_addrlen) == -1) { - close(sfd); - continue; - } - break; - } - if (rp == NULL) { - fputs("Failed to connect\n", stderr); - sfd = -1; - } - - freeaddrinfo(result); - - return sfd; -} - -static _Bool -write_all(int fd, const void *buf, size_t count) -{ - ssize_t ret; - - while (count > 0) { - while ((ret = write(fd, buf, count)) < 0 && errno == EINTR) { - continue; - } - if (ret < 0) { - return false; - } - buf = ((const char *) buf) + ret; - count -= ret; - } - - return true; -} - -static _Bool -poll_fds(int sfd, WOLFSSL *ssl) -{ - struct pollfd fds[2] = { - { .fd = -1, .events = POLLIN|POLLERR, .revents = 0 }, - { .fd = -1, .events = POLLIN|POLLERR, .revents = 0 }, - }; - char buf[MAX(8192, WOLFSSL_MAX_ERROR_SZ)]; - ssize_t len; - int ret; - - fds[0].fd = STDIN_FILENO; - fds[1].fd = sfd; - - for (;;) { - while (poll(fds, ARRAY_SIZE(fds), -1) < 0 && (errno == EINTR || - errno == EAGAIN)) { - continue; - } - if (fds[0].revents > 0) { /* stdin */ - len = read(STDIN_FILENO, buf, sizeof(buf)); - if (len < 0) { - fputs("Input read error\n", stderr); - return false; - } else if (len == 0) { - fds[0].fd = -1; /* Stop polling. */ - } else if ((ret = wolfSSL_write(ssl, buf, len)) <= 0) { - wolfSSL_ERR_error_string(wolfSSL_get_error(ssl, - ret), buf); - fprintf(stderr, "Socket write error: %s\n", - buf); - return false; - } - } - if (fds[1].revents > 0) { /* socket */ - ret = wolfSSL_read(ssl, buf, MIN(sizeof(buf), 1024)); - if (ret < 0) { - wolfSSL_ERR_error_string(wolfSSL_get_error(ssl, - ret), buf); - fprintf(stderr, "Socket read error: %s\n", - buf); - return false; - } else if (ret == 0) { - fds[1].fd = -1; /* Stop polling. */ - close(STDOUT_FILENO); /* Signal socket EOF. */ - } else if (write_all(STDOUT_FILENO, buf, (size_t) ret) - == false) { - return false; - } - } - if (fds[0].fd == fds[1].fd) { /* Both -1 (no longer polled) */ - return true; - } - } - - /* Unreached */ -} - -int -s_client(int argc, char **argv) -{ - _Bool quiet = false; - char *host = NULL; - char *port = NULL; - const char *servername = NULL; - int ret = EXIT_FAILURE; - WOLFSSL_METHOD *method; - WOLFSSL_CTX *ctx = NULL; - WOLFSSL *ssl = NULL; - int sfd = -1; - int err; - char buf[WOLFSSL_MAX_ERROR_SZ]; - - for (; argc > 0; --argc, ++argv) { - if (strcmp(*argv, "-quiet") == 0) { - quiet = true; - } else if (strcmp(*argv, "-connect") == 0) { - --argc, ++argv; - if (parse_host_port(*argv, &host, &port) == false) { - return EXIT_FAILURE; - } - } else if (strcmp(*argv, "-servername") == 0) { - --argc, ++argv; - servername = *argv; - } else if (**argv == '-') { - fprintf(stderr, "Unsupported option \"%s\"\n", *argv); - } - } - - wolfSSL_Init(); - - if (quiet == false) { - wolfSSL_Debugging_ON(); - } - - if ( - (method = wolfTLSv1_2_client_method()) == NULL || - (ctx = wolfSSL_CTX_new(method)) == NULL || -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS - || wolfSSL_CTX_UseOCSPStaplingV2(ctx, - WOLFSSL_CSR2_OCSP_MULTI, 0) != - WOLFSSL_SUCCESS || -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS - || wolfSSL_CTX_UseOCSPStapling(ctx, WOLFSSL_CSR_OCSP, 0) - != WOLFSSL_SUCCESS || -#endif -#ifdef HAVE_OCSP - wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL) != - WOLFSSL_SUCCESS || -#endif -#if defined(HAVE_CRL) && defined(HAVE_CRL_IO) - wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL) != - WOLFSSL_SUCCESS || -#endif -#ifdef HAVE_SNI - (servername != NULL && wolfSSL_CTX_UseSNI(ctx, - WOLFSSL_SNI_HOST_NAME, servername, - strlen(servername)) != WOLFSSL_SUCCESS) || -#endif - (ssl = wolfSSL_new(ctx)) == NULL || - wolfSSL_check_domain_name(ssl, servername) != - WOLFSSL_SUCCESS - ) { - fputs("Out of memory\n", stderr); - goto error; - } - -#if defined(HAVE_CA_CERTS) && HAVE_CA_CERTS - if (wolfSSL_CTX_load_verify_locations_ex(ctx, - CA_CERTS_FILE, CA_CERTS_DIR, - WOLFSSL_LOAD_FLAG_IGNORE_ERR) != - WOLFSSL_SUCCESS) { - fputs("Failed to load CA certificates\n", stderr); - goto error; - } -#endif - - if ((sfd = connect_socket(host, port)) == -1) { - goto error; - } - wolfSSL_set_fd(ssl, sfd); - - if ((err = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { - wolfSSL_ERR_error_string(wolfSSL_get_error(ssl, err), buf); - fprintf(stderr, "Handshake error: %s\n", buf); - goto error; - } - - if (poll_fds(sfd, ssl) == false) { - goto error; - } - - ret = EXIT_SUCCESS; -error: - close(sfd); - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - wolfSSL_Cleanup(); - - return ret; -} |