summaryrefslogtreecommitdiffstats
path: root/lib/libtls/tls.c
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2016-11-03 10:05:32 +0000
committerjsing <jsing@openbsd.org>2016-11-03 10:05:32 +0000
commit9e219fcd14f5a377a8ba5458fed3d60ed31aa98a (patch)
tree6c480703572041a8a43cb63e9d3c2b40f6499039 /lib/libtls/tls.c
parentconvert HMAC and MD5 manuals from pod to mdoc (diff)
downloadwireguard-openbsd-9e219fcd14f5a377a8ba5458fed3d60ed31aa98a.tar.xz
wireguard-openbsd-9e219fcd14f5a377a8ba5458fed3d60ed31aa98a.zip
Only set an error from libssl related code, if an error has not already
been set by libtls code. This avoids the situation where a libtls callback has set an error, only to have it replaced by a less useful libssl based error. ok beck@
Diffstat (limited to 'lib/libtls/tls.c')
-rw-r--r--lib/libtls/tls.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/lib/libtls/tls.c b/lib/libtls/tls.c
index cccdb00531a..6893e95b083 100644
--- a/lib/libtls/tls.c
+++ b/lib/libtls/tls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.c,v 1.50 2016/11/02 15:18:42 beck Exp $ */
+/* $OpenBSD: tls.c,v 1.51 2016/11/03 10:05:32 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -61,15 +61,25 @@ tls_error(struct tls *ctx)
return ctx->error.msg;
}
+void
+tls_error_clear(struct tls_error *error)
+{
+ free(error->msg);
+ error->msg = NULL;
+ error->num = 0;
+ error->tls = 0;
+}
+
static int
tls_error_vset(struct tls_error *error, int errnum, const char *fmt, va_list ap)
{
char *errmsg = NULL;
int rv = -1;
- free(error->msg);
- error->msg = NULL;
+ tls_error_clear(error);
+
error->num = errnum;
+ error->tls = 1;
if (vasprintf(&errmsg, fmt, ap) == -1) {
errmsg = NULL;
@@ -177,6 +187,23 @@ tls_set_errorx(struct tls *ctx, const char *fmt, ...)
return (rv);
}
+int
+tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ /* Only set an error if a more specific one does not already exist. */
+ if (ctx->error.tls != 0)
+ return (0);
+
+ va_start(ap, fmt);
+ rv = tls_error_vset(&ctx->error, -1, fmt, ap);
+ va_end(ap);
+
+ return (rv);
+}
+
struct tls_sni_ctx *
tls_sni_ctx_new(void)
{
@@ -464,21 +491,21 @@ tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix)
} else if (ssl_ret == -1) {
errstr = strerror(errno);
}
- tls_set_errorx(ctx, "%s failed: %s", prefix, errstr);
+ tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr);
return (-1);
case SSL_ERROR_SSL:
if ((err = ERR_peek_error()) != 0) {
errstr = ERR_error_string(err, NULL);
}
- tls_set_errorx(ctx, "%s failed: %s", prefix, errstr);
+ tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr);
return (-1);
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
default:
- tls_set_errorx(ctx, "%s failed (%i)", prefix, ssl_err);
+ tls_set_ssl_errorx(ctx, "%s failed (%i)", prefix, ssl_err);
return (-1);
}
}
@@ -488,6 +515,8 @@ tls_handshake(struct tls *ctx)
{
int rv = -1;
+ tls_error_clear(&ctx->error);
+
if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
tls_set_errorx(ctx, "invalid operation for context");
goto out;
@@ -517,6 +546,8 @@ tls_read(struct tls *ctx, void *buf, size_t buflen)
ssize_t rv = -1;
int ssl_ret;
+ tls_error_clear(&ctx->error);
+
if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) {
if ((rv = tls_handshake(ctx)) != 0)
goto out;
@@ -546,6 +577,8 @@ tls_write(struct tls *ctx, const void *buf, size_t buflen)
ssize_t rv = -1;
int ssl_ret;
+ tls_error_clear(&ctx->error);
+
if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) {
if ((rv = tls_handshake(ctx)) != 0)
goto out;
@@ -575,6 +608,8 @@ tls_close(struct tls *ctx)
int ssl_ret;
int rv = 0;
+ tls_error_clear(&ctx->error);
+
if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
tls_set_errorx(ctx, "invalid operation for context");
rv = -1;