mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 03:02:04 +00:00
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
204 lines
6.9 KiB
Diff
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
|
|
|