Files
asterisk/third-party/pjproject/patches/0300-Merge-pull-request-from-GHSA-9pfh-r8x4-w26w.patch
George Joseph 452e0d7258 bundled_pjproject: Backport security fixes from pjproject 2.13.1
Merge-pull-request-from-GHSA-9pfh-r8x4-w26w.patch
Merge-pull-request-from-GHSA-cxwq-5g9x-x7fr.patch
Locking-fix-so-that-SSL_shutdown-and-SSL_write-are-n.patch
Don-t-call-SSL_shutdown-when-receiving-SSL_ERROR_SYS.patch

Resolves: #188
2023-07-05 10:05:50 -06:00

204 lines
6.9 KiB
Diff

From 0731f6ac75f251302b6b135f9534c8a94fe75e62 Mon Sep 17 00:00:00 2001
From: Nanang Izzuddin <nanang@teluu.com>
Date: Tue, 20 Dec 2022 11:39:12 +0700
Subject: [PATCH 300/303] Merge pull request from GHSA-9pfh-r8x4-w26w
* Fix buffer overread in STUN message decoder
* Updates based on comments
---
pjnath/include/pjnath/stun_msg.h | 4 ++++
pjnath/src/pjnath/stun_msg.c | 32 ++++++++++++++++++++------------
2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h
index f4fc5a1e4..c9dd7cf0d 100644
--- a/pjnath/include/pjnath/stun_msg.h
+++ b/pjnath/include/pjnath/stun_msg.h
@@ -432,20 +432,21 @@ typedef enum pj_stun_status
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Transaction ID
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\endverbatim
*/
+#pragma pack(1)
typedef struct pj_stun_msg_hdr
{
/**
* STUN message type, which the first two bits must be zeroes.
*/
pj_uint16_t type;
/**
* The message length is the size, in bytes, of the message not
* including the 20 byte STUN header.
@@ -463,53 +464,56 @@ typedef struct pj_stun_msg_hdr
* The transaction ID is a 96 bit identifier. STUN transactions are
* identified by their unique 96-bit transaction ID. For request/
* response transactions, the transaction ID is chosen by the STUN
* client and MUST be unique for each new STUN transaction generated by
* that STUN client. The transaction ID MUST be uniformly and randomly
* distributed between 0 and 2**96 - 1.
*/
pj_uint8_t tsx_id[12];
} pj_stun_msg_hdr;
+#pragma pack()
/**
* This structre describes STUN attribute header. Each attribute is
* TLV encoded, with a 16 bit type, 16 bit length, and variable value.
* Each STUN attribute ends on a 32 bit boundary:
*
* \verbatim
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\endverbatim
*/
+#pragma pack(1)
typedef struct pj_stun_attr_hdr
{
/**
* STUN attribute type.
*/
pj_uint16_t type;
/**
* The Length refers to the length of the actual useful content of the
* Value portion of the attribute, measured in bytes. The value
* in the Length field refers to the length of the Value part of the
* attribute prior to padding - i.e., the useful content.
*/
pj_uint16_t length;
} pj_stun_attr_hdr;
+#pragma pack()
/**
* This structure describes STUN generic IP address attribute, used for
* example to represent STUN MAPPED-ADDRESS attribute.
*
* The generic IP address attribute indicates the transport address.
* It consists of an eight bit address family, and a sixteen bit port,
* followed by a fixed length value representing the IP address. If the
* address family is IPv4, the address is 32 bits, in network byte
diff --git a/pjnath/src/pjnath/stun_msg.c b/pjnath/src/pjnath/stun_msg.c
index bd83351e6..fd15230bc 100644
--- a/pjnath/src/pjnath/stun_msg.c
+++ b/pjnath/src/pjnath/stun_msg.c
@@ -739,22 +739,22 @@ PJ_DEF(int) pj_stun_set_padding_char(int chr)
int old_pad = padding_char;
padding_char = chr;
return old_pad;
}
//////////////////////////////////////////////////////////////////////////////
#define INIT_ATTR(a,t,l) (a)->hdr.type=(pj_uint16_t)(t), \
- (a)->hdr.length=(pj_uint16_t)(l)
-#define ATTR_HDR_LEN 4
+ (a)->hdr.length=(pj_uint16_t)(l)
+#define ATTR_HDR_LEN sizeof(pj_stun_attr_hdr)
static pj_uint16_t GETVAL16H(const pj_uint8_t *buf, unsigned pos)
{
return (pj_uint16_t) ((buf[pos + 0] << 8) | \
(buf[pos + 1] << 0));
}
/*unused PJ_INLINE(pj_uint16_t) GETVAL16N(const pj_uint8_t *buf, unsigned pos)
{
return pj_htons(GETVAL16H(buf,pos));
@@ -2318,56 +2318,64 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
PJ_ASSERT_RETURN(pool && pdu && pdu_len && p_msg, PJ_EINVAL);
PJ_ASSERT_RETURN(sizeof(pj_stun_msg_hdr) == 20, PJ_EBUG);
if (p_parsed_len)
*p_parsed_len = 0;
if (p_response)
*p_response = NULL;
/* Check if this is a STUN message, if necessary */
if (options & PJ_STUN_CHECK_PACKET) {
- status = pj_stun_msg_check(pdu, pdu_len, options);
- if (status != PJ_SUCCESS)
- return status;
+ status = pj_stun_msg_check(pdu, pdu_len, options);
+ if (status != PJ_SUCCESS)
+ return status;
+ } else {
+ /* For safety, verify packet length at least */
+ pj_uint32_t msg_len = GETVAL16H(pdu, 2) + 20;
+ if (msg_len > pdu_len ||
+ ((options & PJ_STUN_IS_DATAGRAM) && msg_len != pdu_len))
+ {
+ return PJNATH_EINSTUNMSGLEN;
+ }
}
/* Create the message, copy the header, and convert to host byte order */
msg = PJ_POOL_ZALLOC_T(pool, pj_stun_msg);
pj_memcpy(&msg->hdr, pdu, sizeof(pj_stun_msg_hdr));
msg->hdr.type = pj_ntohs(msg->hdr.type);
msg->hdr.length = pj_ntohs(msg->hdr.length);
msg->hdr.magic = pj_ntohl(msg->hdr.magic);
pdu += sizeof(pj_stun_msg_hdr);
/* pdu_len -= sizeof(pj_stun_msg_hdr); */
pdu_len = msg->hdr.length;
/* No need to create response if this is not a request */
if (!PJ_STUN_IS_REQUEST(msg->hdr.type))
p_response = NULL;
/* Parse attributes */
- while (pdu_len >= 4) {
- unsigned attr_type, attr_val_len;
- const struct attr_desc *adesc;
+ while (pdu_len >= ATTR_HDR_LEN) {
+ unsigned attr_type, attr_val_len;
+ const struct attr_desc *adesc;
/* Get attribute type and length. If length is not aligned
* to 4 bytes boundary, add padding.
*/
attr_type = GETVAL16H(pdu, 0);
attr_val_len = GETVAL16H(pdu, 2);
attr_val_len = (attr_val_len + 3) & (~3);
- /* Check length */
- if (pdu_len < attr_val_len) {
- pj_str_t err_msg;
- char err_msg_buf[80];
+ /* Check length */
+ if (pdu_len < attr_val_len + ATTR_HDR_LEN) {
+ pj_str_t err_msg;
+ char err_msg_buf[80];
err_msg.ptr = err_msg_buf;
err_msg.slen = pj_ansi_snprintf(err_msg_buf, sizeof(err_msg_buf),
"Attribute %s has invalid length",
pj_stun_get_attr_name(attr_type));
PJ_LOG(4,(THIS_FILE, "Error decoding message: %.*s",
(int)err_msg.slen, err_msg.ptr));
if (p_response) {
--
2.41.0