tls_config_set_protocols
tls_config_set_session_id
tls_config_set_session_lifetime
+tls_config_set_session_fd
tls_config_set_verify_depth
tls_config_skip_private_key_check
tls_config_verify
tls_conn_alpn_selected
tls_conn_cipher
tls_conn_servername
+tls_conn_session_resumed
tls_conn_version
tls_connect
tls_connect_cbs
-/* $OpenBSD: tls.h,v 1.51 2017/08/10 18:18:30 jsing Exp $ */
+/* $OpenBSD: tls.h,v 1.52 2018/02/10 04:41:24 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
int tls_config_set_ocsp_staple_file(struct tls_config *_config,
const char *_staple_file);
int tls_config_set_protocols(struct tls_config *_config, uint32_t _protocols);
+int tls_config_set_session_fd(struct tls_config *_config, int _session_fd);
int tls_config_set_verify_depth(struct tls_config *_config, int _verify_depth);
void tls_config_prefer_ciphers_client(struct tls_config *_config);
const char *tls_conn_alpn_selected(struct tls *_ctx);
const char *tls_conn_cipher(struct tls *_ctx);
const char *tls_conn_servername(struct tls *_ctx);
+int tls_conn_session_resumed(struct tls *_ctx);
const char *tls_conn_version(struct tls *_ctx);
uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password);
-/* $OpenBSD: tls_client.c,v 1.43 2017/08/10 18:18:30 jsing Exp $ */
+/* $OpenBSD: tls_client.c,v 1.44 2018/02/10 04:41:24 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <limits.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
return (rv);
}
+static int
+tls_client_read_session(struct tls *ctx)
+{
+ int sfd = ctx->config->session_fd;
+ uint8_t *session = NULL;
+ size_t session_len = 0;
+ SSL_SESSION *ss = NULL;
+ BIO *bio = NULL;
+ struct stat sb;
+ ssize_t n;
+ int rv = -1;
+
+ if (fstat(sfd, &sb) == -1) {
+ tls_set_error(ctx, "failed to stat session file");
+ goto err;
+ }
+ if (sb.st_size < 0 || sb.st_size > INT_MAX) {
+ tls_set_errorx(ctx, "invalid session file size");
+ goto err;
+ }
+ session_len = (size_t)sb.st_size;
+
+ /* A zero size file means that we do not yet have a valid session. */
+ if (session_len == 0)
+ goto done;
+
+ if ((session = malloc(session_len)) == NULL)
+ goto err;
+
+ n = pread(sfd, session, session_len, 0);
+ if (n < 0 || (size_t)n != session_len) {
+ tls_set_error(ctx, "failed to read session file");
+ goto err;
+ }
+ if ((bio = BIO_new_mem_buf(session, session_len)) == NULL)
+ goto err;
+ if ((ss = PEM_read_bio_SSL_SESSION(bio, NULL, tls_password_cb,
+ NULL)) == NULL) {
+ tls_set_errorx(ctx, "failed to parse session");
+ goto err;
+ }
+
+ if (SSL_set_session(ctx->ssl_conn, ss) != 1) {
+ tls_set_errorx(ctx, "failed to set session");
+ goto err;
+ }
+
+ done:
+ rv = 0;
+
+ err:
+ freezero(session, session_len);
+ SSL_SESSION_free(ss);
+ BIO_free(bio);
+
+ return rv;
+}
+
+static int
+tls_client_write_session(struct tls *ctx)
+{
+ int sfd = ctx->config->session_fd;
+ SSL_SESSION *ss = NULL;
+ BIO *bio = NULL;
+ long data_len;
+ char *data;
+ off_t offset;
+ size_t len;
+ ssize_t n;
+ int rv = -1;
+
+ if ((ss = SSL_get1_session(ctx->ssl_conn)) == NULL) {
+ if (ftruncate(sfd, 0) == -1) {
+ tls_set_error(ctx, "failed to truncate session file");
+ goto err;
+ }
+ goto done;
+ }
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ goto err;
+ if (PEM_write_bio_SSL_SESSION(bio, ss) == 0)
+ goto err;
+ if ((data_len = BIO_get_mem_data(bio, &data)) <= 0)
+ goto err;
+
+ len = (size_t)data_len;
+ offset = 0;
+
+ if (ftruncate(sfd, len) == -1) {
+ tls_set_error(ctx, "failed to truncate session file");
+ goto err;
+ }
+ while (len > 0) {
+ if ((n = pwrite(sfd, data + offset, len, offset)) == -1) {
+ tls_set_error(ctx, "failed to write session file");
+ goto err;
+ }
+ offset += n;
+ len -= n;
+ }
+
+ done:
+ rv = 0;
+
+ err:
+ SSL_SESSION_free(ss);
+ BIO_free_all(bio);
+
+ return (rv);
+}
+
static int
tls_connect_common(struct tls *ctx, const char *servername)
{
goto err;
}
+ if (ctx->config->session_fd != -1) {
+ SSL_clear_options(ctx->ssl_conn, SSL_OP_NO_TICKET);
+ if (tls_client_read_session(ctx) == -1)
+ goto err;
+ }
+
if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) {
tls_set_errorx(ctx, "ssl OCSP extension setup failure");
goto err;
}
ctx->state |= TLS_HANDSHAKE_COMPLETE;
+
+ if (ctx->config->session_fd != -1) {
+ if (tls_client_write_session(ctx) == -1)
+ goto err;
+ }
+
rv = 0;
err:
-/* $OpenBSD: tls_config.c,v 1.47 2018/02/08 05:56:49 jsing Exp $ */
+/* $OpenBSD: tls_config.c,v 1.48 2018/02/10 04:41:24 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
goto err;
config->refcount = 1;
+ config->session_fd = -1;
/*
* Default configuration.
return (0);
}
+int
+tls_config_set_session_fd(struct tls_config *config, int session_fd)
+{
+ struct stat sb;
+ mode_t mugo;
+
+ if (session_fd == -1) {
+ config->session_fd = session_fd;
+ return (0);
+ }
+
+ if (fstat(session_fd, &sb) == -1) {
+ tls_config_set_error(config, "failed to stat session file");
+ return (-1);
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ tls_config_set_errorx(config,
+ "session file is not a regular file");
+ return (-1);
+ }
+
+ if (sb.st_uid != getuid()) {
+ tls_config_set_errorx(config, "session file has incorrect "
+ "owner (uid %i != %i)", sb.st_uid, getuid());
+ return (-1);
+ }
+ mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ if (mugo != (S_IRUSR|S_IWUSR)) {
+ tls_config_set_errorx(config, "session file has incorrect "
+ "permissions (%o != 600)", mugo);
+ return (-1);
+ }
+
+ config->session_fd = session_fd;
+
+ return (0);
+}
+
int
tls_config_set_verify_depth(struct tls_config *config, int verify_depth)
{
-/* $OpenBSD: tls_conninfo.c,v 1.17 2018/02/08 10:02:48 jsing Exp $ */
+/* $OpenBSD: tls_conninfo.c,v 1.18 2018/02/10 04:41:24 jsing Exp $ */
/*
* Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2015 Bob Beck <beck@openbsd.org>
return rv;
}
+static int
+tls_conninfo_session(struct tls *ctx)
+{
+ ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn);
+
+ return 0;
+}
+
int
tls_conninfo_populate(struct tls *ctx)
{
if (tls_conninfo_cert_pem(ctx) == -1)
goto err;
+ if (tls_conninfo_session(ctx) == -1)
+ goto err;
+
return (0);
err:
return (ctx->conninfo->servername);
}
+int
+tls_conn_session_resumed(struct tls *ctx)
+{
+ if (ctx->conninfo == NULL)
+ return (0);
+ return (ctx->conninfo->session_resumed);
+}
+
const char *
tls_conn_version(struct tls *ctx)
{
-/* $OpenBSD: tls_internal.h,v 1.68 2018/02/08 10:19:31 jsing Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.69 2018/02/10 04:41:24 jsing Exp $ */
/*
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
int ocsp_require_stapling;
uint32_t protocols;
unsigned char session_id[TLS_MAX_SESSION_ID_LENGTH];
+ int session_fd;
int session_lifetime;
struct tls_ticket_key ticket_keys[TLS_NUM_TICKETS];
uint32_t ticket_keyrev;
char *alpn;
char *cipher;
char *servername;
+ int session_resumed;
char *version;
char *hash;