[Asterisk-code-review] rtp: Enable srtp replay protection (asterisk[17.9])
George Joseph
asteriskteam at digium.com
Thu Feb 18 10:36:50 CST 2021
George Joseph has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/15469 )
Change subject: rtp: Enable srtp replay protection
......................................................................
rtp: Enable srtp replay protection
Add option "srtpreplayprotection" rtp.conf to enable srtp
replay protection.
ASTERISK-29260
Reported by: Alexander Traud
Change-Id: I5cd346e3c6b6812039d1901aa4b7be688173b458
---
M configs/samples/rtp.conf.sample
A doc/CHANGES-staging/srtp_replay_protection.txt
A doc/UPGRADE-staging/srtp_replay_protection.txt
M res/res_rtp_asterisk.c
M res/res_srtp.c
5 files changed, 43 insertions(+), 4 deletions(-)
Approvals:
George Joseph: Looks good to me, approved; Approved for Submit
diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample
index f002449..7ab81b3 100644
--- a/configs/samples/rtp.conf.sample
+++ b/configs/samples/rtp.conf.sample
@@ -45,6 +45,18 @@
; connected. This option is set to 4 by default.
; probation=8
;
+; Enable sRTP replay protection. Buggy SIP user agents (UAs) reset the
+; sequence number (RTP-SEQ) on a re-INVITE, for example, with Session Timers
+; or on Call Hold/Resume, but keep the synchronization source (RTP-SSRC). If
+; the new RTP-SEQ is higher than the previous one, the call continues if the
+; roll-over counter (sRTP-ROC) is zero (the call lasted less than 22 minutes).
+; In all other cases, the call faces one-way audio or even no audio at all.
+; "replay check failed (index too old)" gets printed continuously. This is a
+; software bug. You have to report this to the creator of that UA. Until it is
+; fixed, you could disable sRTP replay protection (see RFC 3711 section 3.3.2).
+; This option is enabled by default.
+; srtpreplayprotection=yes
+;
; Whether to enable or disable ICE support. This option is enabled by default.
; icesupport=false
;
diff --git a/doc/CHANGES-staging/srtp_replay_protection.txt b/doc/CHANGES-staging/srtp_replay_protection.txt
new file mode 100644
index 0000000..945ddb5
--- /dev/null
+++ b/doc/CHANGES-staging/srtp_replay_protection.txt
@@ -0,0 +1,9 @@
+Subject: res_srtp
+
+SRTP replay protection has been added to res_srtp and
+a new configuration option "srtpreplayprotection" has
+been added to the rtp.conf config file. For security
+reasons, the default setting is "yes". Buggy clients
+may not handle this correctly which could result in
+no, or one way, audio and Asterisk error messages like
+"replay check failed".
diff --git a/doc/UPGRADE-staging/srtp_replay_protection.txt b/doc/UPGRADE-staging/srtp_replay_protection.txt
new file mode 100644
index 0000000..945ddb5
--- /dev/null
+++ b/doc/UPGRADE-staging/srtp_replay_protection.txt
@@ -0,0 +1,9 @@
+Subject: res_srtp
+
+SRTP replay protection has been added to res_srtp and
+a new configuration option "srtpreplayprotection" has
+been added to the rtp.conf config file. For security
+reasons, the default setting is "yes". Buggy clients
+may not handle this correctly which could result in
+no, or one way, audio and Asterisk error messages like
+"replay check failed".
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 2ed1831..5a41d9c 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -179,6 +179,7 @@
#define STRICT_RTP_LEARN_TIMEOUT 5000
#define DEFAULT_STRICT_RTP STRICT_RTP_YES /*!< Enabled by default */
+#define DEFAULT_SRTP_REPLAY_PROTECTION 1
#define DEFAULT_ICESUPPORT 1
#define DEFAULT_DTLS_MTU 1200
@@ -203,6 +204,7 @@
static int strictrtp = DEFAULT_STRICT_RTP; /*!< Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode. */
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL; /*!< Number of sequential RTP frames needed from a single source during learning mode to accept new source. */
static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION; /*!< Lowest acceptable timeout between the first and the last sequential RTP frame. */
+static int srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION;
#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
static int dtls_mtu = DEFAULT_DTLS_MTU;
#endif
@@ -6022,7 +6024,7 @@
/* If this is encrypted then decrypt the payload */
if ((*rtcpheader & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
- srtp, rtcpheader, &len, 1) < 0) {
+ srtp, rtcpheader, &len, 1 | (srtp_replay_protection << 1)) < 0) {
return &ast_null_frame;
}
@@ -7109,7 +7111,7 @@
/* If this payload is encrypted then decrypt it using the given SRTP instance */
if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
- srtp, read_area, &res, 0) < 0) {
+ srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
return &ast_null_frame;
}
@@ -8897,6 +8899,8 @@
if (strictrtp) {
ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
}
+
+ ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
#ifdef HAVE_PJPROJECT
ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
#endif
@@ -8999,6 +9003,7 @@
strictrtp = DEFAULT_STRICT_RTP;
learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;
learning_min_duration = DEFAULT_LEARNING_MIN_DURATION;
+ srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION;
/** This resource is not "reloaded" so much as unloaded and loaded again.
* In the case of the TURN related variables, the memory referenced by a
@@ -9078,6 +9083,9 @@
}
learning_min_duration = CALC_LEARNING_MIN_DURATION(learning_min_sequential);
}
+ if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
+ srtp_replay_protection = ast_true(s);
+ }
#ifdef HAVE_PJPROJECT
if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
icesupport = ast_true(s);
diff --git a/res/res_srtp.c b/res/res_srtp.c
index 7874216..3519def 100644
--- a/res/res_srtp.c
+++ b/res/res_srtp.c
@@ -364,11 +364,12 @@
}
/* Vtable functions */
-static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rtcp)
+static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int flags)
{
int res = 0;
int i;
- int retry = 0;
+ int rtcp = (flags & 0x01) >> 0;
+ int retry = (flags & 0x02) >> 1;
struct ast_rtp_instance_stats stats = {0,};
tryagain:
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/15469
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: 17.9
Gerrit-Change-Id: I5cd346e3c6b6812039d1901aa4b7be688173b458
Gerrit-Change-Number: 15469
Gerrit-PatchSet: 2
Gerrit-Owner: Joshua Colp <jcolp at sangoma.com>
Gerrit-Reviewer: Alexander Traud <pabstraud at compuserve.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-CC: Friendly Automation
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210218/58eba312/attachment.html>
More information about the asterisk-code-review
mailing list