From a46b2e89d95dca4ccec598ca4c224a13774f065f Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Wed, 11 Jan 2023 13:36:37 +0100 Subject: [PATCH] dtls: add single connection mode When used with WebRTC, the remote endpoint may send DTLS packets from any port. In this context we should have only one DTLS connection that is used for e.g. SRTP keying and SCTP transport. This happens with Safari 16.1 where it sends DTLS Handshake from one port, and DTLS Alert from another port. --- include/re_tls.h | 1 + src/tls/openssl/tls_udp.c | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/re_tls.h b/include/re_tls.h index 9f9ccdeb6..1aeabf661 100644 --- a/include/re_tls.h +++ b/include/re_tls.h @@ -113,6 +113,7 @@ const struct sa *dtls_peer(const struct tls_conn *tc); void dtls_set_peer(struct tls_conn *tc, const struct sa *peer); void dtls_recv_packet(struct dtls_sock *sock, const struct sa *src, struct mbuf *mb); +void dtls_set_single(struct dtls_sock *sock, bool single); struct x509_st; diff --git a/src/tls/openssl/tls_udp.c b/src/tls/openssl/tls_udp.c index aab4a1ada..8020c4126 100644 --- a/src/tls/openssl/tls_udp.c +++ b/src/tls/openssl/tls_udp.c @@ -52,6 +52,7 @@ struct dtls_sock { dtls_conn_h *connh; void *arg; size_t mtu; + bool single_conn; /* If enabled, only one DTLS connection */ }; @@ -90,6 +91,21 @@ static const char *content_type_str(enum content_type content_type) #endif +static bool first_handler(struct le *le, void *arg) +{ + (void)le; + (void)arg; + + return true; /* stop on the first element */ +} + + +static struct le *hash_get_first(const struct hash *ht) +{ + return hash_apply(ht, first_handler, NULL); +} + + static int bio_create(BIO *b) { BIO_set_init(b, 1); @@ -439,6 +455,13 @@ static int conn_alloc(struct tls_conn **ptc, struct tls *tls, struct tls_conn *tc; int err = 0; + if (sock->single_conn) { + if (hash_get_first(sock->ht)) { + DEBUG_WARNING("single: only one connection allowed\n"); + return EMFILE; + } + } + tc = mem_zalloc(sizeof(*tc), conn_destructor); if (!tc) return ENOMEM; @@ -708,6 +731,11 @@ static bool cmp_handler(struct le *le, void *arg) static struct tls_conn *conn_lookup(struct dtls_sock *sock, const struct sa *peer) { + if (sock->single_conn) { + struct le *le = hash_get_first(sock->ht); + return list_ledata(le); + } + return list_ledata(hash_lookup(sock->ht, sa_hash(peer, SA_ALL), cmp_handler, (void *)peer)); } @@ -846,3 +874,18 @@ void dtls_recv_packet(struct dtls_sock *sock, const struct sa *src, recv_handler(&addr, mb, sock); } + + +/** + * Set single connection mode. If enabled, only one DTLS connection is allowed. + * + * @param sock DTLS Socket + * @param single True to enable, False to disable + */ +void dtls_set_single(struct dtls_sock *sock, bool single) +{ + if (!sock) + return; + + sock->single_conn = single; +}