diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
commit | be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch) | |
tree | 9754ff1ca740f6346cf8483ec915d4054bc5da2d /web/server/h2o/libh2o/deps/picotls/t/util.h | |
parent | Initial commit. (diff) | |
download | netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip |
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | web/server/h2o/libh2o/deps/picotls/t/util.h | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/picotls/t/util.h b/web/server/h2o/libh2o/deps/picotls/t/util.h new file mode 100644 index 00000000..78ce87c3 --- /dev/null +++ b/web/server/h2o/libh2o/deps/picotls/t/util.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016,2017 DeNA Co., Ltd., Kazuho Oku, Fastly + * + * 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 util_h +#define util_h + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */ +#endif + +#include <errno.h> +#include <netdb.h> +#include <netinet/in.h> +#include <stdio.h> +#include <string.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <openssl/pem.h> +#include "picotls/openssl.h" + +static inline void load_certificate_chain(ptls_context_t *ctx, const char *fn) +{ + if (ptls_load_certificates(ctx, (char *)fn) != 0) { + fprintf(stderr, "failed to load certificate:%s:%s\n", fn, strerror(errno)); + exit(1); + } +} + +static inline void load_private_key(ptls_context_t *ctx, const char *fn) +{ + static ptls_openssl_sign_certificate_t sc; + FILE *fp; + EVP_PKEY *pkey; + + if ((fp = fopen(fn, "rb")) == NULL) { + fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno)); + exit(1); + } + pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + + if (pkey == NULL) { + fprintf(stderr, "failed to read private key from file:%s\n", fn); + exit(1); + } + + ptls_openssl_init_sign_certificate(&sc, pkey); + EVP_PKEY_free(pkey); + + ctx->sign_certificate = &sc.super; +} + +struct st_util_save_ticket_t { + ptls_save_ticket_t super; + char fn[MAXPATHLEN]; +}; + +static int save_ticket_cb(ptls_save_ticket_t *_self, ptls_t *tls, ptls_iovec_t src) +{ + struct st_util_save_ticket_t *self = (void *)_self; + FILE *fp; + + if ((fp = fopen(self->fn, "wb")) == NULL) { + fprintf(stderr, "failed to open file:%s:%s\n", self->fn, strerror(errno)); + return PTLS_ERROR_LIBRARY; + } + fwrite(src.base, 1, src.len, fp); + fclose(fp); + + return 0; +} + +static inline void setup_session_file(ptls_context_t *ctx, ptls_handshake_properties_t *hsprop, const char *fn) +{ + static struct st_util_save_ticket_t st; + FILE *fp; + + /* setup save_ticket callback */ + strcpy(st.fn, fn); + st.super.cb = save_ticket_cb; + ctx->save_ticket = &st.super; + + /* load session ticket if possible */ + if ((fp = fopen(fn, "rb")) != NULL) { + static uint8_t ticket[16384]; + size_t ticket_size = fread(ticket, 1, sizeof(ticket), fp); + if (ticket_size == 0 || !feof(fp)) { + fprintf(stderr, "failed to load ticket from file:%s\n", fn); + exit(1); + } + fclose(fp); + hsprop->client.session_ticket = ptls_iovec_init(ticket, ticket_size); + } +} + +static inline void setup_verify_certificate(ptls_context_t *ctx) +{ + static ptls_openssl_verify_certificate_t vc; + ptls_openssl_init_verify_certificate(&vc, NULL); + ctx->verify_certificate = &vc.super; +} + +struct st_util_log_secret_t { + ptls_log_secret_t super; + FILE *fp; +}; + +static void fprinthex(FILE *fp, ptls_iovec_t vec) +{ + size_t i; + for (i = 0; i != vec.len; ++i) + fprintf(fp, "%02x", vec.base[i]); +} + +static void log_secret_cb(ptls_log_secret_t *_self, ptls_t *tls, const char *label, ptls_iovec_t secret) +{ + struct st_util_log_secret_t *self = (void *)_self; + + fprintf(self->fp, "%s ", label); + fprinthex(self->fp, ptls_get_client_random(tls)); + fprintf(self->fp, " "); + fprinthex(self->fp, secret); + fprintf(self->fp, "\n"); + fflush(self->fp); +} + +static inline void setup_log_secret(ptls_context_t *ctx, const char *fn) +{ + static struct st_util_log_secret_t ls; + + if ((ls.fp = fopen(fn, "at")) == NULL) { + fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno)); + exit(1); + } + ls.super.cb = log_secret_cb; + ctx->log_secret = &ls.super; +} + +/* single-entry session cache */ +struct st_util_session_cache_t { + ptls_encrypt_ticket_t super; + uint8_t id[32]; + ptls_iovec_t data; +}; + +static int encrypt_ticket_cb(ptls_encrypt_ticket_t *_self, ptls_t *tls, int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src) +{ + struct st_util_session_cache_t *self = (void *)_self; + int ret; + + if (is_encrypt) { + + /* replace the cached entry along with a newly generated session id */ + free(self->data.base); + if ((self->data.base = malloc(src.len)) == NULL) + return PTLS_ERROR_NO_MEMORY; + + ptls_get_context(tls)->random_bytes(self->id, sizeof(self->id)); + memcpy(self->data.base, src.base, src.len); + self->data.len = src.len; + + /* store the session id in buffer */ + if ((ret = ptls_buffer_reserve(dst, sizeof(self->id))) != 0) + return ret; + memcpy(dst->base + dst->off, self->id, sizeof(self->id)); + dst->off += sizeof(self->id); + + } else { + + /* check if session id is the one stored in cache */ + if (src.len != sizeof(self->id)) + return PTLS_ERROR_SESSION_NOT_FOUND; + if (memcmp(self->id, src.base, sizeof(self->id)) != 0) + return PTLS_ERROR_SESSION_NOT_FOUND; + + /* return the cached value */ + if ((ret = ptls_buffer_reserve(dst, self->data.len)) != 0) + return ret; + memcpy(dst->base + dst->off, self->data.base, self->data.len); + dst->off += self->data.len; + } + + return 0; +} + +static inline void setup_session_cache(ptls_context_t *ctx) +{ + static struct st_util_session_cache_t sc; + + sc.super.cb = encrypt_ticket_cb; + + ctx->ticket_lifetime = 86400; + ctx->max_early_data_size = 8192; + ctx->encrypt_ticket = &sc.super; +} + +static inline int resolve_address(struct sockaddr *sa, socklen_t *salen, const char *host, const char *port, int family, int type, + int proto) +{ + struct addrinfo hints, *res; + int err; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = type; + hints.ai_protocol = proto; + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE; + if ((err = getaddrinfo(host, port, &hints, &res)) != 0 || res == NULL) { + fprintf(stderr, "failed to resolve address:%s:%s:%s\n", host, port, + err != 0 ? gai_strerror(err) : "getaddrinfo returned NULL"); + return -1; + } + + memcpy(sa, res->ai_addr, res->ai_addrlen); + *salen = res->ai_addrlen; + + freeaddrinfo(res); + return 0; +} + +#endif |