diff options
author | Armin Kuster <akuster@mvista.com> | 2015-10-26 16:31:22 -0700 |
---|---|---|
committer | Martin Jansa <Martin.Jansa@gmail.com> | 2016-02-08 14:13:39 +0100 |
commit | 5b2e937448371626cf71b761e3bfb06ffb60a7ee (patch) | |
tree | 93dded2f09e03ac611c9d9f333c0562ec75ac62a | |
parent | e8a8e0be8e39dbb949bf0f0df90abe1c4e3f6470 (diff) | |
download | meta-openembedded-5b2e937448371626cf71b761e3bfb06ffb60a7ee.tar.gz |
squid: serveral missing security fixes
SQUID-2015:2 - Does not affect Squid-3.4 and older versions are not vulnerable.
CVE-2015-5400
CVE-2015-3455
CVE-2014-7142
CVE-2014-7141
CVE-2014-6270
see http://www.squid-cache.org/Advisories/
Signed-off-by: Armin Kuster <akuster@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
5 files changed, 692 insertions, 0 deletions
diff --git a/meta-networking/recipes-daemons/squid/files/CVE-2014-6270.patch b/meta-networking/recipes-daemons/squid/files/CVE-2014-6270.patch new file mode 100644 index 000000000..8f876340e --- /dev/null +++ b/meta-networking/recipes-daemons/squid/files/CVE-2014-6270.patch | |||
@@ -0,0 +1,61 @@ | |||
1 | Fix: CVE-2014-3609 | ||
2 | |||
3 | revno: 13172 | ||
4 | revision-id: squid3@treenet.co.nz-20140915045834-qo85nnsinp9wu4gt | ||
5 | parent: squid3@treenet.co.nz-20140827142207-n6y0r0iuv4sq6hvg | ||
6 | author: Sebastian Krahmer <krahmer@suse.com> | ||
7 | committer: Amos Jeffries <squid3@treenet.co.nz> | ||
8 | branch nick: 3.4 | ||
9 | timestamp: Sun 2014-09-14 22:58:34 -0600 | ||
10 | message: | ||
11 | Fix off by one in SNMP subsystem | ||
12 | ------------------------------------------------------------ | ||
13 | # Bazaar merge directive format 2 (Bazaar 0.90) | ||
14 | # revision_id: squid3@treenet.co.nz-20140915045834-qo85nnsinp9wu4gt | ||
15 | # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
16 | # testament_sha1: 72ffc18d9c25a0412efc813dc5cde1c63e8ebe46 | ||
17 | # timestamp: 2014-09-15 11:08:17 +0000 | ||
18 | # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
19 | # base_revision_id: squid3@treenet.co.nz-20140827142207-\ | ||
20 | # n6y0r0iuv4sq6hvg | ||
21 | # | ||
22 | # Begin patch | ||
23 | |||
24 | Upstream-Status: Backport | ||
25 | |||
26 | http://www.squid-cache.org/Versions/v3/3.4/changesets/squid-3.4-13172.patch | ||
27 | |||
28 | Signed-of-by: Armin Kuster <akuster@mvista.com> | ||
29 | |||
30 | === modified file 'src/snmp_core.cc' | ||
31 | --- a/src/snmp_core.cc 2014-02-18 08:46:49 +0000 | ||
32 | +++ b/src/snmp_core.cc 2014-09-15 04:58:34 +0000 | ||
33 | @@ -362,7 +362,7 @@ | ||
34 | void | ||
35 | snmpHandleUdp(int sock, void *not_used) | ||
36 | { | ||
37 | - LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE); | ||
38 | + static char buf[SNMP_REQUEST_SIZE]; | ||
39 | Ip::Address from; | ||
40 | SnmpRequest *snmp_rq; | ||
41 | int len; | ||
42 | @@ -371,16 +371,11 @@ | ||
43 | |||
44 | Comm::SetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); | ||
45 | |||
46 | - memset(buf, '\0', SNMP_REQUEST_SIZE); | ||
47 | + memset(buf, '\0', sizeof(buf)); | ||
48 | |||
49 | - len = comm_udp_recvfrom(sock, | ||
50 | - buf, | ||
51 | - SNMP_REQUEST_SIZE, | ||
52 | - 0, | ||
53 | - from); | ||
54 | + len = comm_udp_recvfrom(sock, buf, sizeof(buf)-1, 0, from); | ||
55 | |||
56 | if (len > 0) { | ||
57 | - buf[len] = '\0'; | ||
58 | debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << "."); | ||
59 | |||
60 | snmp_rq = (SnmpRequest *)xcalloc(1, sizeof(SnmpRequest)); | ||
61 | |||
diff --git a/meta-networking/recipes-daemons/squid/files/CVE-2014-7141_CVE-2014-7142.patch b/meta-networking/recipes-daemons/squid/files/CVE-2014-7141_CVE-2014-7142.patch new file mode 100644 index 000000000..5d4c6202a --- /dev/null +++ b/meta-networking/recipes-daemons/squid/files/CVE-2014-7141_CVE-2014-7142.patch | |||
@@ -0,0 +1,282 @@ | |||
1 | Fix: CVE-2014-7141 CVE-2014-7142 | ||
2 | |||
3 | revno: 13173 | ||
4 | revision-id: squid3@treenet.co.nz-20140915050614-6uo8tfwrpbrd47kw | ||
5 | parent: squid3@treenet.co.nz-20140915045834-qo85nnsinp9wu4gt | ||
6 | author: Amos Jeffries <squid3@treenet.co.nz>, Sebastian Krahmer <krahmer@suse.com> | ||
7 | committer: Amos Jeffries <squid3@treenet.co.nz> | ||
8 | branch nick: 3.4 | ||
9 | timestamp: Sun 2014-09-14 23:06:14 -0600 | ||
10 | message: | ||
11 | Fix various ICMP handling issues in Squid pinger | ||
12 | |||
13 | * ICMP code type logging display could over-read the registered type | ||
14 | string arrays. | ||
15 | |||
16 | * Malformed ICMP packets were accepted into processing with undefined | ||
17 | and potentially nasty results. | ||
18 | |||
19 | Both sets of flaws can result in pinger segmentation fault and halting | ||
20 | the Squid functionality relying on pinger for correct operation. | ||
21 | |||
22 | Thanks to the OpenSUSE project for analysis and resolution of these. | ||
23 | ------------------------------------------------------------ | ||
24 | # Bazaar merge directive format 2 (Bazaar 0.90) | ||
25 | # revision_id: squid3@treenet.co.nz-20140915050614-6uo8tfwrpbrd47kw | ||
26 | # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
27 | # testament_sha1: 234c1592673c5317e1b323018226e04941cc61a8 | ||
28 | # timestamp: 2014-09-15 11:08:18 +0000 | ||
29 | # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
30 | # base_revision_id: squid3@treenet.co.nz-20140915045834-\ | ||
31 | # qo85nnsinp9wu4gt | ||
32 | # | ||
33 | # Begin patch | ||
34 | |||
35 | Upstream-Status: Backport | ||
36 | |||
37 | http://www.squid-cache.org/Versions/v3/3.4/changesets/squid-3.4-13173.patch | ||
38 | |||
39 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
40 | |||
41 | === modified file 'src/icmp/Icmp4.cc' | ||
42 | --- a/src/icmp/Icmp4.cc 2013-06-03 14:05:16 +0000 | ||
43 | +++ b/src/icmp/Icmp4.cc 2014-09-15 05:06:14 +0000 | ||
44 | @@ -41,26 +41,38 @@ | ||
45 | #include "IcmpPinger.h" | ||
46 | #include "Debug.h" | ||
47 | |||
48 | -const char *icmpPktStr[] = { | ||
49 | - "Echo Reply", | ||
50 | - "ICMP 1", | ||
51 | - "ICMP 2", | ||
52 | - "Destination Unreachable", | ||
53 | - "Source Quench", | ||
54 | - "Redirect", | ||
55 | - "ICMP 6", | ||
56 | - "ICMP 7", | ||
57 | - "Echo", | ||
58 | - "ICMP 9", | ||
59 | - "ICMP 10", | ||
60 | - "Time Exceeded", | ||
61 | - "Parameter Problem", | ||
62 | - "Timestamp", | ||
63 | - "Timestamp Reply", | ||
64 | - "Info Request", | ||
65 | - "Info Reply", | ||
66 | - "Out of Range Type" | ||
67 | -}; | ||
68 | +static const char * | ||
69 | +IcmpPacketType(uint8_t v) | ||
70 | +{ | ||
71 | + static const char *icmpPktStr[] = { | ||
72 | + "Echo Reply", | ||
73 | + "ICMP 1", | ||
74 | + "ICMP 2", | ||
75 | + "Destination Unreachable", | ||
76 | + "Source Quench", | ||
77 | + "Redirect", | ||
78 | + "ICMP 6", | ||
79 | + "ICMP 7", | ||
80 | + "Echo", | ||
81 | + "ICMP 9", | ||
82 | + "ICMP 10", | ||
83 | + "Time Exceeded", | ||
84 | + "Parameter Problem", | ||
85 | + "Timestamp", | ||
86 | + "Timestamp Reply", | ||
87 | + "Info Request", | ||
88 | + "Info Reply", | ||
89 | + "Out of Range Type" | ||
90 | + }; | ||
91 | + | ||
92 | + if (v > 17) { | ||
93 | + static char buf[50]; | ||
94 | + snprintf(buf, sizeof(buf), "ICMP %u (invalid)", v); | ||
95 | + return buf; | ||
96 | + } | ||
97 | + | ||
98 | + return icmpPktStr[v]; | ||
99 | +} | ||
100 | |||
101 | Icmp4::Icmp4() : Icmp() | ||
102 | { | ||
103 | @@ -187,6 +199,12 @@ | ||
104 | from->ai_addr, | ||
105 | &from->ai_addrlen); | ||
106 | |||
107 | + if (n <= 0) { | ||
108 | + debugs(42, DBG_CRITICAL, HERE << "Error when calling recvfrom() on ICMP socket."); | ||
109 | + Ip::Address::FreeAddrInfo(from); | ||
110 | + return; | ||
111 | + } | ||
112 | + | ||
113 | preply.from = *from; | ||
114 | |||
115 | #if GETTIMEOFDAY_NO_TZP | ||
116 | @@ -243,9 +261,15 @@ | ||
117 | |||
118 | preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ); | ||
119 | |||
120 | + if (preply.psize < 0) { | ||
121 | + debugs(42, DBG_CRITICAL, HERE << "Malformed ICMP packet."); | ||
122 | + Ip::Address::FreeAddrInfo(from); | ||
123 | + return; | ||
124 | + } | ||
125 | + | ||
126 | control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) ); | ||
127 | |||
128 | - Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops); | ||
129 | + Log(preply.from, icmp->icmp_type, IcmpPacketType(icmp->icmp_type), preply.rtt, preply.hops); | ||
130 | Ip::Address::FreeAddrInfo(from); | ||
131 | } | ||
132 | |||
133 | |||
134 | === modified file 'src/icmp/Icmp6.cc' | ||
135 | --- a/src/icmp/Icmp6.cc 2013-06-03 14:05:16 +0000 | ||
136 | +++ b/src/icmp/Icmp6.cc 2014-09-15 05:06:14 +0000 | ||
137 | @@ -50,57 +50,61 @@ | ||
138 | |||
139 | // Icmp6 OP-Codes | ||
140 | // see http://www.iana.org/assignments/icmpv6-parameters | ||
141 | -// NP: LowPktStr is for codes 0-127 | ||
142 | -static const char *icmp6LowPktStr[] = { | ||
143 | - "ICMP 0", // 0 | ||
144 | - "Destination Unreachable", // 1 - RFC2463 | ||
145 | - "Packet Too Big", // 2 - RFC2463 | ||
146 | - "Time Exceeded", // 3 - RFC2463 | ||
147 | - "Parameter Problem", // 4 - RFC2463 | ||
148 | - "ICMP 5", // 5 | ||
149 | - "ICMP 6", // 6 | ||
150 | - "ICMP 7", // 7 | ||
151 | - "ICMP 8", // 8 | ||
152 | - "ICMP 9", // 9 | ||
153 | - "ICMP 10" // 10 | ||
154 | -}; | ||
155 | - | ||
156 | -// NP: HighPktStr is for codes 128-255 | ||
157 | -static const char *icmp6HighPktStr[] = { | ||
158 | - "Echo Request", // 128 - RFC2463 | ||
159 | - "Echo Reply", // 129 - RFC2463 | ||
160 | - "Multicast Listener Query", // 130 - RFC2710 | ||
161 | - "Multicast Listener Report", // 131 - RFC2710 | ||
162 | - "Multicast Listener Done", // 132 - RFC2710 | ||
163 | - "Router Solicitation", // 133 - RFC4861 | ||
164 | - "Router Advertisement", // 134 - RFC4861 | ||
165 | - "Neighbor Solicitation", // 135 - RFC4861 | ||
166 | - "Neighbor Advertisement", // 136 - RFC4861 | ||
167 | - "Redirect Message", // 137 - RFC4861 | ||
168 | - "Router Renumbering", // 138 - Crawford | ||
169 | - "ICMP Node Information Query", // 139 - RFC4620 | ||
170 | - "ICMP Node Information Response", // 140 - RFC4620 | ||
171 | - "Inverse Neighbor Discovery Solicitation", // 141 - RFC3122 | ||
172 | - "Inverse Neighbor Discovery Advertisement", // 142 - RFC3122 | ||
173 | - "Version 2 Multicast Listener Report", // 143 - RFC3810 | ||
174 | - "Home Agent Address Discovery Request", // 144 - RFC3775 | ||
175 | - "Home Agent Address Discovery Reply", // 145 - RFC3775 | ||
176 | - "Mobile Prefix Solicitation", // 146 - RFC3775 | ||
177 | - "Mobile Prefix Advertisement", // 147 - RFC3775 | ||
178 | - "Certification Path Solicitation", // 148 - RFC3971 | ||
179 | - "Certification Path Advertisement", // 149 - RFC3971 | ||
180 | - "ICMP Experimental (150)", // 150 - RFC4065 | ||
181 | - "Multicast Router Advertisement", // 151 - RFC4286 | ||
182 | - "Multicast Router Solicitation", // 152 - RFC4286 | ||
183 | - "Multicast Router Termination", // 153 - [RFC4286] | ||
184 | - "ICMP 154", | ||
185 | - "ICMP 155", | ||
186 | - "ICMP 156", | ||
187 | - "ICMP 157", | ||
188 | - "ICMP 158", | ||
189 | - "ICMP 159", | ||
190 | - "ICMP 160" | ||
191 | -}; | ||
192 | +static const char * | ||
193 | +IcmpPacketType(uint8_t v) | ||
194 | +{ | ||
195 | + // NP: LowPktStr is for codes 0-127 | ||
196 | + static const char *icmp6LowPktStr[] = { | ||
197 | + "ICMPv6 0", // 0 | ||
198 | + "Destination Unreachable", // 1 - RFC2463 | ||
199 | + "Packet Too Big", // 2 - RFC2463 | ||
200 | + "Time Exceeded", // 3 - RFC2463 | ||
201 | + "Parameter Problem", // 4 - RFC2463 | ||
202 | + }; | ||
203 | + | ||
204 | + // low codes 1-4 registered | ||
205 | + if (0 < v && v < 5) | ||
206 | + return icmp6LowPktStr[(int)(v&0x7f)]; | ||
207 | + | ||
208 | + // NP: HighPktStr is for codes 128-255 | ||
209 | + static const char *icmp6HighPktStr[] = { | ||
210 | + "Echo Request", // 128 - RFC2463 | ||
211 | + "Echo Reply", // 129 - RFC2463 | ||
212 | + "Multicast Listener Query", // 130 - RFC2710 | ||
213 | + "Multicast Listener Report", // 131 - RFC2710 | ||
214 | + "Multicast Listener Done", // 132 - RFC2710 | ||
215 | + "Router Solicitation", // 133 - RFC4861 | ||
216 | + "Router Advertisement", // 134 - RFC4861 | ||
217 | + "Neighbor Solicitation", // 135 - RFC4861 | ||
218 | + "Neighbor Advertisement", // 136 - RFC4861 | ||
219 | + "Redirect Message", // 137 - RFC4861 | ||
220 | + "Router Renumbering", // 138 - Crawford | ||
221 | + "ICMP Node Information Query", // 139 - RFC4620 | ||
222 | + "ICMP Node Information Response", // 140 - RFC4620 | ||
223 | + "Inverse Neighbor Discovery Solicitation", // 141 - RFC3122 | ||
224 | + "Inverse Neighbor Discovery Advertisement", // 142 - RFC3122 | ||
225 | + "Version 2 Multicast Listener Report", // 143 - RFC3810 | ||
226 | + "Home Agent Address Discovery Request", // 144 - RFC3775 | ||
227 | + "Home Agent Address Discovery Reply", // 145 - RFC3775 | ||
228 | + "Mobile Prefix Solicitation", // 146 - RFC3775 | ||
229 | + "Mobile Prefix Advertisement", // 147 - RFC3775 | ||
230 | + "Certification Path Solicitation", // 148 - RFC3971 | ||
231 | + "Certification Path Advertisement", // 149 - RFC3971 | ||
232 | + "ICMP Experimental (150)", // 150 - RFC4065 | ||
233 | + "Multicast Router Advertisement", // 151 - RFC4286 | ||
234 | + "Multicast Router Solicitation", // 152 - RFC4286 | ||
235 | + "Multicast Router Termination", // 153 - [RFC4286] | ||
236 | + }; | ||
237 | + | ||
238 | + // high codes 127-153 registered | ||
239 | + if (127 < v && v < 154) | ||
240 | + return icmp6HighPktStr[(int)(v&0x7f)]; | ||
241 | + | ||
242 | + // give all others a generic display | ||
243 | + static char buf[50]; | ||
244 | + snprintf(buf, sizeof(buf), "ICMPv6 %u", v); | ||
245 | + return buf; | ||
246 | +} | ||
247 | |||
248 | Icmp6::Icmp6() : Icmp() | ||
249 | { | ||
250 | @@ -236,6 +240,12 @@ | ||
251 | from->ai_addr, | ||
252 | &from->ai_addrlen); | ||
253 | |||
254 | + if (n <= 0) { | ||
255 | + debugs(42, DBG_CRITICAL, HERE << "Error when calling recvfrom() on ICMPv6 socket."); | ||
256 | + Ip::Address::FreeAddrInfo(from); | ||
257 | + return; | ||
258 | + } | ||
259 | + | ||
260 | preply.from = *from; | ||
261 | |||
262 | #if GETTIMEOFDAY_NO_TZP | ||
263 | @@ -291,8 +301,7 @@ | ||
264 | |||
265 | default: | ||
266 | debugs(42, 8, HERE << preply.from << " said: " << icmp6header->icmp6_type << "/" << (int)icmp6header->icmp6_code << " " << | ||
267 | - ( icmp6header->icmp6_type&0x80 ? icmp6HighPktStr[(int)(icmp6header->icmp6_type&0x7f)] : icmp6LowPktStr[(int)(icmp6header->icmp6_type&0x7f)] ) | ||
268 | - ); | ||
269 | + IcmpPacketType(icmp6header->icmp6_type)); | ||
270 | } | ||
271 | Ip::Address::FreeAddrInfo(from); | ||
272 | return; | ||
273 | @@ -331,7 +340,7 @@ | ||
274 | |||
275 | Log(preply.from, | ||
276 | icmp6header->icmp6_type, | ||
277 | - ( icmp6header->icmp6_type&0x80 ? icmp6HighPktStr[(int)(icmp6header->icmp6_type&0x7f)] : icmp6LowPktStr[(int)(icmp6header->icmp6_type&0x7f)] ), | ||
278 | + IcmpPacketType(icmp6header->icmp6_type), | ||
279 | preply.rtt, | ||
280 | preply.hops); | ||
281 | |||
282 | |||
diff --git a/meta-networking/recipes-daemons/squid/files/CVE-2015-3455.patch b/meta-networking/recipes-daemons/squid/files/CVE-2015-3455.patch new file mode 100644 index 000000000..409f9a7f1 --- /dev/null +++ b/meta-networking/recipes-daemons/squid/files/CVE-2015-3455.patch | |||
@@ -0,0 +1,53 @@ | |||
1 | Fix: CVE-2015-3455 | ||
2 | |||
3 | ------------------------------------------------------------ | ||
4 | revno: 13222 | ||
5 | revision-id: squid3@treenet.co.nz-20150501071651-songz1j26frb2ytz | ||
6 | parent: squid3@treenet.co.nz-20150501071104-vd21fu43lvmqoqwa | ||
7 | author: Amos Jeffries <amosjeffries@squid-cache.org>, Christos Tsantilas <chtsanti@users.sourceforge.net> | ||
8 | committer: Amos Jeffries <squid3@treenet.co.nz> | ||
9 | branch nick: 3.4 | ||
10 | timestamp: Fri 2015-05-01 00:16:51 -0700 | ||
11 | message: | ||
12 | Fix X509 server certificate domain matching | ||
13 | |||
14 | The X509 certificate domain fields may contain non-ASCII encodings. | ||
15 | Ensure the domain match algorithm is only passed UTF-8 ASCII-compatible | ||
16 | strings. | ||
17 | ------------------------------------------------------------ | ||
18 | # Bazaar merge directive format 2 (Bazaar 0.90) | ||
19 | # revision_id: squid3@treenet.co.nz-20150501071651-songz1j26frb2ytz | ||
20 | # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
21 | # testament_sha1: e38694c3e222c506740510557d2a7a122786225c | ||
22 | # timestamp: 2015-05-01 07:17:25 +0000 | ||
23 | # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
24 | # base_revision_id: squid3@treenet.co.nz-20150501071104-\ | ||
25 | # vd21fu43lvmqoqwa | ||
26 | # | ||
27 | # Begin patch | ||
28 | |||
29 | Upstream-Status: Backport | ||
30 | |||
31 | http://www.squid-cache.org/Versions/v3/3.4/changesets/squid-3.4-13222.patch | ||
32 | |||
33 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
34 | |||
35 | === modified file 'src/ssl/support.cc' | ||
36 | --- a/src/ssl/support.cc 2015-01-24 05:07:58 +0000 | ||
37 | +++ b/src/ssl/support.cc 2015-05-01 07:16:51 +0000 | ||
38 | @@ -209,7 +209,13 @@ | ||
39 | if (cn_data->length > (int)sizeof(cn) - 1) { | ||
40 | return 1; //if does not fit our buffer just ignore | ||
41 | } | ||
42 | - memcpy(cn, cn_data->data, cn_data->length); | ||
43 | + char *s = reinterpret_cast<char*>(cn_data->data); | ||
44 | + char *d = cn; | ||
45 | + for (int i = 0; i < cn_data->length; ++i, ++d, ++s) { | ||
46 | + if (*s == '\0') | ||
47 | + return 1; // always a domain mismatch. contains 0x00 | ||
48 | + *d = *s; | ||
49 | + } | ||
50 | cn[cn_data->length] = '\0'; | ||
51 | debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn); | ||
52 | return matchDomainName(server, cn[0] == '*' ? cn + 1 : cn); | ||
53 | |||
diff --git a/meta-networking/recipes-daemons/squid/files/CVE-2015-5400.patch b/meta-networking/recipes-daemons/squid/files/CVE-2015-5400.patch new file mode 100644 index 000000000..41af2b101 --- /dev/null +++ b/meta-networking/recipes-daemons/squid/files/CVE-2015-5400.patch | |||
@@ -0,0 +1,292 @@ | |||
1 | Fix: CVE-2015-5400 | ||
2 | |||
3 | ------------------------------------------------------------ | ||
4 | revno: 13225 | ||
5 | revision-id: squid3@treenet.co.nz-20150709032133-qg1patn5zngt4o4h | ||
6 | parent: squid3@treenet.co.nz-20150501100500-3utkhrao1yrd8ig6 | ||
7 | author: Alex Rousskov <rousskov@measurement-factory.com> | ||
8 | committer: Amos Jeffries <squid3@treenet.co.nz> | ||
9 | branch nick: 3.4 | ||
10 | timestamp: Wed 2015-07-08 20:21:33 -0700 | ||
11 | message: | ||
12 | Do not blindly forward cache peer CONNECT responses. | ||
13 | |||
14 | Squid blindly forwards cache peer CONNECT responses to clients. This | ||
15 | may break things if the peer responds with something like HTTP 403 | ||
16 | (Forbidden) and keeps the connection with Squid open: | ||
17 | - The client application issues a CONNECT request. | ||
18 | - Squid forwards this request to a cache peer. | ||
19 | - Cache peer correctly responds back with a "403 Forbidden". | ||
20 | - Squid does not parse cache peer response and | ||
21 | just forwards it as if it was a Squid response to the client. | ||
22 | - The TCP connections are not closed. | ||
23 | |||
24 | At this stage, Squid is unaware that the CONNECT request has failed. All | ||
25 | subsequent requests on the user agent TCP connection are treated as | ||
26 | tunnelled traffic. Squid is forwarding these requests to the peer on the | ||
27 | TCP connection previously used for the 403-ed CONNECT request, without | ||
28 | proper processing. The additional headers which should have been applied | ||
29 | by Squid to these requests are not applied, and the requests are being | ||
30 | forwarded to the cache peer even though the Squid configuration may | ||
31 | state that these requests must go directly to the origin server. | ||
32 | |||
33 | This fixes Squid to parse cache peer responses, and if an error response | ||
34 | found, respond with "502 Bad Gateway" to the client and close the | ||
35 | connections. | ||
36 | ------------------------------------------------------------ | ||
37 | # Bazaar merge directive format 2 (Bazaar 0.90) | ||
38 | # revision_id: squid3@treenet.co.nz-20150709032133-qg1patn5zngt4o4h | ||
39 | # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
40 | # testament_sha1: 6cbce093f30c8a09173eb610eaa423c7c305ff23 | ||
41 | # timestamp: 2015-07-09 03:40:35 +0000 | ||
42 | # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 | ||
43 | # base_revision_id: squid3@treenet.co.nz-20150501100500-\ | ||
44 | # 3utkhrao1yrd8ig6 | ||
45 | # | ||
46 | # Begin patch | ||
47 | |||
48 | Upstream-Status: Backport | ||
49 | http://www.squid-cache.org/Versions/v3/3.4/changesets/squid-3.4-13225.patch | ||
50 | |||
51 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
52 | |||
53 | === modified file 'src/tunnel.cc' | ||
54 | --- a/src/tunnel.cc 2014-04-26 10:58:22 +0000 | ||
55 | +++ b/src/tunnel.cc 2015-07-09 03:21:33 +0000 | ||
56 | @@ -122,6 +122,10 @@ | ||
57 | (request->flags.interceptTproxy || request->flags.intercepted)); | ||
58 | } | ||
59 | |||
60 | + /// Sends "502 Bad Gateway" error response to the client, | ||
61 | + /// if it is waiting for Squid CONNECT response, closing connections. | ||
62 | + void informUserOfPeerError(const char *errMsg); | ||
63 | + | ||
64 | class Connection | ||
65 | { | ||
66 | |||
67 | @@ -139,13 +143,14 @@ | ||
68 | |||
69 | void error(int const xerrno); | ||
70 | int debugLevelForError(int const xerrno) const; | ||
71 | - /// handles a non-I/O error associated with this Connection | ||
72 | - void logicError(const char *errMsg); | ||
73 | void closeIfOpen(); | ||
74 | void dataSent (size_t amount); | ||
75 | + /// writes 'b' buffer, setting the 'writer' member to 'callback'. | ||
76 | + void write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func); | ||
77 | int len; | ||
78 | char *buf; | ||
79 | int64_t *size_ptr; /* pointer to size in an ConnStateData for logging */ | ||
80 | + AsyncCall::Pointer writer; ///< pending Comm::Write callback | ||
81 | |||
82 | Comm::ConnectionPointer conn; ///< The currently connected connection. | ||
83 | |||
84 | @@ -195,13 +200,14 @@ | ||
85 | TunnelStateData *tunnelState = (TunnelStateData *)params.data; | ||
86 | debugs(26, 3, HERE << tunnelState->server.conn); | ||
87 | tunnelState->server.conn = NULL; | ||
88 | + tunnelState->server.writer = NULL; | ||
89 | |||
90 | if (tunnelState->noConnections()) { | ||
91 | delete tunnelState; | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | - if (!tunnelState->server.len) { | ||
96 | + if (!tunnelState->client.writer) { | ||
97 | tunnelState->client.conn->close(); | ||
98 | return; | ||
99 | } | ||
100 | @@ -213,13 +219,14 @@ | ||
101 | TunnelStateData *tunnelState = (TunnelStateData *)params.data; | ||
102 | debugs(26, 3, HERE << tunnelState->client.conn); | ||
103 | tunnelState->client.conn = NULL; | ||
104 | + tunnelState->client.writer = NULL; | ||
105 | |||
106 | if (tunnelState->noConnections()) { | ||
107 | delete tunnelState; | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | - if (!tunnelState->client.len) { | ||
112 | + if (!tunnelState->server.writer) { | ||
113 | tunnelState->server.conn->close(); | ||
114 | return; | ||
115 | } | ||
116 | @@ -343,6 +350,23 @@ | ||
117 | handleConnectResponse(len); | ||
118 | } | ||
119 | |||
120 | +void | ||
121 | +TunnelStateData::informUserOfPeerError(const char *errMsg) | ||
122 | +{ | ||
123 | + server.len = 0; | ||
124 | + if (!clientExpectsConnectResponse()) { | ||
125 | + // closing the connection is the best we can do here | ||
126 | + debugs(50, 3, server.conn << " closing on error: " << errMsg); | ||
127 | + server.conn->close(); | ||
128 | + return; | ||
129 | + } | ||
130 | + ErrorState *err = new ErrorState(ERR_CONNECT_FAIL, Http::scBadGateway, request.getRaw()); | ||
131 | + err->callback = tunnelErrorComplete; | ||
132 | + err->callback_data = this; | ||
133 | + *status_ptr = Http::scBadGateway; | ||
134 | + errorSend(http->getConn()->clientConnection, err); | ||
135 | +} | ||
136 | + | ||
137 | /* Read from client side and queue it for writing to the server */ | ||
138 | void | ||
139 | TunnelStateData::ReadConnectResponseDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data) | ||
140 | @@ -374,7 +398,7 @@ | ||
141 | const bool parsed = rep.parse(connectRespBuf, eof, &parseErr); | ||
142 | if (!parsed) { | ||
143 | if (parseErr > 0) { // unrecoverable parsing error | ||
144 | - server.logicError("malformed CONNECT response from peer"); | ||
145 | + informUserOfPeerError("malformed CONNECT response from peer"); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | @@ -383,7 +407,7 @@ | ||
150 | assert(!parseErr); | ||
151 | |||
152 | if (!connectRespBuf->hasSpace()) { | ||
153 | - server.logicError("huge CONNECT response from peer"); | ||
154 | + informUserOfPeerError("huge CONNECT response from peer"); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | @@ -397,7 +421,8 @@ | ||
159 | |||
160 | // bail if we did not get an HTTP 200 (Connection Established) response | ||
161 | if (rep.sline.status() != Http::scOkay) { | ||
162 | - server.logicError("unsupported CONNECT response status code"); | ||
163 | + // if we ever decide to reuse the peer connection, we must extract the error response first | ||
164 | + informUserOfPeerError("unsupported CONNECT response status code"); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | @@ -416,13 +441,6 @@ | ||
169 | } | ||
170 | |||
171 | void | ||
172 | -TunnelStateData::Connection::logicError(const char *errMsg) | ||
173 | -{ | ||
174 | - debugs(50, 3, conn << " closing on error: " << errMsg); | ||
175 | - conn->close(); | ||
176 | -} | ||
177 | - | ||
178 | -void | ||
179 | TunnelStateData::Connection::error(int const xerrno) | ||
180 | { | ||
181 | /* XXX fixme xstrerror and xerrno... */ | ||
182 | @@ -517,7 +535,7 @@ | ||
183 | debugs(26, 3, HERE << "Schedule Write"); | ||
184 | AsyncCall::Pointer call = commCbCall(5,5, "TunnelBlindCopyWriteHandler", | ||
185 | CommIoCbPtrFun(completion, this)); | ||
186 | - Comm::Write(to.conn, from.buf, len, call, NULL); | ||
187 | + to.write(from.buf, len, call, NULL); | ||
188 | } | ||
189 | |||
190 | /* Writes data from the client buffer to the server side */ | ||
191 | @@ -526,6 +544,7 @@ | ||
192 | { | ||
193 | TunnelStateData *tunnelState = (TunnelStateData *)data; | ||
194 | assert (cbdataReferenceValid (tunnelState)); | ||
195 | + tunnelState->server.writer = NULL; | ||
196 | |||
197 | tunnelState->writeServerDone(buf, len, flag, xerrno); | ||
198 | } | ||
199 | @@ -575,6 +594,7 @@ | ||
200 | { | ||
201 | TunnelStateData *tunnelState = (TunnelStateData *)data; | ||
202 | assert (cbdataReferenceValid (tunnelState)); | ||
203 | + tunnelState->client.writer = NULL; | ||
204 | |||
205 | tunnelState->writeClientDone(buf, len, flag, xerrno); | ||
206 | } | ||
207 | @@ -592,7 +612,14 @@ | ||
208 | } | ||
209 | |||
210 | void | ||
211 | -TunnelStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno) | ||
212 | +TunnelStateData::Connection::write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func) | ||
213 | +{ | ||
214 | + writer = callback; | ||
215 | + Comm::Write(conn, b, size, callback, free_func); | ||
216 | +} | ||
217 | + | ||
218 | +void | ||
219 | +TunnelStateData::writeClientDone(char *, size_t len, comm_err_t flag, int xerrno) | ||
220 | { | ||
221 | debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag); | ||
222 | |||
223 | @@ -712,6 +739,7 @@ | ||
224 | { | ||
225 | TunnelStateData *tunnelState = (TunnelStateData *)data; | ||
226 | debugs(26, 3, HERE << conn << ", flag=" << flag); | ||
227 | + tunnelState->client.writer = NULL; | ||
228 | |||
229 | if (flag != COMM_OK) { | ||
230 | *tunnelState->status_ptr = Http::scInternalServerError; | ||
231 | @@ -728,6 +756,7 @@ | ||
232 | { | ||
233 | TunnelStateData *tunnelState = (TunnelStateData *)data; | ||
234 | debugs(26, 3, conn << ", flag=" << flag); | ||
235 | + tunnelState->server.writer = NULL; | ||
236 | assert(tunnelState->waitingForConnectRequest()); | ||
237 | |||
238 | if (flag != COMM_OK) { | ||
239 | @@ -768,7 +797,7 @@ | ||
240 | else { | ||
241 | AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone", | ||
242 | CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState)); | ||
243 | - Comm::Write(tunnelState->client.conn, conn_established, strlen(conn_established), call, NULL); | ||
244 | + tunnelState->client.write(conn_established, strlen(conn_established), call, NULL); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | @@ -955,29 +984,20 @@ | ||
249 | debugs(11, 2, "Tunnel Server REQUEST: " << tunnelState->server.conn << ":\n----------\n" << | ||
250 | Raw("tunnelRelayConnectRequest", mb.content(), mb.contentSize()) << "\n----------"); | ||
251 | |||
252 | - if (tunnelState->clientExpectsConnectResponse()) { | ||
253 | - // hack: blindly tunnel peer response (to our CONNECT request) to the client as ours. | ||
254 | - AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectedWriteDone", | ||
255 | - CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState)); | ||
256 | - Comm::Write(srv, &mb, writeCall); | ||
257 | - } else { | ||
258 | - // we have to eat the connect response from the peer (so that the client | ||
259 | - // does not see it) and only then start shoveling data to the client | ||
260 | - AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectReqWriteDone", | ||
261 | - CommIoCbPtrFun(tunnelConnectReqWriteDone, | ||
262 | - tunnelState)); | ||
263 | - Comm::Write(srv, &mb, writeCall); | ||
264 | - tunnelState->connectReqWriting = true; | ||
265 | - | ||
266 | - tunnelState->connectRespBuf = new MemBuf; | ||
267 | - // SQUID_TCP_SO_RCVBUF: we should not accumulate more than regular I/O buffer | ||
268 | - // can hold since any CONNECT response leftovers have to fit into server.buf. | ||
269 | - // 2*SQUID_TCP_SO_RCVBUF: HttpMsg::parse() zero-terminates, which uses space. | ||
270 | - tunnelState->connectRespBuf->init(SQUID_TCP_SO_RCVBUF, 2*SQUID_TCP_SO_RCVBUF); | ||
271 | - tunnelState->readConnectResponse(); | ||
272 | - | ||
273 | - assert(tunnelState->waitingForConnectExchange()); | ||
274 | - } | ||
275 | + AsyncCall::Pointer writeCall = commCbCall(5,5, "tunnelConnectReqWriteDone", | ||
276 | + CommIoCbPtrFun(tunnelConnectReqWriteDone, tunnelState)); | ||
277 | + | ||
278 | + tunnelState->server.write(mb.buf, mb.size, writeCall, mb.freeFunc()); | ||
279 | + tunnelState->connectReqWriting = true; | ||
280 | + | ||
281 | + tunnelState->connectRespBuf = new MemBuf; | ||
282 | + // SQUID_TCP_SO_RCVBUF: we should not accumulate more than regular I/O buffer | ||
283 | + // can hold since any CONNECT response leftovers have to fit into server.buf. | ||
284 | + // 2*SQUID_TCP_SO_RCVBUF: HttpMsg::parse() zero-terminates, which uses space. | ||
285 | + tunnelState->connectRespBuf->init(SQUID_TCP_SO_RCVBUF, 2*SQUID_TCP_SO_RCVBUF); | ||
286 | + tunnelState->readConnectResponse(); | ||
287 | + | ||
288 | + assert(tunnelState->waitingForConnectExchange()); | ||
289 | |||
290 | AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout", | ||
291 | CommTimeoutCbPtrFun(tunnelTimeout, tunnelState)); | ||
292 | |||
diff --git a/meta-networking/recipes-daemons/squid/squid_3.4.7.bb b/meta-networking/recipes-daemons/squid/squid_3.4.7.bb index c5f616dd4..25940f7fc 100644 --- a/meta-networking/recipes-daemons/squid/squid_3.4.7.bb +++ b/meta-networking/recipes-daemons/squid/squid_3.4.7.bb | |||
@@ -20,6 +20,10 @@ SRC_URI = "http://www.squid-cache.org/Versions/v${MAJ_VER}/${MIN_VER}/${BPN}-${P | |||
20 | file://squid-use-serial-tests-config-needed-by-ptest.patch \ | 20 | file://squid-use-serial-tests-config-needed-by-ptest.patch \ |
21 | file://run-ptest \ | 21 | file://run-ptest \ |
22 | file://volatiles.03_squid \ | 22 | file://volatiles.03_squid \ |
23 | file://CVE-2014-6270.patch \ | ||
24 | file://CVE-2014-7141_CVE-2014-7142.patch \ | ||
25 | file://CVE-2015-3455.patch \ | ||
26 | file://CVE-2015-5400.patch \ | ||
23 | " | 27 | " |
24 | 28 | ||
25 | LIC_FILES_CHKSUM = "file://COPYING;md5=c492e2d6d32ec5c1aad0e0609a141ce9 \ | 29 | LIC_FILES_CHKSUM = "file://COPYING;md5=c492e2d6d32ec5c1aad0e0609a141ce9 \ |