From f2836dc6b645b4d35d1870d2e8c6ac83969d0421 Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Fri, 27 May 2022 22:41:51 +0300 Subject: [PATCH] rtp: Accept CRLF delimiters in SDP as required by RFC 4566 RFC 4566 states that SDP record is terminated with CRLF, and parsers should be able to accept records terminated with just LF. Pulseaudio only accepts LF here. Fix this by accepting both CRLF and LF terminators. --- src/modules/rtp/sap.c | 4 +++- src/modules/rtp/sdp.c | 31 ++++++++++++++++++++++++++----- src/modules/rtp/sdp.h | 2 +- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 7fb1a3895..8614022f8 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -213,7 +213,9 @@ int pa_sap_recv(pa_sap_context *c, bool *goodbye) { if ((unsigned) size >= sizeof(MIME_TYPE) && pa_streq(e, MIME_TYPE)) { e += sizeof(MIME_TYPE); size -= (int) sizeof(MIME_TYPE); - } else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) { + } else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1) + || strcspn(e, "\r\n") != sizeof(PA_SDP_HEADER)-1) { + /* SDP header does not start with v=0[\r]\n */ pa_log_warn("Invalid SDP header."); goto fail; } diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index c3203ba62..bf131a27e 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -73,7 +73,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u pa_assert_se(inet_ntop(af, dst, buf_dst, sizeof(buf_dst))); return pa_sprintf_malloc( - PA_SDP_HEADER + PA_SDP_HEADER "\n" "o=%s %lu 0 IN %s %s\n" "s=%s\n" "c=IN %s %s\n" @@ -131,17 +131,29 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { i->payload = 255; i->enable_opus = false; - if (!pa_startswith(t, PA_SDP_HEADER)) { + if (pa_startswith(t, PA_SDP_HEADER)) { + t += sizeof(PA_SDP_HEADER) - 1; + + /* CR delimiter is optional */ + if (*t == '\r') + t++; + + /* LF delimiter is mandatory */ + if (*t == '\n') + t++; + else { + pa_log("Failed to parse SDP data: missing header record terminator LF."); + goto fail; + } + } else { pa_log("Failed to parse SDP data: invalid header."); goto fail; } - t += sizeof(PA_SDP_HEADER)-1; - while (*t) { size_t l; - l = strcspn(t, "\n"); + l = strcspn(t, "\r\n"); if (l <= 2) { pa_log("Failed to parse SDP data: line too short: >%s<.", t); @@ -241,8 +253,17 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { t += l; + /* CR delimiter is optional */ + if (*t == '\r') + t++; + + /* LF delimiter is mandatory */ if (*t == '\n') t++; + else { + pa_log("Failed to parse SDP data: missing record terminator LF."); + goto fail; + } } if (!i->origin || (!is_goodbye && (!i->salen || i->payload > 127 || !ss_valid || port == 0))) { diff --git a/src/modules/rtp/sdp.h b/src/modules/rtp/sdp.h index 28c755a27..80ab3636e 100644 --- a/src/modules/rtp/sdp.h +++ b/src/modules/rtp/sdp.h @@ -26,7 +26,7 @@ #include -#define PA_SDP_HEADER "v=0\n" +#define PA_SDP_HEADER "v=0" typedef struct pa_sdp_info { char *origin;