summary refs log tree commit diff
path: root/tls_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tls_compat.c')
-rw-r--r--tls_compat.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/tls_compat.c b/tls_compat.c
new file mode 100644
index 0000000..cde80a9
--- /dev/null
+++ b/tls_compat.c
@@ -0,0 +1,283 @@
+#include "tls_compat.h"
+
+#ifndef NOSSL
+
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+
+static char tls_error_buf[256];
+static tls_config_t global_tls_config = NULL;
+
+tls_config_t
+tls_config_new(void)
+{
+	tls_config_t config;
+	SSL_CTX *ctx;
+
+	SSL_library_init();
+	SSL_load_error_strings();
+	OpenSSL_add_all_algorithms();
+
+	ctx = SSL_CTX_new(TLS_client_method());
+	if (ctx == NULL)
+		return NULL;
+
+	config = calloc(1, sizeof(*config));
+	if (config == NULL) {
+		SSL_CTX_free(ctx);
+		return NULL;
+	}
+
+	config->ctx = ctx;
+	config->verify_depth = 100;
+	config->noverifycert = 0;
+	config->noverifyname = 0;
+	config->noverifytime = 0;
+	config->muststaple = 0;
+	config->session_fd = -1;
+
+	SSL_CTX_set_options(ctx, SSL_OP_LEGACY_SERVER_CONNECT);
+	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+
+	return config;
+}
+
+void
+tls_config_free(tls_config_t config)
+{
+	if (config) {
+		if (config->ctx)
+			SSL_CTX_free(config->ctx);
+		free(config);
+	}
+}
+
+int
+tls_config_set_ca_file(tls_config_t config, const char *ca_file)
+{
+	if (SSL_CTX_load_verify_locations(config->ctx, ca_file, NULL) != 1)
+		return -1;
+	return 0;
+}
+
+int
+tls_config_set_ca_path(tls_config_t config, const char *ca_path)
+{
+	if (SSL_CTX_load_verify_locations(config->ctx, NULL, ca_path) != 1)
+		return -1;
+	return 0;
+}
+
+int
+tls_config_set_ciphers(tls_config_t config, const char *ciphers)
+{
+	if (SSL_CTX_set_cipher_list(config->ctx, ciphers) != 1)
+		return -1;
+	return 0;
+}
+
+void
+tls_config_insecure_noverifycert(tls_config_t config)
+{
+	config->noverifycert = 1;
+	SSL_CTX_set_verify(config->ctx, SSL_VERIFY_NONE, NULL);
+}
+
+void
+tls_config_insecure_noverifyname(tls_config_t config)
+{
+	config->noverifyname = 1;
+}
+
+void
+tls_config_verify(tls_config_t config)
+{
+	config->noverifycert = 0;
+	config->noverifyname = 0;
+	SSL_CTX_set_verify(config->ctx, SSL_VERIFY_PEER, NULL);
+}
+
+int
+tls_config_set_verify_depth(tls_config_t config, int depth)
+{
+	config->verify_depth = depth;
+	SSL_CTX_set_verify_depth(config->ctx, depth);
+	return 0;
+}
+
+void
+tls_config_ocsp_require_stapling(tls_config_t config)
+{
+	config->muststaple = 1;
+}
+
+void
+tls_config_insecure_noverifytime(tls_config_t config)
+{
+	config->noverifytime = 1;
+	X509_STORE *store = SSL_CTX_get_cert_store(config->ctx);
+	if (store)
+		X509_STORE_set_flags(store, X509_V_FLAG_NO_CHECK_TIME);
+}
+
+int
+tls_config_set_session_fd(tls_config_t config, int fd)
+{
+	config->session_fd = fd;
+	return 0;
+}
+
+int
+tls_config_parse_protocols(uint32_t *protocols, const char *protostr)
+{
+	*protocols = 0;
+	if (strstr(protostr, "TLSv1.3") || strstr(protostr, "tlsv1.3"))
+		*protocols |= (1 << 0);
+	if (strstr(protostr, "TLSv1.2") || strstr(protostr, "tlsv1.2"))
+		*protocols |= (1 << 1);
+	if (strstr(protostr, "TLSv1.1") || strstr(protostr, "tlsv1.1"))
+		*protocols |= (1 << 2);
+	if (strstr(protostr, "TLSv1.0") || strstr(protostr, "tlsv1.0") || strstr(protostr, "TLSv1") || strstr(protostr, "tlsv1"))
+		*protocols |= (1 << 3);
+	if (*protocols == 0)
+		return -1;
+	return 0;
+}
+
+int
+tls_config_set_protocols(tls_config_t config, uint32_t protocols)
+{
+	long options = 0;
+	if (!(protocols & (1 << 3)))
+		options |= SSL_OP_NO_TLSv1;
+	if (!(protocols & (1 << 2)))
+		options |= SSL_OP_NO_TLSv1_1;
+	if (!(protocols & (1 << 1)))
+		options |= SSL_OP_NO_TLSv1_2;
+	if (!(protocols & (1 << 0)))
+		options |= SSL_OP_NO_TLSv1_3;
+	SSL_CTX_set_options(config->ctx, options);
+	return 0;
+}
+
+const char *
+tls_config_error(tls_config_t config)
+{
+	unsigned long err = ERR_get_error();
+	if (err)
+		ERR_error_string_n(err, tls_error_buf, sizeof(tls_error_buf));
+	else
+		strcpy(tls_error_buf, "unknown error");
+	return tls_error_buf;
+}
+
+tls_t
+tls_client(void)
+{
+	tls_t tls = calloc(1, sizeof(*tls));
+	if (tls == NULL)
+		return NULL;
+	return tls;
+}
+
+int
+tls_configure(tls_t ctx, tls_config_t config)
+{
+	ctx->ctx = config->ctx;
+	global_tls_config = config;
+	return 0;
+}
+
+int
+tls_connect_socket(tls_t ctx, int s, const char *servername)
+{
+	ctx->fd = s;
+	ctx->ssl = SSL_new(ctx->ctx);
+	if (ctx->ssl == NULL)
+		return -1;
+	if (SSL_set_fd(ctx->ssl, s) != 1)
+		return -1;
+	if (servername && SSL_set_tlsext_host_name(ctx->ssl, servername) != 1)
+		return -1;
+	return 0;
+}
+
+int
+tls_handshake(tls_t ctx)
+{
+	int ret = SSL_connect(ctx->ssl);
+	if (ret <= 0) {
+		int err = SSL_get_error(ctx->ssl, ret);
+		if (err == SSL_ERROR_WANT_READ)
+			return TLS_WANT_POLLIN;
+		if (err == SSL_ERROR_WANT_WRITE)
+			return TLS_WANT_POLLOUT;
+		return -1;
+	}
+	return 0;
+}
+
+int
+tls_read(tls_t ctx, void *buf, size_t buflen)
+{
+	return SSL_read(ctx->ssl, buf, buflen);
+}
+
+int
+tls_write(tls_t ctx, const void *buf, size_t buflen)
+{
+	return SSL_write(ctx->ssl, buf, buflen);
+}
+
+int
+tls_close(tls_t ctx)
+{
+	if (ctx && ctx->ssl) {
+		int ret = SSL_shutdown(ctx->ssl);
+		if (ret < 0) {
+			int err = SSL_get_error(ctx->ssl, ret);
+			if (err == SSL_ERROR_WANT_READ)
+				return TLS_WANT_POLLIN;
+			if (err == SSL_ERROR_WANT_WRITE)
+				return TLS_WANT_POLLOUT;
+		}
+		SSL_free(ctx->ssl);
+		ctx->ssl = NULL;
+	}
+	return 0;
+}
+
+void
+tls_free(tls_t ctx)
+{
+	if (ctx) {
+		if (ctx->ssl)
+			SSL_free(ctx->ssl);
+		free(ctx);
+	}
+}
+
+const char *
+tls_error(tls_t ctx)
+{
+	unsigned long err = ERR_get_error();
+	if (err)
+		ERR_error_string_n(err, tls_error_buf, sizeof(tls_error_buf));
+	else
+		strcpy(tls_error_buf, "unknown error");
+	return tls_error_buf;
+}
+
+int
+tls_conn_session_resumed(tls_t ctx)
+{
+	return SSL_session_reused(ctx->ssl);
+}
+
+#endif
\ No newline at end of file