Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: chrome/browser/chromeos/web_socket_proxy.cc

Issue 8586027: Move DNS resolution from websocket-to-TCP proxy to ExtensionFunction (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merged Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
11 #include <algorithm> 11 #include <algorithm>
12 #include <limits> 12 #include <limits>
13 #include <list> 13 #include <list>
14 #include <map> 14 #include <map>
15 #include <vector> 15 #include <vector>
16 16
17 #include <arpa/inet.h> 17 #include <arpa/inet.h>
18 #include <errno.h> 18 #include <errno.h>
19 #include <fcntl.h> 19 #include <fcntl.h>
20 #include <netinet/in.h> 20 #include <netinet/in.h>
21 #include <signal.h> 21 #include <signal.h>
22 #include <sys/socket.h> 22 #include <sys/socket.h>
23 #include <sys/types.h> 23 #include <sys/types.h>
24 #include <sys/wait.h> 24 #include <sys/wait.h>
25 25
26 #include "base/base64.h" 26 #include "base/base64.h"
27 #include "base/basictypes.h" 27 #include "base/basictypes.h"
28 #include "base/bind.h" 28 #include "base/bind.h"
29 #include "base/logging.h" 29 #include "base/logging.h"
30 #include "base/string_split.h"
30 #include "base/memory/ref_counted.h" 31 #include "base/memory/ref_counted.h"
31 #include "base/memory/scoped_ptr.h" 32 #include "base/memory/scoped_ptr.h"
32 #include "base/sha1.h" 33 #include "base/sha1.h"
33 #include "base/stl_util.h" 34 #include "base/stl_util.h"
34 #include "base/string_number_conversions.h" 35 #include "base/string_number_conversions.h"
35 #include "base/string_util.h" 36 #include "base/string_util.h"
36 #include "chrome/browser/internal_auth.h" 37 #include "chrome/browser/internal_auth.h"
37 #include "chrome/common/chrome_notification_types.h" 38 #include "chrome/common/chrome_notification_types.h"
38 #include "chrome/common/url_constants.h" 39 #include "chrome/common/url_constants.h"
39 #include "content/public/browser/browser_thread.h" 40 #include "content/public/browser/browser_thread.h"
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 std::string FetchAsciiSnippet(uint8* begin, uint8* end, AsciiFilter filter) { 141 std::string FetchAsciiSnippet(uint8* begin, uint8* end, AsciiFilter filter) {
141 std::string rv; 142 std::string rv;
142 for (; begin < end; ++begin) { 143 for (; begin < end; ++begin) {
143 if (!isascii(*begin)) 144 if (!isascii(*begin))
144 return rv; 145 return rv;
145 rv += filter(*begin); 146 rv += filter(*begin);
146 } 147 }
147 return rv; 148 return rv;
148 } 149 }
149 150
150 // Parses "passport:hostname:port:" string. Returns true on success. 151 // Parses "passport:addr:hostname:port:" string. Returns true on success.
151 bool FetchPassportNamePort( 152 bool FetchPassportAddrNamePort(
152 uint8* begin, uint8* end, 153 uint8* begin, uint8* end,
153 std::string* passport, std::string* name, int* port) { 154 std::string* passport, std::string* addr,
155 std::string* hostname, int* port) {
156
154 std::string input(begin, end); 157 std::string input(begin, end);
155 if (input[input.size() - 1] != ':')
156 return false;
157 input.resize(input.size() - 1);
158 158
159 size_t pos = input.find_last_of(':'); 159 std::vector<std::string> parts;
160 if (pos == std::string::npos) 160 base::SplitString(input, ':', &parts);
161 return false; 161
162 std::string port_str(input, pos + 1); 162 if (parts.size() != 5 || !parts.back().empty()) {
163 if (port_str.empty()) 163 LOG(ERROR) << "Wrong format, input" << input;
164 return false;
165 const char kAsciiDigits[] = "0123456789";
166 COMPILE_ASSERT(sizeof(kAsciiDigits) == 10 + 1, mess_with_digits);
167 if (port_str.find_first_not_of(kAsciiDigits) != std::string::npos)
168 return false;
169 if (!base::StringToInt(port_str, port) ||
170 *port < 0 ||
171 *port >= (1 << 16)) {
172 return false; 164 return false;
173 } 165 }
174 input.resize(pos);
175 166
176 pos = input.find_first_of(':'); 167 // Get passport
177 if (pos == std::string::npos) 168 *passport = parts[0];
169 // Get IP address.
170 *addr = parts[1];
171 // Get hostname.
172 *hostname = parts[2];
173 // Get port.
174 if (!base::StringToInt(parts[3], port) || *port < 0 || *port >= (1<<16)) {
175 LOG(ERROR) << "Not a port: " << port << ", input=" << input;
178 return false; 176 return false;
179 passport->assign(input, 0, pos); 177 }
180 name->assign(input, pos + 1, std::string::npos); 178
181 return !name->empty(); 179 if (passport->empty() || hostname->empty()) {
180 LOG(ERROR) << "Password or hostname is empty, input=" << input;
181 return false;
182 }
183 return true;
182 } 184 }
183 185
184 std::string FetchExtensionIdFromOrigin(const std::string &origin) { 186 std::string FetchExtensionIdFromOrigin(const std::string &origin) {
185 GURL url(origin); 187 GURL url(origin);
186 if (url.SchemeIs(chrome::kExtensionScheme)) 188 if (url.SchemeIs(chrome::kExtensionScheme))
187 return url.host(); 189 return url.host();
188 else 190 else
189 return std::string(); 191 return std::string();
190 } 192 }
191 193
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 std::map<std::string, std::string> header_fields_; 445 std::map<std::string, std::string> header_fields_;
444 446
445 // Parameters requested via query component of GET resource. 447 // Parameters requested via query component of GET resource.
446 std::map<std::string, std::string> requested_parameters_; 448 std::map<std::string, std::string> requested_parameters_;
447 449
448 // Hostname and port of destination socket. 450 // Hostname and port of destination socket.
449 // Websocket client supplies them in first data frame (destframe). 451 // Websocket client supplies them in first data frame (destframe).
450 std::string destname_; 452 std::string destname_;
451 int destport_; 453 int destport_;
452 454
455 // Preresolved |destname_| (empty if not pre-resolved).
456 std::string destaddr_;
457
453 // Whether TLS over TCP requested. 458 // Whether TLS over TCP requested.
454 bool do_tls_; 459 bool do_tls_;
455 460
456 // We try to DNS resolve hostname in both IPv4 and IPv6 domains. 461 // We try to DNS resolve hostname in both IPv4 and IPv6 domains.
457 // Track resolution failures here. 462 // Track resolution failures here.
458 bool destresolution_ipv4_failed_; 463 bool destresolution_ipv4_failed_;
459 bool destresolution_ipv6_failed_; 464 bool destresolution_ipv6_failed_;
460 465
461 // Used to schedule a timeout for initial phase of connection. 466 // Used to schedule a timeout for initial phase of connection.
462 scoped_ptr<struct event> destconnect_timeout_event_; 467 scoped_ptr<struct event> destconnect_timeout_event_;
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 return STATUS_ABORT; 1300 return STATUS_ABORT;
1296 1301
1297 if (!requested_parameters_.empty()) { 1302 if (!requested_parameters_.empty()) {
1298 destname_ = requested_parameters_["hostname"]; 1303 destname_ = requested_parameters_["hostname"];
1299 int port; 1304 int port;
1300 if (!base::StringToInt(requested_parameters_["port"], &port) || 1305 if (!base::StringToInt(requested_parameters_["port"], &port) ||
1301 port < 0 || port >= 1 << 16) { 1306 port < 0 || port >= 1 << 16) {
1302 return STATUS_ABORT; 1307 return STATUS_ABORT;
1303 } 1308 }
1304 destport_ = port; 1309 destport_ = port;
1310 destaddr_ = requested_parameters_["addr"];
1305 do_tls_ = (requested_parameters_["tls"] == "true"); 1311 do_tls_ = (requested_parameters_["tls"] == "true");
1306 1312
1307 requested_parameters_["extension_id"] = 1313 requested_parameters_["extension_id"] =
1308 FetchExtensionIdFromOrigin(GetOrigin()); 1314 FetchExtensionIdFromOrigin(GetOrigin());
1309 std::string passport(requested_parameters_["passport"]); 1315 std::string passport(requested_parameters_["passport"]);
1310 requested_parameters_.erase("passport"); 1316 requested_parameters_.erase("passport");
1311 if (!browser::InternalAuthVerification::VerifyPassport( 1317 if (!browser::InternalAuthVerification::VerifyPassport(
1312 passport, "web_socket_proxy", requested_parameters_)) { 1318 passport, "web_socket_proxy", requested_parameters_)) {
1313 return STATUS_ABORT; 1319 return STATUS_ABORT;
1314 } 1320 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 1388
1383 uint8* buf = EVBUFFER_DATA(evb); 1389 uint8* buf = EVBUFFER_DATA(evb);
1384 size_t buf_size = EVBUFFER_LENGTH(evb); 1390 size_t buf_size = EVBUFFER_LENGTH(evb);
1385 if (buf_size < frame_bytes_remaining_) 1391 if (buf_size < frame_bytes_remaining_)
1386 return STATUS_INCOMPLETE; 1392 return STATUS_INCOMPLETE;
1387 for (size_t i = 0; i < buf_size; ++i) { 1393 for (size_t i = 0; i < buf_size; ++i) {
1388 buf[i] ^= frame_mask_[frame_mask_index_]; 1394 buf[i] ^= frame_mask_[frame_mask_index_];
1389 frame_mask_index_ = (frame_mask_index_ + 1) % 4; 1395 frame_mask_index_ = (frame_mask_index_ + 1) % 4;
1390 } 1396 }
1391 std::string passport; 1397 std::string passport;
1392 if (!FetchPassportNamePort(buf, buf + frame_bytes_remaining_, 1398 if (!FetchPassportAddrNamePort(buf, buf + frame_bytes_remaining_,
1393 &passport, &destname_, &destport_)) { 1399 &passport, &destaddr_, &destname_, &destport_)) {
1394 return STATUS_ABORT; 1400 return STATUS_ABORT;
1395 } 1401 }
1396 std::map<std::string, std::string> map; 1402 std::map<std::string, std::string> map;
1397 map["hostname"] = destname_; 1403 map["hostname"] = destname_;
1398 map["port"] = base::IntToString(destport_); 1404 map["port"] = base::IntToString(destport_);
1399 map["extension_id"] = FetchExtensionIdFromOrigin(GetOrigin()); 1405 map["extension_id"] = FetchExtensionIdFromOrigin(GetOrigin());
1406 if (!destaddr_.empty())
1407 map["addr"] = destaddr_;
1400 if (!browser::InternalAuthVerification::VerifyPassport( 1408 if (!browser::InternalAuthVerification::VerifyPassport(
1401 passport, "web_socket_proxy", map)) { 1409 passport, "web_socket_proxy", map)) {
1402 return STATUS_ABORT; 1410 return STATUS_ABORT;
1403 } 1411 }
1404 1412
1405 evbuffer_drain(evb, frame_bytes_remaining_); 1413 evbuffer_drain(evb, frame_bytes_remaining_);
1406 frame_bytes_remaining_ = 0; 1414 frame_bytes_remaining_ = 0;
1407 return STATUS_OK; 1415 return STATUS_OK;
1408 } 1416 }
1409 1417
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 case PHASE_WAIT_DESTFRAME: { 1606 case PHASE_WAIT_DESTFRAME: {
1599 switch (cs->ConsumeDestframe(EVBUFFER_INPUT(bev))) { 1607 switch (cs->ConsumeDestframe(EVBUFFER_INPUT(bev))) {
1600 case STATUS_OK: { 1608 case STATUS_OK: {
1601 { 1609 {
1602 // Unfortunately libevent as of 1.4 does not look into /etc/hosts. 1610 // Unfortunately libevent as of 1.4 does not look into /etc/hosts.
1603 // There seems to be no easy API to perform only "local" part of 1611 // There seems to be no easy API to perform only "local" part of
1604 // getaddrinfo resolution. Hence this hack for "localhost". 1612 // getaddrinfo resolution. Hence this hack for "localhost".
1605 if (cs->destname_ == "localhost") 1613 if (cs->destname_ == "localhost")
1606 cs->destname_ = "127.0.0.1"; 1614 cs->destname_ = "127.0.0.1";
1607 } 1615 }
1616 if (cs->destaddr_.empty())
1617 cs->destaddr_ = cs->destname_;
1608 { 1618 {
1609 struct sockaddr_in sa; 1619 struct sockaddr_in sa;
1610 memset(&sa, 0, sizeof(sa)); 1620 memset(&sa, 0, sizeof(sa));
1611 sa.sin_port = htons(cs->destport_); 1621 sa.sin_port = htons(cs->destport_);
1612 if (inet_pton(sa.sin_family = AF_INET, 1622 if (inet_pton(sa.sin_family = AF_INET,
1613 cs->destname_.c_str(), 1623 cs->destaddr_.c_str(),
1614 &sa.sin_addr) == 1) { 1624 &sa.sin_addr) == 1) {
1615 // valid IPv4 address supplied. 1625 // valid IPv4 address supplied.
1616 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { 1626 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) {
1617 cs->phase_ = PHASE_WAIT_DESTCONNECT; 1627 cs->phase_ = PHASE_WAIT_DESTCONNECT;
1618 return; 1628 return;
1619 } 1629 }
1620 } 1630 }
1621 } 1631 }
1622 { 1632 {
1623 if (cs->destname_.size() >= 2 && 1633 if (cs->destaddr_.size() >= 2 &&
1624 cs->destname_[0] == '[' && 1634 cs->destaddr_[0] == '[' &&
1625 cs->destname_[cs->destname_.size() - 1] == ']') { 1635 cs->destaddr_[cs->destaddr_.size() - 1] == ']') {
1626 // Literal IPv6 address in brackets. 1636 // Literal IPv6 address in brackets.
1627 cs->destname_ = 1637 cs->destaddr_ =
1628 cs->destname_.substr(1, cs->destname_.size() - 2); 1638 cs->destaddr_.substr(1, cs->destaddr_.size() - 2);
1629 } 1639 }
1630 struct sockaddr_in6 sa; 1640 struct sockaddr_in6 sa;
1631 memset(&sa, 0, sizeof(sa)); 1641 memset(&sa, 0, sizeof(sa));
1632 sa.sin6_port = htons(cs->destport_); 1642 sa.sin6_port = htons(cs->destport_);
1633 if (inet_pton(sa.sin6_family = AF_INET6, 1643 if (inet_pton(sa.sin6_family = AF_INET6,
1634 cs->destname_.c_str(), 1644 cs->destaddr_.c_str(),
1635 &sa.sin6_addr) == 1) { 1645 &sa.sin6_addr) == 1) {
1636 // valid IPv6 address supplied. 1646 // valid IPv6 address supplied.
1637 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) { 1647 if (cs->TryConnectDest((struct sockaddr*)&sa, sizeof(sa))) {
1638 cs->phase_ = PHASE_WAIT_DESTCONNECT; 1648 cs->phase_ = PHASE_WAIT_DESTCONNECT;
1639 return; 1649 return;
1640 } 1650 }
1641 } 1651 }
1642 } 1652 }
1643 // Asynchronous DNS resolution. 1653 // Asynchronous DNS resolution.
1644 if (evdns_count_nameservers() < 1) { 1654 if (evdns_count_nameservers() < 1) {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 1939
1930 void WebSocketProxy::Shutdown() { 1940 void WebSocketProxy::Shutdown() {
1931 static_cast<Serv*>(impl_)->Shutdown(); 1941 static_cast<Serv*>(impl_)->Shutdown();
1932 } 1942 }
1933 1943
1934 void WebSocketProxy::OnNetworkChange() { 1944 void WebSocketProxy::OnNetworkChange() {
1935 static_cast<Serv*>(impl_)->OnNetworkChange(); 1945 static_cast<Serv*>(impl_)->OnNetworkChange();
1936 } 1946 }
1937 1947
1938 } // namespace chromeos 1948 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698