From 77e50caaf2ef81cd91075cf836fed0e75718ffb4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 23:12:02 +0200 Subject: Adding debian version 1.8.3-2. Signed-off-by: Daniel Baumann --- debian/vendor-h2o/deps/picotls/t/cli.c | 392 +++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 debian/vendor-h2o/deps/picotls/t/cli.c (limited to 'debian/vendor-h2o/deps/picotls/t/cli.c') diff --git a/debian/vendor-h2o/deps/picotls/t/cli.c b/debian/vendor-h2o/deps/picotls/t/cli.c new file mode 100644 index 0000000..fc73499 --- /dev/null +++ b/debian/vendor-h2o/deps/picotls/t/cli.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "picotls.h" +#include "picotls/openssl.h" +#include "util.h" + +static void shift_buffer(ptls_buffer_t *buf, size_t delta) +{ + if (delta != 0) { + assert(delta <= buf->off); + if (delta != buf->off) + memmove(buf->base, buf->base + delta, buf->off - delta); + buf->off -= delta; + } +} + +static int handle_connection(int sockfd, ptls_context_t *ctx, const char *server_name, const char *input_file, + ptls_handshake_properties_t *hsprop) +{ + ptls_t *tls = ptls_new(ctx, server_name == NULL); + ptls_buffer_t rbuf, encbuf, ptbuf; + char bytebuf[16384]; + enum { IN_HANDSHAKE, IN_1RTT, IN_SHUTDOWN } state = IN_HANDSHAKE; + int inputfd = 0, ret = 0; + size_t early_bytes_sent = 0; + ssize_t ioret; + + ptls_buffer_init(&rbuf, "", 0); + ptls_buffer_init(&encbuf, "", 0); + ptls_buffer_init(&ptbuf, "", 0); + + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + if (input_file != NULL) { + if ((inputfd = open(input_file, O_RDONLY)) == -1) { + fprintf(stderr, "failed to open file:%s:%s\n", input_file, strerror(errno)); + ret = 1; + goto Exit; + } + } + if (server_name != NULL) { + ptls_set_server_name(tls, server_name, 0); + if ((ret = ptls_handshake(tls, &encbuf, NULL, NULL, hsprop)) != PTLS_ERROR_IN_PROGRESS) { + fprintf(stderr, "ptls_handshake:%d\n", ret); + ret = 1; + goto Exit; + } + } + + while (1) { + /* check if data is available */ + fd_set readfds, writefds, exceptfds; + int maxfd = 0; + struct timeval timeout; + do { + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_SET(sockfd, &readfds); + if (encbuf.off != 0) + FD_SET(sockfd, &writefds); + FD_SET(sockfd, &exceptfds); + maxfd = sockfd + 1; + if (inputfd != -1) { + FD_SET(inputfd, &readfds); + FD_SET(inputfd, &exceptfds); + if (maxfd <= inputfd) + maxfd = inputfd + 1; + } + timeout.tv_sec = encbuf.off != 0 ? 0 : 3600; + timeout.tv_usec = 0; + } while (select(maxfd, &readfds, &writefds, &exceptfds, &timeout) == -1); + + /* consume incoming messages */ + if (FD_ISSET(sockfd, &readfds) || FD_ISSET(sockfd, &exceptfds)) { + size_t off = 0, leftlen; + while ((ioret = read(sockfd, bytebuf, sizeof(bytebuf))) == -1 && errno == EINTR) + ; + if (ioret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + /* no data */ + ioret = 0; + } else if (ioret <= 0) { + goto Exit; + } + while ((leftlen = ioret - off) != 0) { + if (state == IN_HANDSHAKE) { + if ((ret = ptls_handshake(tls, &encbuf, bytebuf + off, &leftlen, hsprop)) == 0) { + state = IN_1RTT; + /* release data sent as early-data, if server accepted it */ + if (hsprop->client.early_data_accepted_by_peer) + shift_buffer(&ptbuf, early_bytes_sent); + if (ptbuf.off != 0) { + if ((ret = ptls_send(tls, &encbuf, ptbuf.base, ptbuf.off)) != 0) { + fprintf(stderr, "ptls_send(1rtt):%d\n", ret); + goto Exit; + } + ptbuf.off = 0; + } + } else if (ret == PTLS_ERROR_IN_PROGRESS) { + /* ok */ + } else { + fprintf(stderr, "ptls_handshake:%d\n", ret); + goto Exit; + } + } else { + if ((ret = ptls_receive(tls, &rbuf, bytebuf + off, &leftlen)) == 0) { + if (rbuf.off != 0) { + write(1, rbuf.base, rbuf.off); + rbuf.off = 0; + } + } else if (ret == PTLS_ERROR_IN_PROGRESS) { + /* ok */ + } else { + fprintf(stderr, "ptls_receive:%d\n", ret); + goto Exit; + } + } + off += leftlen; + } + } + + /* read input (and send if possible) */ + if (inputfd != -1 && (FD_ISSET(inputfd, &readfds) || FD_ISSET(inputfd, &exceptfds))) { + while ((ioret = read(inputfd, bytebuf, sizeof(bytebuf))) == -1 && errno == EINTR) + ; + if (ioret > 0) { + ptls_buffer_pushv(&ptbuf, bytebuf, ioret); + if (state == IN_HANDSHAKE) { + size_t send_amount = 0; + if (hsprop->client.max_early_data_size != NULL) { + size_t max_can_be_sent = *hsprop->client.max_early_data_size; + if (max_can_be_sent > ptbuf.off) + max_can_be_sent = ptbuf.off; + send_amount = max_can_be_sent - early_bytes_sent; + } + if (send_amount != 0) { + if ((ret = ptls_send(tls, &encbuf, ptbuf.base, send_amount)) != 0) { + fprintf(stderr, "ptls_send(early_data):%d\n", ret); + goto Exit; + } + early_bytes_sent += send_amount; + } + } else { + if ((ret = ptls_send(tls, &encbuf, bytebuf, ioret)) != 0) { + fprintf(stderr, "ptls_send(1rtt):%d\n", ret); + goto Exit; + } + ptbuf.off = 0; + } + } else { + /* closed */ + if (input_file != NULL) + close(inputfd); + inputfd = -1; + } + } + + /* send any data */ + if (encbuf.off != 0) { + while ((ioret = write(sockfd, encbuf.base, encbuf.off)) == -1 && errno == EINTR) + ; + if (ioret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + /* no data */ + } else if (ioret <= 0) { + goto Exit; + } else { + shift_buffer(&encbuf, ioret); + } + } + + /* close the sender side when necessary */ + if (state == IN_1RTT && inputfd == -1) { + /* FIXME send close_alert */ + shutdown(sockfd, SHUT_WR); + state = IN_SHUTDOWN; + } + } + +Exit: + if (sockfd != -1) + close(sockfd); + if (input_file != NULL && inputfd != -1) + close(inputfd); + ptls_buffer_dispose(&rbuf); + ptls_buffer_dispose(&encbuf); + ptls_buffer_dispose(&ptbuf); + ptls_free(tls); + return ret != 0; +} + +static int run_server(struct sockaddr *sa, socklen_t salen, ptls_context_t *ctx, const char *input_file, + ptls_handshake_properties_t *hsprop) +{ + int listen_fd, conn_fd, on = 1; + + if ((listen_fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) { + perror("socket(2) failed"); + return 1; + } + if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) { + perror("setsockopt(SO_REUSEADDR) failed"); + return 1; + } + if (bind(listen_fd, sa, salen) != 0) { + perror("bind(2) failed"); + return 1; + } + if (listen(listen_fd, SOMAXCONN) != 0) { + perror("listen(2) failed"); + return 1; + } + + while (1) { + if ((conn_fd = accept(listen_fd, NULL, 0)) != -1) + handle_connection(conn_fd, ctx, NULL, input_file, hsprop); + } + + return 0; +} + +static int run_client(struct sockaddr *sa, socklen_t salen, ptls_context_t *ctx, const char *server_name, const char *input_file, + ptls_handshake_properties_t *hsprop) +{ + int fd; + + if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == 1) { + perror("socket(2) failed"); + return 1; + } + if (connect(fd, sa, salen) != 0) { + perror("connect(2) failed"); + return 1; + } + + return handle_connection(fd, ctx, server_name, input_file, hsprop); +} + +static void usage(const char *cmd) +{ + printf("Usage: %s [options] host port\n" + "\n" + "Options:\n" + " -4 force IPv4\n" + " -6 force IPv6\n" + " -c certificate-file\n" + " -i file a file to read from and send to the peer (default: stdin)\n" + " -k key-file specifies the credentials to be used for running the\n" + " server. If omitted, the command runs as a client.\n" + " -l log-file file to log traffic secrets\n" + " -n negotiates the key exchange method (i.e. wait for HRR)\n" + " -s session-file file to read/write the session ticket\n" + " -S require public key exchange when resuming a session\n" + " -e when resuming a session, send first 8,192 bytes of input\n" + " as early data\n" + " -v verify peer using the default certificates\n" + " -h print this help\n" + "\n", + cmd); +} + +int main(int argc, char **argv) +{ + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); +#if !defined(OPENSSL_NO_ENGINE) + /* Load all compiled-in ENGINEs */ + ENGINE_load_builtin_engines(); + ENGINE_register_all_ciphers(); + ENGINE_register_all_digests(); +#endif + + ptls_context_t ctx = {ptls_openssl_random_bytes, &ptls_get_time, ptls_openssl_key_exchanges, ptls_openssl_cipher_suites}; + ptls_handshake_properties_t hsprop = {{{{NULL}}}}; + const char *host, *port, *file = NULL; + int use_early_data = 0, ch; + struct sockaddr_storage sa; + socklen_t salen; + int family = 0; + + while ((ch = getopt(argc, argv, "46c:i:k:nes:Sl:vh")) != -1) { + switch (ch) { + case '4': + family = AF_INET; + break; + case '6': + family = AF_INET6; + break; + case 'c': + load_certificate_chain(&ctx, optarg); + break; + case 'i': + file = optarg; + break; + case 'k': + load_private_key(&ctx, optarg); + break; + case 'n': + hsprop.client.negotiate_before_key_exchange = 1; + break; + case 'e': + use_early_data = 1; + break; + case 's': + setup_session_file(&ctx, &hsprop, optarg); + break; + case 'S': + ctx.require_dhe_on_psk = 1; + break; + case 'l': + setup_log_secret(&ctx, optarg); + break; + case 'v': + setup_verify_certificate(&ctx); + break; + default: + usage(argv[0]); + exit(1); + } + } + argc -= optind; + argv += optind; + if (ctx.certificates.count != 0 || ctx.sign_certificate != NULL) { + /* server */ + if (ctx.certificates.count == 0 || ctx.sign_certificate == NULL) { + fprintf(stderr, "-c and -k options must be used together\n"); + return 1; + } + setup_session_cache(&ctx); + } else { + /* client */ + if (use_early_data) { + static size_t max_early_data_size; + hsprop.client.max_early_data_size = &max_early_data_size; + } + } + if (argc != 2) { + fprintf(stderr, "missing host and port\n"); + return 1; + } + host = (--argc, *argv++); + port = (--argc, *argv++); + + if (resolve_address((struct sockaddr *)&sa, &salen, host, port, family, SOCK_STREAM, IPPROTO_TCP) != 0) + exit(1); + + if (ctx.certificates.count != 0) { + return run_server((struct sockaddr *)&sa, salen, &ctx, file, &hsprop); + } else { + return run_client((struct sockaddr *)&sa, salen, &ctx, host, file, &hsprop); + } +} -- cgit v1.2.3