--- res/res_rtp_asterisk.c (Asterisk 13.38.1) +++ res/res_rtp_asterisk.c (working copy) @@ -168,2 +168,3 @@ #define DEFAULT_STRICT_RTP STRICT_RTP_YES /*!< Enabled by default */ +#define DEFAULT_SRTP_REPLAY_PROTECTION 1 #define DEFAULT_ICESUPPORT 1 @@ -192,2 +193,3 @@ static int strictrtp = DEFAULT_STRICT_RT 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) @@ -2716,5 +2718,7 @@ static int __rtp_recvfrom(struct ast_rtp if ((*in & 0xC0) && res_srtp && srtp && res_srtp->unprotect( - srtp, buf, &len, rtcp || rtcp_mux(rtp, buf)) < 0) { + srtp, buf, &len, + (rtcp || rtcp_mux(rtp, buf)) | (srtp_replay_protection << 1) + ) < 0) { return -1; } @@ -6679,4 +6683,6 @@ static char *handle_cli_rtp_settings(str 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)); @@ -6782,2 +6788,3 @@ static int rtp_reload(int reload, int by learning_min_duration = DEFAULT_LEARNING_MIN_DURATION; + srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION; @@ -6860,4 +6867,7 @@ static int rtp_reload(int reload, int by 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"))) { --- res/res_srtp.c (Asterisk 13.38.1) +++ res/res_srtp.c (working copy) @@ -337,9 +337,10 @@ static void ast_srtp_set_cb(struct ast_s /* 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,}; --- configs/samples/rtp.conf.sample (Asterisk 13.38.1) +++ configs/samples/rtp.conf.sample (working copy) @@ -47,2 +47,14 @@ ; +; 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.