public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/sipp] f44: Fix CVEs
@ 2026-09-17 13:42 Peter Lemenkov
  0 siblings, 0 replies; only message in thread
From: Peter Lemenkov @ 2026-09-17 13:42 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/sipp
            Branch : f44
            Commit : 374897767d7c0f952b8fe0baafc38b184596caff
            Author : Peter Lemenkov <lemenkov@gmail.com>
            Date   : 2026-09-16T12:44:49+02:00
            Stats  : +202/-0 in 4 file(s)
            URL    : https://src.fedoraproject.org/rpms/sipp/c/374897767d7c0f952b8fe0baafc38b184596caff?branch=f44

            Log:
            Fix CVEs

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>

---
diff --git a/sipp-0007-fix-use-getAuthParameter-for-algorithm-in-createAuth.patch b/sipp-0007-fix-use-getAuthParameter-for-algorithm-in-createAuth.patch
new file mode 100644
index 0000000..5a0eabd
--- /dev/null
+++ b/sipp-0007-fix-use-getAuthParameter-for-algorithm-in-createAuth.patch
@@ -0,0 +1,44 @@
+From: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+Date: Mon, 24 Aug 2026 11:57:09 +0300
+Subject: [PATCH] fix: use getAuthParameter() for algorithm in
+ createAuthHeader()
+
+createAuthHeader() parsed the algorithm= value from a 401/407
+challenge with an inline strncpy bounded by the source length
+instead of the destination's 32-byte stack buffer, allowing a
+malicious SIP server to overflow it. verifyAuthHeader() already
+parses the same field safely via getAuthParameter(), which is
+bounded by sizeof(algo); reuse it here instead of the unbounded
+inline parser.
+diff --git a/src/auth.cpp b/src/auth.cpp
+index d66771d..5e38d4d 100644
+--- a/src/auth.cpp
++++ b/src/auth.cpp
+@@ -163,7 +163,7 @@ int createAuthHeader(
+ {
+ 
+     char algo[32] = "MD5";
+-    char *start, *end;
++    char *start;
+ 
+     if ((start = stristr(auth, "Digest")) == nullptr) {
+         snprintf(result, result_len, "createAuthHeader: authentication must be digest");
+@@ -175,15 +175,9 @@ int createAuthHeader(
+         return 0;
+     }
+ 
+-    if ((start = stristr(auth, "algorithm=")) != nullptr) {
+-        start = start + strlen("algorithm=");
+-        if (*start == '"') {
+-            start++;
+-        }
+-        end = start + strcspn(start, " ,\"\r\n");
+-        strncpy(algo, start, end - start);
+-        algo[end - start] ='\0';
+-
++    getAuthParameter("algorithm", auth, algo, sizeof(algo));
++    if (algo[0] == '\0') {
++        strcpy(algo, "MD5");
+     }
+ 
+     if (strncasecmp(algo, "MD5", 3)==0) {

diff --git a/sipp-0008-fix-bound-get_peer_tag-copy-against-buffer-size.patch b/sipp-0008-fix-bound-get_peer_tag-copy-against-buffer-size.patch
new file mode 100644
index 0000000..f1aae3c
--- /dev/null
+++ b/sipp-0008-fix-bound-get_peer_tag-copy-against-buffer-size.patch
@@ -0,0 +1,23 @@
+From: Orgad Shaneh <orgad.shaneh@audiocodes.com>
+Date: Mon, 24 Aug 2026 11:57:09 +0300
+Subject: [PATCH] fix: bound get_peer_tag() copy against buffer size
+
+get_peer_tag() copied the To header's tag= value into a static
+2049-byte buffer byte-by-byte with no bounds check on the write
+index. A malicious SIP server sending a response with an
+oversized tag parameter could overflow this BSS buffer with
+attacker-controlled data before the caller's length check ever
+runs.
+diff --git a/src/sip_parser.cpp b/src/sip_parser.cpp
+index 2ba638d..aeb7ce5 100644
+--- a/src/sip_parser.cpp
++++ b/src/sip_parser.cpp
+@@ -104,7 +104,7 @@ char* get_peer_tag(const char* msg)
+     }
+ 
+     while (*ptr && *ptr != ' ' && *ptr != ';' && *ptr != '\t' &&
+-           *ptr != '\r' && *ptr != '\n') {
++           *ptr != '\r' && *ptr != '\n' && tag_i < (int) sizeof(tag) - 1) {
+         tag[tag_i++] = *(ptr++);
+     }
+     tag[tag_i] = '\0';

diff --git a/sipp-0009-fix-bound-get_header-writes-against-last_header-buff.patch b/sipp-0009-fix-bound-get_header-writes-against-last_header-buff.patch
new file mode 100644
index 0000000..5513c3f
--- /dev/null
+++ b/sipp-0009-fix-bound-get_header-writes-against-last_header-buff.patch
@@ -0,0 +1,131 @@
+From: Peter Lemenkov <lemenkov@gmail.com>
+Date: Tue, 8 Sep 2026 13:14:21 +0200
+Subject: [PATCH] fix: bound get_header() writes against last_header buffer
+ size
+
+get_header() accumulates matching headers into a static
+last_header[MAX_HEADER_LEN * 10] buffer using a series of unbounded
+sprintf() calls. When a message contains a header (or several repeated
+headers, e.g. Via or Record-Route) whose combined content exceeds the
+buffer, the content copy
+
+    dest += sprintf(dest, "%s", src);
+
+writes past the end of last_header with attacker-controlled data. The
+source is taken from the message's pre-body section, which can be far
+larger than the 20490-byte destination.
+
+Convert the name, separator, and content writes to snprintf() bounded by
+the space remaining in last_header, and bail out via a truncated: label
+when a write would not fit. On truncation the partially-written header
+is dropped and the accumulated result so far is returned, so callers
+still get a well-formed, NUL-terminated string.
+
+Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
+Assisted-by: Claude (Anthropic) <https://claude.ai>
+diff --git a/src/sip_parser.cpp b/src/sip_parser.cpp
+index aeb7ce5..b22b37d 100644
+--- a/src/sip_parser.cpp
++++ b/src/sip_parser.cpp
+@@ -122,6 +122,7 @@ char* get_header(const char* message, const char* name, bool content)
+ {
+     /* non reentrant. consider accepting char buffer as param */
+     static char last_header[MAX_HEADER_LEN * 10];
++    const char *last_header_end = last_header + sizeof(last_header);
+     const char *cptr;
+     char *src, *src_copy, *dest, *start, *ptr;
+     bool first_time = true;
+@@ -164,8 +165,10 @@ char* get_header(const char* message, const char* name, bool content)
+     while ((src = internal_match_header(
+             src, header_with_newline, compact_header_with_newline))) {
+         if (!content && first_time) {
+-            // Add the name to the string;
+-            dest += sprintf(dest, "%s", name);
++            int n = snprintf(dest, last_header_end - dest, "%s", name);
++            if (n < 0 || n >= last_header_end - dest)
++                goto truncated;
++            dest += n;
+             first_time = false;
+         }
+ 
+@@ -210,12 +213,23 @@ char* get_header(const char* message, const char* name, bool content)
+             }
+ 
+             if (*(dest-1) == ':') {
+-                dest += sprintf(dest, " ");
++                int n = snprintf(dest, last_header_end - dest, " ");
++                if (n < 0 || n >= last_header_end - dest) goto truncated;
++                dest += n;
+             } else {
+-                dest += sprintf(dest, ", ");
++                int n = snprintf(dest, last_header_end - dest, ", ");
++                if (n < 0 || n >= last_header_end - dest) goto truncated;
++                dest += n;
+             }
+         }
+-        dest += sprintf(dest, "%s", src);
++
++        int n = snprintf(dest, last_header_end - dest, "%s", src);
++        if (n < 0 || n >= last_header_end - dest) {
++            /* restore the newline we may have nulled, then bail */
++            if (ptr) *ptr = '\n';
++            goto truncated;
++        }
++        dest += n;
+ 
+         if (ptr) {
+             *ptr = '\n';
+@@ -226,6 +240,7 @@ char* get_header(const char* message, const char* name, bool content)
+         }
+     }
+ 
++truncated:
+     /* No header found? */
+     if (dest == last_header) {
+         free(src_copy);
+@@ -549,6 +564,7 @@ static const char* internal_skip_lws(const char* ptr)
+ 
+ #ifdef GTEST
+ #include "gtest/gtest.h"
++#include <string>
+ 
+ TEST(Parser, internal_find_header) {
+     char data[] = "OPTIONS sip:server SIP/2.0\r\n"
+@@ -680,6 +696,37 @@ From: SIP/2.0/UDP 85.55.55.12:6090;branch=z9hG4bK831a.2bb3de85.0\r\n\
+     EXPECT_STREQ("", get_header(data, "Via:", false));
+ }
+ 
++TEST(Parser, get_header_oversized_single) {
++    /* A single header whose content is larger than the static
++     * last_header[MAX_HEADER_LEN * 10] buffer must be truncated, not
++     * overflowed. Run under ASan/Valgrind this catches the overflow;
++     * everywhere it asserts the result stays within the buffer. */
++    std::string msg = "SIP/2.0 200 OK\r\nSubject: ";
++    msg += std::string(MAX_HEADER_LEN * 12, 'A');
++    msg += "\r\n\r\n";
++
++    char* result = get_header(msg.c_str(), "Subject:", true);
++    ASSERT_NE(result, nullptr);
++    EXPECT_EQ(result[0], 'A');
++    EXPECT_LT(strlen(result), (size_t)(MAX_HEADER_LEN * 10));
++}
++
++TEST(Parser, get_header_oversized_repeated) {
++    /* Many repeated headers whose concatenated content exceeds the
++     * buffer must be truncated, not overflowed. */
++    std::string msg = "SIP/2.0 200 OK\r\n";
++    for (int i = 0; i < 500; ++i) {
++        msg += "Via: SIP/2.0/UDP host" + std::to_string(i) +
++               ".example.com:5060;branch=z9hG4bK" +
++               std::string(50, 'x') + "\r\n";
++    }
++    msg += "\r\n";
++
++    char* result = get_header(msg.c_str(), "Via:", true);
++    ASSERT_NE(result, nullptr);
++    EXPECT_LT(strlen(result), (size_t)(MAX_HEADER_LEN * 10));
++}
++
+ TEST(Parser, get_peer_tag__notag) {
+     EXPECT_STREQ(nullptr, get_peer_tag("...\r\nTo: <abc>\r\n;tag=notag\r\n\r\n"));
+ }

diff --git a/sipp.spec b/sipp.spec
index be06c05..db31e44 100644
--- a/sipp.spec
+++ b/sipp.spec
@@ -12,6 +12,10 @@ Patch:		sipp-0003-Make-SSL-library-mandatory.patch
 Patch:		sipp-0004-Removed-outdated-md5-implementation.patch
 Patch:		sipp-0005-Removed-outdated-Rijndael-Vincent-Rijmen-et-al.-impl.patch
 Patch:		sipp-0006-Raise-minimal-OpenSSL-version-to-1.1.1.patch
+# Security fixes backported from upstream master (unreleased as of 3.7.7)
+Patch:		sipp-0007-fix-use-getAuthParameter-for-algorithm-in-createAuth.patch
+Patch:		sipp-0008-fix-bound-get_peer_tag-copy-against-buffer-size.patch
+Patch:		sipp-0009-fix-bound-get_header-writes-against-last_header-buff.patch
 BuildRequires:	cmake
 BuildRequires:	gcc
 BuildRequires:	gcc-c++

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-17 13:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-17 13:42 [rpms/sipp] f44: Fix CVEs Peter Lemenkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox