asterisk-11.x: add upstream patches for CVEs
[feed/telephony.git] / net / asterisk-11.x / patches / 024-AST-2017-005-11.diff
1 From dc4c130439f053592b86f0b35c1fb219a0dc6587 Mon Sep 17 00:00:00 2001
2 From: Joshua Colp <jcolp@digium.com>
3 Date: Mon, 22 May 2017 15:36:38 +0000
4 Subject: [PATCH] res_rtp_asterisk: Only learn a new source in learn state.
5
6 This change moves the logic which learns a new source address
7 for RTP so it only occurs in the learning state. The learning
8 state is entered on initial allocation of RTP or if we are
9 told that the remote address for the media has changed. While
10 in the learning state if we continue to receive media from
11 the original source we restart the learning process. It is
12 only once we receive a sufficient number of RTP packets from
13 the new source that we will switch to it. Once this is done
14 the closed state is entered where all packets that do not
15 originate from the expected source are dropped.
16
17 The learning process has also been improved to take into
18 account the time between received packets so a flood of them
19 while in the learning state does not cause media to be switched.
20
21 Finally RTCP now drops packets which are not for the learned
22 SSRC if strict RTP is enabled.
23
24 ASTERISK-27013
25
26 Change-Id: I56a96e993700906355e79bc880ad9d4ad3ab129c
27 ---
28
29 diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
30 index 4cdc750..4881171 100644
31 --- a/res/res_rtp_asterisk.c
32 +++ b/res/res_rtp_asterisk.c
33 @@ -201,6 +201,7 @@
34 struct rtp_learning_info {
35 int max_seq; /*!< The highest sequence number received */
36 int packets; /*!< The number of remaining packets before the source is accepted */
37 + struct timeval received; /*!< The time of the last received packet */
38 };
39
40 #ifdef HAVE_OPENSSL_SRTP
41 @@ -286,7 +287,6 @@
42 * but these are in place to keep learning mode sequence values sealed from their normal counterparts.
43 */
44 struct rtp_learning_info rtp_source_learn; /* Learning mode track for the expected RTP source */
45 - struct rtp_learning_info alt_source_learn; /* Learning mode tracking for a new RTP source after one has been chosen */
46
47 struct rtp_red *red;
48
49 @@ -2357,6 +2357,7 @@
50 {
51 info->max_seq = seq - 1;
52 info->packets = learning_min_sequential;
53 + memset(&info->received, 0, sizeof(info->received));
54 }
55
56 /*!
57 @@ -2371,6 +2372,13 @@
58 */
59 static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq)
60 {
61 + if (!ast_tvzero(info->received) && ast_tvdiff_ms(ast_tvnow(), info->received) < 5) {
62 + /* During the probation period the minimum amount of media we'll accept is
63 + * 10ms so give a reasonable 5ms buffer just in case we get it sporadically.
64 + */
65 + return 1;
66 + }
67 +
68 if (seq == info->max_seq + 1) {
69 /* packet is in sequence */
70 info->packets--;
71 @@ -2379,6 +2387,7 @@
72 info->packets = learning_min_sequential - 1;
73 }
74 info->max_seq = seq;
75 + info->received = ast_tvnow();
76
77 return (info->packets == 0);
78 }
79 @@ -2540,7 +2549,6 @@
80 rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
81 if (strictrtp) {
82 rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t)rtp->seqno);
83 - rtp_learning_seq_init(&rtp->alt_source_learn, (uint16_t)rtp->seqno);
84 }
85
86 /* Create a new socket for us to listen on and use */
87 @@ -3910,16 +3918,6 @@
88
89 packetwords = res / 4;
90
91 - if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
92 - /* Send to whoever sent to us */
93 - if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
94 - ast_sockaddr_copy(&rtp->rtcp->them, &addr);
95 - if (rtpdebug)
96 - ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
97 - ast_sockaddr_stringify(&rtp->rtcp->them));
98 - }
99 - }
100 -
101 ast_debug(1, "Got RTCP report of %d bytes\n", res);
102
103 while (position < packetwords) {
104 @@ -3939,6 +3937,24 @@
105 if (rtpdebug)
106 ast_debug(1, "RTCP Read too short\n");
107 return &ast_null_frame;
108 + }
109 +
110 + if ((rtp->strict_rtp_state != STRICT_RTP_OPEN) && (ntohl(rtcpheader[i + 1]) != rtp->themssrc)) {
111 + /* Skip over this RTCP record as it does not contain the correct SSRC */
112 + position += (length + 1);
113 + ast_debug(1, "%p -- Received RTCP report from %s, dropping due to strict RTP protection. Received SSRC '%u' but expected '%u'\n",
114 + rtp, ast_sockaddr_stringify(&addr), ntohl(rtcpheader[i + 1]), rtp->themssrc);
115 + continue;
116 + }
117 +
118 + if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
119 + /* Send to whoever sent to us */
120 + if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
121 + ast_sockaddr_copy(&rtp->rtcp->them, &addr);
122 + if (rtpdebug)
123 + ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
124 + ast_sockaddr_stringify(&rtp->rtcp->them));
125 + }
126 }
127
128 if (rtcp_debug_test_addr(&addr)) {
129 @@ -4330,24 +4346,11 @@
130
131 /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
132 if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
133 - ast_debug(1, "%p -- Probation learning mode pass with source address %s\n", rtp, ast_sockaddr_stringify(&addr));
134 - /* For now, we always copy the address. */
135 - ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
136 -
137 - /* Send the rtp and the seqno from header to rtp_learning_rtp_seq_update to see whether we can exit or not*/
138 - if (rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
139 - ast_debug(1, "%p -- Probation at seq %d with %d to go; discarding frame\n",
140 - rtp, rtp->rtp_source_learn.max_seq, rtp->rtp_source_learn.packets);
141 - return &ast_null_frame;
142 - }
143 -
144 - ast_verb(4, "%p -- Probation passed - setting RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr));
145 - rtp->strict_rtp_state = STRICT_RTP_CLOSED;
146 - }
147 - if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
148 if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
149 - /* Always reset the alternate learning source */
150 - rtp_learning_seq_init(&rtp->alt_source_learn, seqno);
151 + /* We are learning a new address but have received traffic from the existing address,
152 + * accept it but reset the current learning for the new source so it only takes over
153 + * once sufficient traffic has been received. */
154 + rtp_learning_seq_init(&rtp->rtp_source_learn, seqno);
155 } else {
156 /* Hmm, not the strict address. Perhaps we're getting audio from the alternate? */
157 if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) {
158 @@ -4359,15 +4362,21 @@
159 * it, that means we've stopped getting RTP from the original source and we should
160 * switch to it.
161 */
162 - if (rtp_learning_rtp_seq_update(&rtp->alt_source_learn, seqno)) {
163 + if (rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
164 ast_debug(1, "%p -- Received RTP packet from %s, dropping due to strict RTP protection. Will switch to it in %d packets\n",
165 - rtp, ast_sockaddr_stringify(&addr), rtp->alt_source_learn.packets);
166 + rtp, ast_sockaddr_stringify(&addr), rtp->rtp_source_learn.packets);
167 return &ast_null_frame;
168 }
169 - ast_verb(4, "%p -- Switching RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr));
170 ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
171 }
172 +
173 + ast_verb(4, "%p -- Probation passed - setting RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr));
174 + rtp->strict_rtp_state = STRICT_RTP_CLOSED;
175 }
176 + } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED && ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
177 + ast_debug(1, "%p -- Received RTP packet from %s, dropping due to strict RTP protection.\n",
178 + rtp, ast_sockaddr_stringify(&addr));
179 + return &ast_null_frame;
180 }
181
182 /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
183 @@ -4762,7 +4771,11 @@
184
185 rtp->rxseqno = 0;
186
187 - if (strictrtp && rtp->strict_rtp_state != STRICT_RTP_OPEN) {
188 + if (strictrtp && rtp->strict_rtp_state != STRICT_RTP_OPEN && !ast_sockaddr_isnull(addr) &&
189 + ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
190 + /* We only need to learn a new strict source address if we've been told the source is
191 + * changing to something different.
192 + */
193 rtp->strict_rtp_state = STRICT_RTP_LEARN;
194 rtp_learning_seq_init(&rtp->rtp_source_learn, rtp->seqno);
195 }