aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe2023-03-15 20:55:12 +0100
committerGert Doering2023-03-15 21:46:29 +0100
commit0942e1575abbc0bdda62e3158827b130ae3f9ab6 (patch)
treeeb265f314aa12946f00aee107823fd849b90b5e0
parent1e954cefa0941439ca09598b6131203b975950f8 (diff)
downloadopenvpn-0942e1575abbc0bdda62e3158827b130ae3f9ab6.zip
openvpn-0942e1575abbc0bdda62e3158827b130ae3f9ab6.tar.gz
Fix memory leaks in HMAC initial packet generation
The HMAC leaks are just forgotten frees/deinitialisations. tls_wrap_control() will sometimes return the original buffer (non tls-crypt) and sometimes tls_wrap.work, so handling this buffer lifetime is a bit more complicated. Instead of further complicating that code just give our work buffer the same lifetime as the other one inside tls_wrap.work (put it into per-session gc_arena) as that is also more consistent. Second, packet_id_init() allocates a buffer with malloc and not using a gc_arena, so we need to also manually free it. Patch v2: add missing deallocations in unit tests of the new workbuf Patch v3: remove useless allocation of 0 size buffer in tls_auth_standalone_init Found-By: clang with asan Change-Id: I0cff44f79ee7e3bcf7b5981fc94f469c15f21af3 Signed-off-by: Arne Schwabe <arne@rfc2549.org> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <20230315195512.323070-1-arne@rfc2549.org> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/ Signed-off-by: Gert Doering <gert@greenie.muc.de> (cherry picked from commit e8ecaadd2ac38f2c2d4bcd40eeaea7401aa737a1)
-rw-r--r--src/openvpn/init.c3
-rw-r--r--src/openvpn/ssl.c11
-rw-r--r--src/openvpn/ssl.h6
-rw-r--r--src/openvpn/ssl_pkt.c8
-rw-r--r--src/openvpn/ssl_pkt.h2
-rw-r--r--tests/unit_tests/openvpn/test_pkt.c33
6 files changed, 49 insertions, 14 deletions
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 124ac76..fa2681d 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -3483,6 +3483,7 @@ do_init_frame_tls(struct context *c)
frame_print(&c->c2.tls_auth_standalone->frame, D_MTU_INFO,
"TLS-Auth MTU parms");
c->c2.tls_auth_standalone->tls_wrap.work = alloc_buf_gc(BUF_SIZE(&c->c2.frame), &c->c2.gc);
+ c->c2.tls_auth_standalone->workbuf = alloc_buf_gc(BUF_SIZE(&c->c2.frame), &c->c2.gc);
}
}
@@ -3881,6 +3882,8 @@ do_close_tls(struct context *c)
md_ctx_cleanup(c->c2.pulled_options_state);
md_ctx_free(c->c2.pulled_options_state);
}
+
+ tls_auth_standalone_free(c->c2.tls_auth_standalone);
}
/*
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 78cec90..fe6390f 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -1361,6 +1361,17 @@ tls_auth_standalone_init(struct tls_options *tls_options,
return tas;
}
+void
+tls_auth_standalone_free(struct tls_auth_standalone *tas)
+{
+ if (!tas)
+ {
+ return;
+ }
+
+ packet_id_free(&tas->tls_wrap.opt.packet_id);
+}
+
/*
* Set local and remote option compatibility strings.
* Used to verify compatibility of local and remote option
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
index 58ff4b9..a050cd5 100644
--- a/src/openvpn/ssl.h
+++ b/src/openvpn/ssl.h
@@ -180,6 +180,12 @@ void tls_multi_init_finalize(struct tls_multi *multi, int tls_mtu);
struct tls_auth_standalone *tls_auth_standalone_init(struct tls_options *tls_options,
struct gc_arena *gc);
+/**
+ * Frees a standalone tls-auth verification object.
+ * @param tas the object to free. May be NULL.
+ */
+void tls_auth_standalone_free(struct tls_auth_standalone *tas);
+
/*
* Setups the control channel frame size parameters from the data channel
* parameters
diff --git a/src/openvpn/ssl_pkt.c b/src/openvpn/ssl_pkt.c
index 17a7f89..8b3391e 100644
--- a/src/openvpn/ssl_pkt.c
+++ b/src/openvpn/ssl_pkt.c
@@ -434,7 +434,10 @@ tls_reset_standalone(struct tls_wrap_ctx *ctx,
uint8_t header,
bool request_resend_wkc)
{
- struct buffer buf = alloc_buf(tas->frame.buf.payload_size);
+ /* Copy buffer here to point at the same data but allow tls_wrap_control
+ * to potentially change buf to point to another buffer without
+ * modifying the buffer in tas */
+ struct buffer buf = tas->workbuf;
ASSERT(buf_init(&buf, tas->frame.buf.headroom));
/* Reliable ACK structure */
@@ -461,7 +464,8 @@ tls_reset_standalone(struct tls_wrap_ctx *ctx,
buf_write_u16(&buf, EARLY_NEG_FLAG_RESEND_WKC);
}
- /* Add tls-auth/tls-crypt wrapping, this might replace buf */
+ /* Add tls-auth/tls-crypt wrapping, this might replace buf with
+ * ctx->work */
tls_wrap_control(ctx, header, &buf, own_sid);
return buf;
diff --git a/src/openvpn/ssl_pkt.h b/src/openvpn/ssl_pkt.h
index ec7b48d..ef4852e 100644
--- a/src/openvpn/ssl_pkt.h
+++ b/src/openvpn/ssl_pkt.h
@@ -77,6 +77,7 @@
struct tls_auth_standalone
{
struct tls_wrap_ctx tls_wrap;
+ struct buffer workbuf;
struct frame frame;
};
@@ -220,7 +221,6 @@ read_control_auth(struct buffer *buf,
* This function creates a reset packet using the information
* from the tls pre decrypt state.
*
- * The returned buf needs to be free with \c free_buf
*/
struct buffer
tls_reset_standalone(struct tls_wrap_ctx *ctx,
diff --git a/tests/unit_tests/openvpn/test_pkt.c b/tests/unit_tests/openvpn/test_pkt.c
index f11e52a..736f131 100644
--- a/tests/unit_tests/openvpn/test_pkt.c
+++ b/tests/unit_tests/openvpn/test_pkt.c
@@ -203,6 +203,7 @@ init_tas_auth(int key_direction)
static_key, true, key_direction,
"Control Channel Authentication", "tls-auth",
NULL);
+ tas.workbuf = alloc_buf(1600);
return tas;
}
@@ -217,18 +218,29 @@ init_tas_crypt(bool server)
tls_crypt_init_key(&tas.tls_wrap.opt.key_ctx_bi,
&tas.tls_wrap.original_wrap_keydata, static_key,
true, server);
+ tas.workbuf = alloc_buf(1600);
+ tas.tls_wrap.work = alloc_buf(1600);
return tas;
}
void
+free_tas(struct tls_auth_standalone *tas)
+{
+ /* Not some of these might be null pointers but calling free on null
+ * pointers is a noop */
+ free_key_ctx_bi(&tas->tls_wrap.opt.key_ctx_bi);
+ free_buf(&tas->workbuf);
+ free_buf(&tas->tls_wrap.work);
+}
+
+void
test_tls_decrypt_lite_crypt(void **ut_state)
{
struct link_socket_actual from = { 0 };
struct tls_pre_decrypt_state state = { 0 };
struct tls_auth_standalone tas = init_tas_crypt(true);
-
struct buffer buf = alloc_buf(1024);
/* tls-auth should be invalid */
@@ -263,6 +275,7 @@ test_tls_decrypt_lite_crypt(void **ut_state)
}
free_key_ctx_bi(&tas.tls_wrap.opt.key_ctx_bi);
+ free_tas(&tas);
free_buf(&buf);
}
@@ -318,6 +331,7 @@ test_tls_decrypt_lite_auth(void **ut_state)
free_tls_pre_decrypt_state(&state);
/* Wrong key direction gives a wrong hmac key and should not validate */
free_key_ctx_bi(&tas.tls_wrap.opt.key_ctx_bi);
+ free_tas(&tas);
tas = init_tas_auth(KEY_DIRECTION_INVERSE);
buf_reset_len(&buf);
@@ -326,7 +340,7 @@ test_tls_decrypt_lite_auth(void **ut_state)
assert_int_equal(verdict, VERDICT_INVALID);
free_tls_pre_decrypt_state(&state);
- free_key_ctx_bi(&tas.tls_wrap.opt.key_ctx_bi);
+ free_tas(&tas);
free_buf(&buf);
}
@@ -371,6 +385,7 @@ test_tls_decrypt_lite_none(void **ut_state)
free_tls_pre_decrypt_state(&state);
free_buf(&buf);
+ free_tas(&tas);
}
static void
@@ -442,10 +457,9 @@ test_verify_hmac_tls_auth(void **ut_state)
bool valid = check_session_id_hmac(&state, &from.dest, hmac, 30);
assert_false(valid);
- free_key_ctx_bi(&tas.tls_wrap.opt.key_ctx_bi);
- free_key_ctx(&tas.tls_wrap.tls_crypt_v2_server_key);
free_tls_pre_decrypt_state(&state);
free_buf(&buf);
+ free_tas(&tas);
hmac_ctx_cleanup(hmac);
hmac_ctx_free(hmac);
}
@@ -563,6 +577,7 @@ test_generate_reset_packet_plain(void **ut_state)
tas.tls_wrap.mode = TLS_WRAP_NONE;
struct frame frame = { {.headroom = 200, .payload_size = 1400}, 0};
tas.frame = frame;
+ tas.workbuf = alloc_buf(1600);
uint8_t header = 0 | (P_CONTROL_HARD_RESET_CLIENT_V2 << P_OPCODE_SHIFT);
@@ -577,10 +592,9 @@ test_generate_reset_packet_plain(void **ut_state)
struct buffer buf2 = tls_reset_standalone(&tas.tls_wrap, &tas, &client_id, &server_id, header, false);
assert_int_equal(BLEN(&buf), BLEN(&buf2));
assert_memory_equal(BPTR(&buf), BPTR(&buf2), BLEN(&buf));
- free_buf(&buf2);
free_tls_pre_decrypt_state(&state);
- free_buf(&buf);
+ free_buf(&tas.workbuf);
}
static void
@@ -614,15 +628,12 @@ test_generate_reset_packet_tls_auth(void **ut_state)
assert_int_equal(BLEN(&buf), BLEN(&buf2));
assert_memory_equal(BPTR(&buf), BPTR(&buf2), BLEN(&buf));
- free_buf(&buf2);
free_tls_pre_decrypt_state(&state);
packet_id_free(&tas_client.tls_wrap.opt.packet_id);
- free_buf(&buf);
- free_key_ctx_bi(&tas_server.tls_wrap.opt.key_ctx_bi);
- free_key_ctx_bi(&tas_client.tls_wrap.opt.key_ctx_bi);
-
+ free_tas(&tas_client);
+ free_tas(&tas_server);
}
int