OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/web_socket_proxy.h" | 5 #include "chrome/browser/chromeos/web_socket_proxy.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string.h> | 9 #include <string.h> |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... |
27 #include "base/basictypes.h" | 27 #include "base/basictypes.h" |
28 #include "base/bind.h" | 28 #include "base/bind.h" |
29 #include "base/lazy_instance.h" | 29 #include "base/lazy_instance.h" |
30 #include "base/logging.h" | 30 #include "base/logging.h" |
31 #include "base/memory/ref_counted.h" | 31 #include "base/memory/ref_counted.h" |
32 #include "base/memory/scoped_ptr.h" | 32 #include "base/memory/scoped_ptr.h" |
33 #include "base/sha1.h" | 33 #include "base/sha1.h" |
34 #include "base/stl_util.h" | 34 #include "base/stl_util.h" |
35 #include "base/string_number_conversions.h" | 35 #include "base/string_number_conversions.h" |
36 #include "base/string_util.h" | 36 #include "base/string_util.h" |
| 37 #include "chrome/browser/chromeos/web_socket_proxy_helper.h" |
37 #include "chrome/browser/internal_auth.h" | 38 #include "chrome/browser/internal_auth.h" |
38 #include "chrome/common/chrome_notification_types.h" | 39 #include "chrome/common/chrome_notification_types.h" |
39 #include "chrome/common/url_constants.h" | 40 #include "chrome/common/url_constants.h" |
40 #include "content/public/browser/browser_thread.h" | 41 #include "content/public/browser/browser_thread.h" |
41 #include "content/public/browser/notification_details.h" | 42 #include "content/public/browser/notification_details.h" |
42 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
43 #include "content/public/browser/notification_types.h" | 44 #include "content/public/browser/notification_types.h" |
44 #include "content/public/common/url_constants.h" | 45 #include "content/public/common/url_constants.h" |
45 #include "googleurl/src/gurl.h" | 46 #include "googleurl/src/gurl.h" |
46 #include "googleurl/src/url_parse.h" | 47 #include "googleurl/src/url_parse.h" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 std::string FetchAsciiSnippet(uint8* begin, uint8* end, AsciiFilter filter) { | 142 std::string FetchAsciiSnippet(uint8* begin, uint8* end, AsciiFilter filter) { |
142 std::string rv; | 143 std::string rv; |
143 for (; begin < end; ++begin) { | 144 for (; begin < end; ++begin) { |
144 if (!isascii(*begin)) | 145 if (!isascii(*begin)) |
145 return rv; | 146 return rv; |
146 rv += filter(*begin); | 147 rv += filter(*begin); |
147 } | 148 } |
148 return rv; | 149 return rv; |
149 } | 150 } |
150 | 151 |
151 // Parses "passport:hostname:port:" string. Returns true on success. | |
152 bool FetchPassportNamePort( | |
153 uint8* begin, uint8* end, | |
154 std::string* passport, std::string* name, int* port) { | |
155 std::string input(begin, end); | |
156 if (input[input.size() - 1] != ':') | |
157 return false; | |
158 input.resize(input.size() - 1); | |
159 | |
160 size_t pos = input.find_last_of(':'); | |
161 if (pos == std::string::npos) | |
162 return false; | |
163 std::string port_str(input, pos + 1); | |
164 if (port_str.empty()) | |
165 return false; | |
166 const char kAsciiDigits[] = "0123456789"; | |
167 COMPILE_ASSERT(sizeof(kAsciiDigits) == 10 + 1, mess_with_digits); | |
168 if (port_str.find_first_not_of(kAsciiDigits) != std::string::npos) | |
169 return false; | |
170 if (!base::StringToInt(port_str, port) || | |
171 *port < 0 || | |
172 *port >= (1 << 16)) { | |
173 return false; | |
174 } | |
175 input.resize(pos); | |
176 | |
177 pos = input.find_first_of(':'); | |
178 if (pos == std::string::npos) | |
179 return false; | |
180 passport->assign(input, 0, pos); | |
181 name->assign(input, pos + 1, std::string::npos); | |
182 return !name->empty(); | |
183 } | |
184 | |
185 std::string FetchExtensionIdFromOrigin(const std::string &origin) { | 152 std::string FetchExtensionIdFromOrigin(const std::string &origin) { |
186 GURL url(origin); | 153 GURL url(origin); |
187 if (url.SchemeIs(chrome::kExtensionScheme)) | 154 if (url.SchemeIs(chrome::kExtensionScheme)) |
188 return url.host(); | 155 return url.host(); |
189 else | 156 else |
190 return std::string(); | 157 return std::string(); |
191 } | 158 } |
192 | 159 |
193 inline size_t strlen(const void* s) { | 160 inline size_t strlen(const void* s) { |
194 return ::strlen(static_cast<const char*>(s)); | 161 return ::strlen(static_cast<const char*>(s)); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 std::map<std::string, std::string> header_fields_; | 411 std::map<std::string, std::string> header_fields_; |
445 | 412 |
446 // Parameters requested via query component of GET resource. | 413 // Parameters requested via query component of GET resource. |
447 std::map<std::string, std::string> requested_parameters_; | 414 std::map<std::string, std::string> requested_parameters_; |
448 | 415 |
449 // Hostname and port of destination socket. | 416 // Hostname and port of destination socket. |
450 // Websocket client supplies them in first data frame (destframe). | 417 // Websocket client supplies them in first data frame (destframe). |
451 std::string destname_; | 418 std::string destname_; |
452 int destport_; | 419 int destport_; |
453 | 420 |
| 421 // Preresolved |destname_| (empty if not pre-resolved). |
| 422 std::string destaddr_; |
| 423 |
454 // Whether TLS over TCP requested. | 424 // Whether TLS over TCP requested. |
455 bool do_tls_; | 425 bool do_tls_; |
456 | 426 |
457 // We try to DNS resolve hostname in both IPv4 and IPv6 domains. | 427 // We try to DNS resolve hostname in both IPv4 and IPv6 domains. |
458 // Track resolution failures here. | 428 // Track resolution failures here. |
459 bool destresolution_ipv4_failed_; | 429 bool destresolution_ipv4_failed_; |
460 bool destresolution_ipv6_failed_; | 430 bool destresolution_ipv6_failed_; |
461 | 431 |
462 // Used to schedule a timeout for initial phase of connection. | 432 // Used to schedule a timeout for initial phase of connection. |
463 scoped_ptr<struct event> destconnect_timeout_event_; | 433 scoped_ptr<struct event> destconnect_timeout_event_; |
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 return STATUS_ABORT; | 1268 return STATUS_ABORT; |
1299 | 1269 |
1300 if (!requested_parameters_.empty()) { | 1270 if (!requested_parameters_.empty()) { |
1301 destname_ = requested_parameters_["hostname"]; | 1271 destname_ = requested_parameters_["hostname"]; |
1302 int port; | 1272 int port; |
1303 if (!base::StringToInt(requested_parameters_["port"], &port) || | 1273 if (!base::StringToInt(requested_parameters_["port"], &port) || |
1304 port < 0 || port >= 1 << 16) { | 1274 port < 0 || port >= 1 << 16) { |
1305 return STATUS_ABORT; | 1275 return STATUS_ABORT; |
1306 } | 1276 } |
1307 destport_ = port; | 1277 destport_ = port; |
| 1278 destaddr_ = requested_parameters_["addr"]; |
1308 do_tls_ = (requested_parameters_["tls"] == "true"); | 1279 do_tls_ = (requested_parameters_["tls"] == "true"); |
1309 | 1280 |
1310 requested_parameters_["extension_id"] = | 1281 requested_parameters_["extension_id"] = |
1311 FetchExtensionIdFromOrigin(GetOrigin()); | 1282 FetchExtensionIdFromOrigin(GetOrigin()); |
1312 std::string passport(requested_parameters_["passport"]); | 1283 std::string passport(requested_parameters_["passport"]); |
1313 requested_parameters_.erase("passport"); | 1284 requested_parameters_.erase("passport"); |
1314 if (!browser::InternalAuthVerification::VerifyPassport( | 1285 if (!browser::InternalAuthVerification::VerifyPassport( |
1315 passport, "web_socket_proxy", requested_parameters_)) { | 1286 passport, "web_socket_proxy", requested_parameters_)) { |
1316 return STATUS_ABORT; | 1287 return STATUS_ABORT; |
1317 } | 1288 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 | 1356 |
1386 uint8* buf = EVBUFFER_DATA(evb); | 1357 uint8* buf = EVBUFFER_DATA(evb); |
1387 size_t buf_size = EVBUFFER_LENGTH(evb); | 1358 size_t buf_size = EVBUFFER_LENGTH(evb); |
1388 if (buf_size < frame_bytes_remaining_) | 1359 if (buf_size < frame_bytes_remaining_) |
1389 return STATUS_INCOMPLETE; | 1360 return STATUS_INCOMPLETE; |
1390 for (size_t i = 0; i < buf_size; ++i) { | 1361 for (size_t i = 0; i < buf_size; ++i) { |
1391 buf[i] ^= frame_mask_[frame_mask_index_]; | 1362 buf[i] ^= frame_mask_[frame_mask_index_]; |
1392 frame_mask_index_ = (frame_mask_index_ + 1) % 4; | 1363 frame_mask_index_ = (frame_mask_index_ + 1) % 4; |
1393 } | 1364 } |
1394 std::string passport; | 1365 std::string passport; |
1395 if (!FetchPassportNamePort(buf, buf + frame_bytes_remaining_, | 1366 if (!WebSocketProxyHelper::FetchPassportAddrNamePort( |
1396 &passport, &destname_, &destport_)) { | 1367 buf, buf + frame_bytes_remaining_, |
| 1368 &passport, &destaddr_, &destname_, &destport_)) { |
1397 return STATUS_ABORT; | 1369 return STATUS_ABORT; |
1398 } | 1370 } |
1399 std::map<std::string, std::string> map; | 1371 std::map<std::string, std::string> map; |
1400 map["hostname"] = destname_; | 1372 map["hostname"] = destname_; |
1401 map["port"] = base::IntToString(destport_); | 1373 map["port"] = base::IntToString(destport_); |
1402 map["extension_id"] = FetchExtensionIdFromOrigin(GetOrigin()); | 1374 map["extension_id"] = FetchExtensionIdFromOrigin(GetOrigin()); |
| 1375 if (!destaddr_.empty()) |
| 1376 map["addr"] = destaddr_; |
1403 if (!browser::InternalAuthVerification::VerifyPassport( | 1377 if (!browser::InternalAuthVerification::VerifyPassport( |
1404 passport, "web_socket_proxy", map)) { | 1378 passport, "web_socket_proxy", map)) { |
1405 return STATUS_ABORT; | 1379 return STATUS_ABORT; |
1406 } | 1380 } |
1407 | 1381 |
1408 evbuffer_drain(evb, frame_bytes_remaining_); | 1382 evbuffer_drain(evb, frame_bytes_remaining_); |
1409 frame_bytes_remaining_ = 0; | 1383 frame_bytes_remaining_ = 0; |
1410 return STATUS_OK; | 1384 return STATUS_OK; |
1411 } | 1385 } |
1412 | 1386 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 case PHASE_WAIT_DESTFRAME: { | 1575 case PHASE_WAIT_DESTFRAME: { |
1602 switch (cs->ConsumeDestframe(EVBUFFER_INPUT(bev))) { | 1576 switch (cs->ConsumeDestframe(EVBUFFER_INPUT(bev))) { |
1603 case STATUS_OK: { | 1577 case STATUS_OK: { |
1604 { | 1578 { |
1605 // Unfortunately libevent as of 1.4 does not look into /etc/hosts. | 1579 // Unfortunately libevent as of 1.4 does not look into /etc/hosts. |
1606 // There seems to be no easy API to perform only "local" part of | 1580 // There seems to be no easy API to perform only "local" part of |
1607 // getaddrinfo resolution. Hence this hack for "localhost". | 1581 // getaddrinfo resolution. Hence this hack for "localhost". |
1608 if (cs->destname_ == "localhost") | 1582 if (cs->destname_ == "localhost") |
1609 cs->destname_ = "127.0.0.1"; | 1583 cs->destname_ = "127.0.0.1"; |
1610 } | 1584 } |
| 1585 if (cs->destaddr_.empty()) |
| 1586 cs->destaddr_ = cs->destname_; |
1611 { | 1587 { |
1612 struct sockaddr_in sa; | 1588 struct sockaddr_in sa; |
1613 memset(&sa, 0, sizeof(sa)); | 1589 memset(&sa, 0, sizeof(sa)); |
1614 sa.sin_port = htons(cs->destport_); | 1590 sa.sin_port = htons(cs->destport_); |
1615 if (inet_pton(sa.sin_family = AF_INET, | 1591 if (inet_pton(sa.sin_family = AF_INET, |
1616 cs->destname_.c_str(), | 1592 cs->destaddr_.c_str(), |
1617 &sa.sin_addr) == 1) { | 1593 &sa.sin_addr) == 1) { |
1618 // valid IPv4 address supplied. | 1594 // valid IPv4 address supplied. |
1619 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { | 1595 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { |
1620 cs->phase_ = PHASE_WAIT_DESTCONNECT; | 1596 cs->phase_ = PHASE_WAIT_DESTCONNECT; |
1621 return; | 1597 return; |
1622 } | 1598 } |
1623 } | 1599 } |
1624 } | 1600 } |
1625 { | 1601 { |
1626 if (cs->destname_.size() >= 2 && | 1602 if (cs->destaddr_.size() >= 2 && |
1627 cs->destname_[0] == '[' && | 1603 cs->destaddr_[0] == '[' && |
1628 cs->destname_[cs->destname_.size() - 1] == ']') { | 1604 cs->destaddr_[cs->destaddr_.size() - 1] == ']') { |
1629 // Literal IPv6 address in brackets. | 1605 // Literal IPv6 address in brackets. |
1630 cs->destname_ = | 1606 cs->destaddr_ = |
1631 cs->destname_.substr(1, cs->destname_.size() - 2); | 1607 cs->destaddr_.substr(1, cs->destaddr_.size() - 2); |
1632 } | 1608 } |
1633 struct sockaddr_in6 sa; | 1609 struct sockaddr_in6 sa; |
1634 memset(&sa, 0, sizeof(sa)); | 1610 memset(&sa, 0, sizeof(sa)); |
1635 sa.sin6_port = htons(cs->destport_); | 1611 sa.sin6_port = htons(cs->destport_); |
1636 if (inet_pton(sa.sin6_family = AF_INET6, | 1612 if (inet_pton(sa.sin6_family = AF_INET6, |
1637 cs->destname_.c_str(), | 1613 cs->destaddr_.c_str(), |
1638 &sa.sin6_addr) == 1) { | 1614 &sa.sin6_addr) == 1) { |
1639 // valid IPv6 address supplied. | 1615 // valid IPv6 address supplied. |
1640 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { | 1616 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { |
1641 cs->phase_ = PHASE_WAIT_DESTCONNECT; | 1617 cs->phase_ = PHASE_WAIT_DESTCONNECT; |
1642 return; | 1618 return; |
1643 } | 1619 } |
1644 } | 1620 } |
1645 } | 1621 } |
1646 // Asynchronous DNS resolution. | 1622 // Asynchronous DNS resolution. |
1647 if (evdns_count_nameservers() < 1) { | 1623 if (evdns_count_nameservers() < 1) { |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1937 | 1913 |
1938 void WebSocketProxy::Shutdown() { | 1914 void WebSocketProxy::Shutdown() { |
1939 static_cast<Serv*>(impl_)->Shutdown(); | 1915 static_cast<Serv*>(impl_)->Shutdown(); |
1940 } | 1916 } |
1941 | 1917 |
1942 void WebSocketProxy::OnNetworkChange() { | 1918 void WebSocketProxy::OnNetworkChange() { |
1943 static_cast<Serv*>(impl_)->OnNetworkChange(); | 1919 static_cast<Serv*>(impl_)->OnNetworkChange(); |
1944 } | 1920 } |
1945 | 1921 |
1946 } // namespace chromeos | 1922 } // namespace chromeos |
OLD | NEW |