OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/extensions/api/cast_channel/cast_socket.h" | 5 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" |
6 | 6 |
7 #include <cert.h> | |
8 #include <cryptohi.h> | |
9 #include <pk11pub.h> | |
10 #include <seccomon.h> | |
7 #include <string.h> | 11 #include <string.h> |
8 | 12 |
9 #include "base/bind.h" | 13 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 14 #include "base/callback_helpers.h" |
11 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
12 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
13 #include "base/sys_byteorder.h" | 17 #include "base/sys_byteorder.h" |
14 #include "chrome/browser/extensions/api/cast_channel/cast_channel.pb.h" | 18 #include "chrome/browser/extensions/api/cast_channel/cast_channel.pb.h" |
15 #include "chrome/browser/extensions/api/cast_channel/cast_message_util.h" | 19 #include "chrome/browser/extensions/api/cast_channel/cast_message_util.h" |
20 #include "crypto/scoped_nss_types.h" | |
Ryan Sleevi
2013/10/22 20:23:22
DESIGN: Strictly speaking, while I realize extensi
Munjal (Google)
2013/10/22 23:42:43
Trying to understand this:
- You are saying that I
Ryan Sleevi
2013/10/23 19:14:04
That's because the NetworkingPrivate code is/was o
Munjal (Google)
2013/10/23 20:08:56
Done.
| |
16 #include "net/base/address_list.h" | 21 #include "net/base/address_list.h" |
17 #include "net/base/host_port_pair.h" | 22 #include "net/base/host_port_pair.h" |
18 #include "net/base/net_errors.h" | 23 #include "net/base/net_errors.h" |
19 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" |
20 #include "net/cert/cert_verifier.h" | 25 #include "net/cert/cert_verifier.h" |
21 #include "net/cert/x509_certificate.h" | 26 #include "net/cert/x509_certificate.h" |
22 #include "net/http/transport_security_state.h" | 27 #include "net/http/transport_security_state.h" |
23 #include "net/socket/client_socket_factory.h" | 28 #include "net/socket/client_socket_factory.h" |
24 #include "net/socket/client_socket_handle.h" | 29 #include "net/socket/client_socket_handle.h" |
25 #include "net/socket/ssl_client_socket.h" | 30 #include "net/socket/ssl_client_socket.h" |
(...skipping 11 matching lines...) Expand all Loading... | |
37 // Size of the message header, in bytes. Don't use sizeof(MessageHeader) | 42 // Size of the message header, in bytes. Don't use sizeof(MessageHeader) |
38 // because of alignment; instead, sum the sizeof() for the fields. | 43 // because of alignment; instead, sum the sizeof() for the fields. |
39 const uint32 kMessageHeaderSize = sizeof(uint32); | 44 const uint32 kMessageHeaderSize = sizeof(uint32); |
40 | 45 |
41 // The default keepalive delay. On Linux, keepalives probes will be sent after | 46 // The default keepalive delay. On Linux, keepalives probes will be sent after |
42 // the socket is idle for this length of time, and the socket will be closed | 47 // the socket is idle for this length of time, and the socket will be closed |
43 // after 9 failed probes. So the total idle time before close is 10 * | 48 // after 9 failed probes. So the total idle time before close is 10 * |
44 // kTcpKeepAliveDelaySecs. | 49 // kTcpKeepAliveDelaySecs. |
45 const int kTcpKeepAliveDelaySecs = 10; | 50 const int kTcpKeepAliveDelaySecs = 10; |
46 | 51 |
52 // Public key of the certificate with which the peer cert should be signed. | |
53 static const unsigned char kCAPublicKeyDER[] = { | |
54 0x30, 0x82, 0x03, 0x87, 0x30, 0x82, 0x02, 0x6f, 0xa0, 0x03, 0x02, 0x01, | |
55 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, | |
56 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7c, 0x31, 0x0b, 0x30, | |
57 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, | |
58 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, | |
59 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14, 0x06, | |
60 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, | |
61 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11, 0x06, | |
62 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, | |
63 0x20, 0x49, 0x6e, 0x63, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, | |
64 0x0b, 0x0c, 0x09, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x56, | |
65 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x45, | |
66 0x75, 0x72, 0x65, 0x6b, 0x61, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, | |
67 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x32, 0x31, 0x39, 0x30, | |
68 0x30, 0x34, 0x37, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x31, 0x32, | |
69 0x31, 0x34, 0x30, 0x30, 0x34, 0x37, 0x31, 0x32, 0x5a, 0x30, 0x7d, 0x31, | |
70 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, | |
71 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, | |
72 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, | |
73 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, | |
74 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, | |
75 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67, | |
76 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, | |
77 0x55, 0x04, 0x0b, 0x0c, 0x09, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, | |
78 0x54, 0x56, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, | |
79 0x0f, 0x45, 0x75, 0x72, 0x65, 0x6b, 0x61, 0x20, 0x47, 0x65, 0x6e, 0x31, | |
80 0x20, 0x49, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, | |
81 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, | |
82 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, | |
83 0x00, 0xbc, 0x22, 0x80, 0xbd, 0x80, 0xf6, 0x3a, 0x21, 0x00, 0x3b, 0xae, | |
84 0x76, 0x5e, 0x35, 0x7f, 0x3d, 0xc3, 0x64, 0x5c, 0x55, 0x94, 0x86, 0x34, | |
85 0x2f, 0x05, 0x87, 0x28, 0xcd, 0xf7, 0x69, 0x8c, 0x17, 0xb3, 0x50, 0xa7, | |
86 0xb8, 0x82, 0xfa, 0xdf, 0xc7, 0x43, 0x2d, 0xd6, 0x7e, 0xab, 0xa0, 0x6f, | |
87 0xb7, 0x13, 0x72, 0x80, 0xa4, 0x47, 0x15, 0xc1, 0x20, 0x99, 0x50, 0xcd, | |
88 0xec, 0x14, 0x62, 0x09, 0x5b, 0xa4, 0x98, 0xcd, 0xd2, 0x41, 0xb6, 0x36, | |
89 0x4e, 0xff, 0xe8, 0x2e, 0x32, 0x30, 0x4a, 0x81, 0xa8, 0x42, 0xa3, 0x6c, | |
90 0x9b, 0x33, 0x6e, 0xca, 0xb2, 0xf5, 0x53, 0x66, 0xe0, 0x27, 0x53, 0x86, | |
91 0x1a, 0x85, 0x1e, 0xa7, 0x39, 0x3f, 0x4a, 0x77, 0x8e, 0xfb, 0x54, 0x66, | |
92 0x66, 0xfb, 0x58, 0x54, 0xc0, 0x5e, 0x39, 0xc7, 0xf5, 0x50, 0x06, 0x0b, | |
93 0xe0, 0x8a, 0xd4, 0xce, 0xe1, 0x6a, 0x55, 0x1f, 0x8b, 0x17, 0x00, 0xe6, | |
94 0x69, 0xa3, 0x27, 0xe6, 0x08, 0x25, 0x69, 0x3c, 0x12, 0x9d, 0x8d, 0x05, | |
95 0x2c, 0xd6, 0x2e, 0xa2, 0x31, 0xde, 0xb4, 0x52, 0x50, 0xd6, 0x20, 0x49, | |
96 0xde, 0x71, 0xa0, 0xf9, 0xad, 0x20, 0x40, 0x12, 0xf1, 0xdd, 0x25, 0xeb, | |
97 0xd5, 0xe6, 0xb8, 0x36, 0xf4, 0xd6, 0x8f, 0x7f, 0xca, 0x43, 0xdc, 0xd7, | |
98 0x10, 0x5b, 0xe6, 0x3f, 0x51, 0x8a, 0x85, 0xb3, 0xf3, 0xff, 0xf6, 0x03, | |
99 0x2d, 0xcb, 0x23, 0x4f, 0x9c, 0xad, 0x18, 0xe7, 0x93, 0x05, 0x8c, 0xac, | |
100 0x52, 0x9a, 0xf7, 0x4c, 0xe9, 0x99, 0x7a, 0xbe, 0x6e, 0x7e, 0x4d, 0x0a, | |
101 0xe3, 0xc6, 0x1c, 0xa9, 0x93, 0xfa, 0x3a, 0xa5, 0x91, 0x5d, 0x1c, 0xbd, | |
102 0x66, 0xeb, 0xcc, 0x60, 0xdc, 0x86, 0x74, 0xca, 0xcf, 0xf8, 0x92, 0x1c, | |
103 0x98, 0x7d, 0x57, 0xfa, 0x61, 0x47, 0x9e, 0xab, 0x80, 0xb7, 0xe4, 0x48, | |
104 0x80, 0x2a, 0x92, 0xc5, 0x1b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, | |
105 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, | |
106 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, | |
107 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, | |
108 0x01, 0x01, 0x00, 0x8b, 0xd4, 0xa1, 0xb1, 0xcf, 0x5d, 0xcd, 0x7b, 0x6c, | |
109 0x48, 0x4a, 0x41, 0x1f, 0x53, 0x2f, 0x18, 0x2d, 0x32, 0x45, 0xff, 0x9e, | |
110 0xab, 0xd3, 0x73, 0x3e, 0x1f, 0x22, 0xd7, 0xea, 0xfa, 0x01, 0xe6, 0x73, | |
111 0x03, 0x0f, 0x2b, 0xc6, 0x25, 0xbb, 0xa5, 0xee, 0xc5, 0xf5, 0x45, 0xcb, | |
112 0x24, 0x12, 0x2a, 0xad, 0xc2, 0x5d, 0x05, 0xf4, 0x7a, 0xf5, 0xc2, 0x9b, | |
113 0x10, 0x16, 0x5a, 0xd1, 0x0a, 0x73, 0xc5, 0x16, 0x39, 0xa0, 0x10, 0xca, | |
114 0xd1, 0x68, 0x85, 0x9e, 0xfb, 0x9e, 0x26, 0x83, 0x8e, 0x58, 0xf3, 0x77, | |
115 0xa0, 0x4e, 0xe5, 0xdb, 0x97, 0xbe, 0x2d, 0x00, 0x5f, 0xf5, 0x94, 0xdb, | |
116 0xb1, 0x9d, 0x65, 0x6b, 0xfd, 0xf0, 0xd1, 0x04, 0x51, 0xdf, 0xcc, 0x92, | |
117 0xa6, 0x99, 0x2d, 0x71, 0xf5, 0x4d, 0xd5, 0x23, 0xfe, 0x33, 0x1c, 0xa9, | |
118 0xb4, 0xab, 0xc5, 0xbf, 0x1a, 0xb8, 0xd1, 0x80, 0xef, 0x89, 0xc9, 0xe2, | |
119 0x1f, 0x9c, 0x4c, 0x48, 0x3b, 0xa2, 0xfa, 0x02, 0x0a, 0xdc, 0x84, 0x01, | |
120 0x8a, 0x87, 0x02, 0xfb, 0x59, 0xee, 0xa7, 0x4c, 0x04, 0x7d, 0x74, 0x99, | |
121 0x87, 0x6a, 0x25, 0x44, 0xad, 0x16, 0xaa, 0xec, 0x4e, 0x35, 0x1b, 0x7c, | |
122 0x7b, 0x84, 0xc9, 0xb1, 0x3f, 0xe1, 0x82, 0x70, 0xe5, 0x0d, 0xe7, 0xd9, | |
123 0x6d, 0xfa, 0x95, 0xb6, 0xc5, 0xe4, 0x1e, 0xe8, 0x11, 0x9b, 0xd8, 0xb2, | |
124 0xf3, 0xa4, 0xfd, 0x13, 0xf3, 0x83, 0x4f, 0xf7, 0x07, 0x14, 0x20, 0xbb, | |
125 0x22, 0xa5, 0xa6, 0x8f, 0xd6, 0xb5, 0xdb, 0xa9, 0x74, 0x78, 0xe2, 0x93, | |
126 0x0d, 0xe5, 0x23, 0x2f, 0x05, 0x17, 0xe0, 0xb2, 0x97, 0x67, 0x34, 0x4d, | |
127 0x0f, 0x9c, 0x76, 0x43, 0x7b, 0xa6, 0x21, 0x4a, 0x56, 0x05, 0xf6, 0x2a, | |
128 0x7c, 0xf2, 0x7f, 0x12, 0x94, 0x82, 0x26, 0x29, 0x07, 0xf0, 0x0b, 0x6c, | |
129 0x6c, 0x79, 0x14, 0xb0, 0x74, 0xd5, 0x6c }; | |
130 | |
47 } // namespace | 131 } // namespace |
48 | 132 |
133 typedef scoped_ptr_malloc< | |
134 CERTCertificate, | |
135 crypto::NSSDestroyer<CERTCertificate, CERT_DestroyCertificate> > | |
136 ScopedCERTCertificate; | |
137 | |
49 namespace extensions { | 138 namespace extensions { |
50 | 139 |
51 static base::LazyInstance< | 140 static base::LazyInstance< |
52 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> > > | 141 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> > > |
53 g_factory = LAZY_INSTANCE_INITIALIZER; | 142 g_factory = LAZY_INSTANCE_INITIALIZER; |
54 | 143 |
55 // static | 144 // static |
56 template <> | 145 template <> |
57 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> >* | 146 ProfileKeyedAPIFactory<ApiResourceManager<api::cast_channel::CastSocket> >* |
58 ApiResourceManager<api::cast_channel::CastSocket>::GetFactoryInstance() { | 147 ApiResourceManager<api::cast_channel::CastSocket>::GetFactoryInstance() { |
59 return &g_factory.Get(); | 148 return &g_factory.Get(); |
60 } | 149 } |
61 | 150 |
62 namespace api { | 151 namespace api { |
63 namespace cast_channel { | 152 namespace cast_channel { |
64 | 153 |
65 const uint32 kMaxMessageSize = 65536; | 154 const uint32 kMaxMessageSize = 65536; |
66 | 155 |
67 CastSocket::CastSocket(const std::string& owner_extension_id, | 156 CastSocket::CastSocket(const std::string& owner_extension_id, |
68 const GURL& url, CastSocket::Delegate* delegate, | 157 const GURL& url, |
158 CastSocket::Delegate* delegate, | |
69 net::NetLog* net_log) : | 159 net::NetLog* net_log) : |
70 ApiResource(owner_extension_id), | 160 ApiResource(owner_extension_id), |
71 channel_id_(0), | 161 channel_id_(0), |
72 url_(url), | 162 url_(url), |
73 delegate_(delegate), | 163 delegate_(delegate), |
74 is_secure_(false), | 164 is_secure_(false), |
75 error_state_(CHANNEL_ERROR_NONE), | 165 error_state_(CHANNEL_ERROR_NONE), |
76 ready_state_(READY_STATE_NONE), | 166 ready_state_(READY_STATE_NONE), |
77 write_callback_pending_(false), | 167 write_callback_pending_(false), |
78 read_callback_pending_(false), | 168 read_callback_pending_(false), |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 | 229 |
140 scoped_ptr<net::ClientSocketHandle> connection(new net::ClientSocketHandle); | 230 scoped_ptr<net::ClientSocketHandle> connection(new net::ClientSocketHandle); |
141 connection->SetSocket(tcp_socket_.PassAs<net::StreamSocket>()); | 231 connection->SetSocket(tcp_socket_.PassAs<net::StreamSocket>()); |
142 net::HostPortPair host_and_port = net::HostPortPair::FromIPEndPoint( | 232 net::HostPortPair host_and_port = net::HostPortPair::FromIPEndPoint( |
143 ip_endpoint_); | 233 ip_endpoint_); |
144 | 234 |
145 return net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket( | 235 return net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket( |
146 connection.Pass(), host_and_port, ssl_config, context); | 236 connection.Pass(), host_and_port, ssl_config, context); |
147 } | 237 } |
148 | 238 |
239 bool CastSocket::ExtractPeerCert(std::string* cert) { | |
240 CHECK(peer_cert_.empty()); | |
241 net::SSLInfo ssl_info; | |
242 if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) | |
243 return false; | |
244 bool result = net::X509Certificate::GetDEREncoded( | |
245 ssl_info.cert->os_cert_handle(), cert); | |
246 if (result) | |
247 DVLOG(1) << "Successfully extracted peer certificate: " << *cert; | |
248 return result; | |
249 } | |
250 | |
251 void CastSocket::SendAuthChallenge() { | |
252 CastMessage challenge_message; | |
253 CreateAuthChallengeMessage(&challenge_message); | |
254 SendMessageInternal(challenge_message, | |
255 base::Bind(&CastSocket::OnChallengeEvent, AsWeakPtr())); | |
Ryan Sleevi
2013/10/22 20:23:22
It's unfortunate that you have to use WeakPtr here
Munjal (Google)
2013/10/22 23:42:43
Right now, all code in this file uses WeakPtr. I w
| |
256 } | |
257 | |
149 void CastSocket::OnConnectComplete(int result) { | 258 void CastSocket::OnConnectComplete(int result) { |
150 int rv = DoConnectLoop(result); | 259 int rv = DoConnectLoop(result); |
151 if (rv != net::ERR_IO_PENDING) | 260 if (rv != net::ERR_IO_PENDING) |
152 DoConnectCallback(rv); | 261 DoConnectCallback(rv); |
153 } | 262 } |
154 | 263 |
264 void CastSocket::OnChallengeEvent(int result) { | |
265 int rv = DoConnectLoop(result); | |
266 if (rv != net::ERR_IO_PENDING) | |
267 DoConnectCallback(rv); | |
268 } | |
269 | |
155 void CastSocket::Connect(const net::CompletionCallback& callback) { | 270 void CastSocket::Connect(const net::CompletionCallback& callback) { |
156 DCHECK(CalledOnValidThread()); | 271 DCHECK(CalledOnValidThread()); |
157 int result = net::ERR_CONNECTION_FAILED; | 272 int result = net::ERR_CONNECTION_FAILED; |
158 DVLOG(1) << "Connect readyState = " << ready_state_; | 273 DVLOG(1) << "Connect readyState = " << ready_state_; |
159 if (ready_state_ != READY_STATE_NONE) { | 274 if (ready_state_ != READY_STATE_NONE) { |
160 callback.Run(result); | 275 callback.Run(result); |
161 return; | 276 return; |
162 } | 277 } |
163 if (!ParseChannelUrl(url_)) { | 278 if (!ParseChannelUrl(url_)) { |
164 CloseWithError(cast_channel::CHANNEL_ERROR_CONNECT_ERROR); | 279 CloseWithError(cast_channel::CHANNEL_ERROR_CONNECT_ERROR); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 case CONN_STATE_TCP_CONNECT_COMPLETE: | 313 case CONN_STATE_TCP_CONNECT_COMPLETE: |
199 rv = DoTcpConnectComplete(rv); | 314 rv = DoTcpConnectComplete(rv); |
200 break; | 315 break; |
201 case CONN_STATE_SSL_CONNECT: | 316 case CONN_STATE_SSL_CONNECT: |
202 DCHECK_EQ(net::OK, rv); | 317 DCHECK_EQ(net::OK, rv); |
203 rv = DoSslConnect(); | 318 rv = DoSslConnect(); |
204 break; | 319 break; |
205 case CONN_STATE_SSL_CONNECT_COMPLETE: | 320 case CONN_STATE_SSL_CONNECT_COMPLETE: |
206 rv = DoSslConnectComplete(rv); | 321 rv = DoSslConnectComplete(rv); |
207 break; | 322 break; |
323 case CONN_STATE_AUTH_CHALLENGE_SEND: | |
324 rv = DoAuthChallengeSend(); | |
325 break; | |
326 case CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE: | |
327 rv = DoAuthChallengeSendComplete(rv); | |
328 break; | |
329 case CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE: | |
330 rv = DoAuthChallengeReplyComplete(rv); | |
331 break; | |
332 | |
208 default: | 333 default: |
209 NOTREACHED() << "BUG in CastSocket state machine code"; | 334 NOTREACHED() << "BUG in CastSocket state machine code"; |
210 break; | 335 break; |
211 } | 336 } |
212 } while (rv != net::ERR_IO_PENDING && next_state_ != CONN_STATE_NONE); | 337 } while (rv != net::ERR_IO_PENDING && next_state_ != CONN_STATE_NONE); |
213 // Get out of the loop either when: | 338 // Get out of the loop either when: |
214 // a. A network operation is pending, OR | 339 // a. A network operation is pending, OR |
215 // b. The Do* method called did not change state | 340 // b. The Do* method called did not change state |
216 | 341 |
217 return rv; | 342 return rv; |
(...skipping 18 matching lines...) Expand all Loading... | |
236 return socket_->Connect( | 361 return socket_->Connect( |
237 base::Bind(&CastSocket::OnConnectComplete, AsWeakPtr())); | 362 base::Bind(&CastSocket::OnConnectComplete, AsWeakPtr())); |
238 } | 363 } |
239 | 364 |
240 int CastSocket::DoSslConnectComplete(int result) { | 365 int CastSocket::DoSslConnectComplete(int result) { |
241 // TODO(mfoltz,munjal): Authenticate the channel if is_secure_ == true. | 366 // TODO(mfoltz,munjal): Authenticate the channel if is_secure_ == true. |
242 if (result == net::ERR_CERT_AUTHORITY_INVALID && | 367 if (result == net::ERR_CERT_AUTHORITY_INVALID && |
243 peer_cert_.empty() && | 368 peer_cert_.empty() && |
244 ExtractPeerCert(&peer_cert_)) { | 369 ExtractPeerCert(&peer_cert_)) { |
245 next_state_ = CONN_STATE_TCP_CONNECT; | 370 next_state_ = CONN_STATE_TCP_CONNECT; |
371 } else if (result == net::OK && is_secure_) { | |
372 next_state_ = CONN_STATE_AUTH_CHALLENGE_SEND; | |
246 } | 373 } |
247 return result; | 374 return result; |
248 } | 375 } |
249 | 376 |
377 int CastSocket::DoAuthChallengeSend() { | |
378 next_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE; | |
379 SendAuthChallenge(); | |
380 return net::ERR_IO_PENDING; | |
381 } | |
382 | |
383 int CastSocket::DoAuthChallengeSendComplete(int result) { | |
384 next_state_ = CONN_STATE_AUTH_CHALLENGE_REPLY_COMPLETE; | |
Ryan Sleevi
2013/10/22 20:23:22
Shouldn't you update this only after the error che
Munjal (Google)
2013/10/22 23:42:43
Done.
| |
385 if (result != net::OK) | |
386 return result; | |
387 | |
388 ReadData(); | |
Ryan Sleevi
2013/10/22 20:23:22
BUG: This may synchronously complete (line 635), w
Munjal (Google)
2013/10/22 23:42:43
Done.
| |
389 return net::ERR_IO_PENDING; | |
390 } | |
391 | |
392 int CastSocket::DoAuthChallengeReplyComplete(int result) { | |
393 if (result != net::OK) | |
394 return result; | |
395 if (VerifyChallengeReply()) | |
396 return net::OK; | |
397 else | |
398 return net::ERR_FAILED; | |
399 } | |
400 | |
401 bool CastSocket::VerifyChallengeReply() { | |
402 CHECK(!peer_cert_.empty()); | |
403 CHECK(challenge_reply_.get()); | |
Ryan Sleevi
2013/10/22 20:23:22
SECURITY BUG: Seems like an attacker could induce
Munjal (Google)
2013/10/22 23:42:43
Done.
| |
404 | |
405 DVLOG(1) << "Challenge reply: " << MessageProtoToString(*challenge_reply_); | |
406 | |
407 if (challenge_reply_->payload_type() != CastMessage_PayloadType_BINARY) { | |
408 LOG(ERROR) << "Wrong payload type in challenge reply"; | |
Ryan Sleevi
2013/10/22 20:23:22
DVLOG?
There's fairly extensive use of LOG() here
Munjal (Google)
2013/10/22 23:42:43
Done.
| |
409 return false; | |
410 } | |
411 if (!challenge_reply_->has_payload_binary()) { | |
412 LOG(ERROR) << "Payload type is binary but payload_binary field not set"; | |
413 return false; | |
414 } | |
415 DeviceAuthMessage auth_message; | |
416 if (!auth_message.ParseFromString(challenge_reply_->payload_binary())) { | |
417 LOG(ERROR) << "Cannot parse binary payload into DeviceAuthMessage"; | |
418 return false; | |
419 } | |
420 DVLOG(1) << "Auth message: " << AuthMessageToString(auth_message); | |
421 if (auth_message.has_error()) { | |
422 LOG(ERROR) << "Auth message has error: " << | |
423 auth_message.error().error_type(); | |
424 return false; | |
425 } | |
426 if (!auth_message.has_response()) { | |
427 LOG(ERROR) << "Auth message has no response field"; | |
428 return false; | |
429 } | |
430 | |
431 const AuthResponse& response = auth_message.response(); | |
432 return VerifyCredentials(response.client_auth_certificate(), | |
433 response.signature(), | |
434 peer_cert_); | |
435 } | |
436 | |
437 bool CastSocket::VerifyCredentials(const std::string& certificate, | |
438 const std::string& signature, | |
439 const std::string& data) { | |
440 // Make a copy of the incoming cert string since we are going to | |
441 // directly use the underlying char array. | |
442 std::string cert_data(certificate); | |
443 SECItem der_cert; | |
444 der_cert.type = siDERCertBuffer; | |
445 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>( | |
446 cert_data.c_str())); | |
447 der_cert.len = cert_data.length(); | |
448 | |
449 // Parse into a certificate structure. | |
450 ScopedCERTCertificate cert(CERT_NewTempCertificate( | |
451 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE)); | |
Ryan Sleevi
2013/10/22 20:23:22
You should make sure that crypto::EnsureNSSInit()
Munjal (Google)
2013/10/22 23:42:43
Done.
| |
452 if (!cert.get()) { | |
453 LOG(ERROR) << "Failed to parse certificate."; | |
454 return false; | |
455 } | |
456 | |
457 // Check that the certificate is signed by trusted CA. | |
458 SECItem trusted_ca_key_der_item; | |
459 trusted_ca_key_der_item.type = siDERCertBuffer; | |
460 trusted_ca_key_der_item.data = const_cast<unsigned char*>(kCAPublicKeyDER); | |
461 trusted_ca_key_der_item.len = sizeof(kCAPublicKeyDER); | |
462 crypto::ScopedSECKEYPublicKey ca_public_key( | |
463 SECKEY_ImportDERPublicKey(&trusted_ca_key_der_item, CKK_RSA)); | |
464 SECStatus verified = CERT_VerifySignedDataWithPublicKey( | |
465 &cert->signatureWrap, ca_public_key.get(), NULL); | |
466 if (verified != SECSuccess) { | |
467 LOG(ERROR)<< "Cert not signed by trusted CA"; | |
468 return false; | |
469 } | |
470 | |
471 // Verify that the |signature| matches |data|. | |
472 crypto::ScopedSECKEYPublicKey public_key(CERT_ExtractPublicKey(cert.get())); | |
473 if (!public_key.get()) { | |
474 LOG(ERROR) << "Unable to extract public key from certificate."; | |
475 return false; | |
476 } | |
477 SECItem signature_item; | |
478 signature_item.type = siBuffer; | |
479 signature_item.data = reinterpret_cast<unsigned char*>( | |
480 const_cast<char*>(signature.c_str())); | |
481 signature_item.len = static_cast<unsigned int>(signature.size()); | |
482 verified = VFY_VerifyDataDirect( | |
483 reinterpret_cast<unsigned char*>(const_cast<char*>(data.c_str())), | |
484 data.size(), | |
485 public_key.get(), | |
486 &signature_item, | |
487 SEC_OID_PKCS1_RSA_ENCRYPTION, | |
488 SEC_OID_SHA1, NULL, NULL); | |
489 | |
490 if (verified != SECSuccess) { | |
491 LOG(ERROR) << "Signed blobs did not match."; | |
492 return false; | |
493 } | |
494 return true; | |
495 } | |
496 | |
250 void CastSocket::DoConnectCallback(int result) { | 497 void CastSocket::DoConnectCallback(int result) { |
251 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; | 498 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; |
252 error_state_ = (result == net::OK) ? | 499 error_state_ = (result == net::OK) ? |
253 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR; | 500 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR; |
254 base::ResetAndReturn(&connect_callback_).Run(result); | 501 base::ResetAndReturn(&connect_callback_).Run(result); |
255 if (result == net::OK) | 502 if (result == net::OK) |
256 ReadData(); | 503 ReadData(); |
257 } | 504 } |
258 | 505 |
259 void CastSocket::Close(const net::CompletionCallback& callback) { | 506 void CastSocket::Close(const net::CompletionCallback& callback) { |
260 DCHECK(CalledOnValidThread()); | 507 DCHECK(CalledOnValidThread()); |
261 DVLOG(1) << "Close ReadyState = " << ready_state_; | 508 DVLOG(1) << "Close ReadyState = " << ready_state_; |
262 tcp_socket_.reset(NULL); | 509 tcp_socket_.reset(NULL); |
263 socket_.reset(NULL); | 510 socket_.reset(NULL); |
264 cert_verifier_.reset(NULL); | 511 cert_verifier_.reset(NULL); |
265 transport_security_state_.reset(NULL); | 512 transport_security_state_.reset(NULL); |
266 ready_state_ = READY_STATE_CLOSED; | 513 ready_state_ = READY_STATE_CLOSED; |
267 callback.Run(net::OK); | 514 callback.Run(net::OK); |
268 } | 515 } |
269 | 516 |
270 void CastSocket::SendMessage(const MessageInfo& message, | 517 void CastSocket::SendMessage(const MessageInfo& message, |
271 const net::CompletionCallback& callback) { | 518 const net::CompletionCallback& callback) { |
272 DCHECK(CalledOnValidThread()); | 519 DCHECK(CalledOnValidThread()); |
273 DVLOG(1) << "Send ReadyState " << ready_state_; | 520 DVLOG(1) << "Send ReadyState " << ready_state_; |
274 int result = net::ERR_FAILED; | 521 int result = net::ERR_FAILED; |
275 if (ready_state_ != READY_STATE_OPEN) { | 522 if (ready_state_ != READY_STATE_OPEN) { |
276 callback.Run(result); | 523 callback.Run(result); |
277 return; | 524 return; |
278 } | 525 } |
279 WriteRequest write_request(callback); | |
280 CastMessage message_proto; | 526 CastMessage message_proto; |
281 if (!MessageInfoToCastMessage(message, &message_proto) || | 527 if (!MessageInfoToCastMessage(message, &message_proto)) { |
282 !write_request.SetContent(message_proto)) { | |
283 CloseWithError(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE); | 528 CloseWithError(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE); |
284 // TODO(mfoltz): Do a better job of signaling cast_channel errors to the | 529 // TODO(mfoltz): Do a better job of signaling cast_channel errors to the |
285 // caller. | 530 // caller. |
286 callback.Run(net::OK); | 531 callback.Run(net::OK); |
287 return; | 532 return; |
288 } | 533 } |
534 SendMessageInternal(message_proto, callback); | |
535 } | |
536 | |
537 void CastSocket::SendMessageInternal(const CastMessage& message_proto, | |
538 const net::CompletionCallback& callback) { | |
539 WriteRequest write_request(callback); | |
540 if (!write_request.SetContent(message_proto)) { | |
541 CloseWithError(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE); | |
542 callback.Run(net::OK); | |
Ryan Sleevi
2013/10/22 20:23:22
BUG: You run a callback but then continue executin
Munjal (Google)
2013/10/22 23:42:43
Done.
| |
543 } | |
289 write_queue_.push(write_request); | 544 write_queue_.push(write_request); |
290 WriteData(); | 545 WriteData(); |
291 } | 546 } |
292 | 547 |
293 void CastSocket::WriteData() { | 548 void CastSocket::WriteData() { |
294 DCHECK(CalledOnValidThread()); | 549 DCHECK(CalledOnValidThread()); |
295 DVLOG(1) << "WriteData q = " << write_queue_.size(); | 550 DVLOG(1) << "WriteData q = " << write_queue_.size(); |
296 if (write_queue_.empty() || write_callback_pending_) | 551 if (write_queue_.empty() || write_callback_pending_) |
297 return; | 552 return; |
298 | 553 |
299 WriteRequest& request = write_queue_.front(); | 554 WriteRequest& request = write_queue_.front(); |
300 if (ready_state_ != READY_STATE_OPEN) { | |
301 request.callback.Run(net::ERR_FAILED); | |
302 return; | |
303 } | |
304 | 555 |
305 DVLOG(1) << "WriteData byte_count = " << request.io_buffer->size() << | 556 DVLOG(1) << "WriteData byte_count = " << request.io_buffer->size() << |
306 " bytes_written " << request.io_buffer->BytesConsumed(); | 557 " bytes_written " << request.io_buffer->BytesConsumed(); |
307 | 558 |
308 write_callback_pending_ = true; | 559 write_callback_pending_ = true; |
309 int result = socket_->Write( | 560 int result = socket_->Write( |
310 request.io_buffer.get(), | 561 request.io_buffer.get(), |
311 request.io_buffer->BytesRemaining(), | 562 request.io_buffer->BytesRemaining(), |
312 base::Bind(&CastSocket::OnWriteData, AsWeakPtr())); | 563 base::Bind(&CastSocket::OnWriteData, AsWeakPtr())); |
313 | 564 |
314 DVLOG(1) << "WriteData result = " << result; | |
315 | |
316 if (result != net::ERR_IO_PENDING) | 565 if (result != net::ERR_IO_PENDING) |
317 OnWriteData(result); | 566 OnWriteData(result); |
318 } | 567 } |
319 | 568 |
320 void CastSocket::OnWriteData(int result) { | 569 void CastSocket::OnWriteData(int result) { |
321 DCHECK(CalledOnValidThread()); | 570 DCHECK(CalledOnValidThread()); |
322 DVLOG(1) << "OnWriteComplete result = " << result; | 571 DVLOG(1) << "OnWriteComplete result = " << result; |
323 DCHECK(write_callback_pending_); | 572 DCHECK(write_callback_pending_); |
324 DCHECK(!write_queue_.empty()); | 573 DCHECK(!write_queue_.empty()); |
325 write_callback_pending_ = false; | 574 write_callback_pending_ = false; |
(...skipping 27 matching lines...) Expand all Loading... | |
353 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); | 602 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); |
354 return; | 603 return; |
355 } | 604 } |
356 | 605 |
357 if (!write_queue_.empty()) | 606 if (!write_queue_.empty()) |
358 WriteData(); | 607 WriteData(); |
359 } | 608 } |
360 | 609 |
361 void CastSocket::ReadData() { | 610 void CastSocket::ReadData() { |
362 DCHECK(CalledOnValidThread()); | 611 DCHECK(CalledOnValidThread()); |
363 if (!socket_.get() || ready_state_ != READY_STATE_OPEN) { | 612 if (!socket_.get()) |
364 return; | 613 return; |
365 } | |
366 DCHECK(!read_callback_pending_); | 614 DCHECK(!read_callback_pending_); |
367 read_callback_pending_ = true; | 615 read_callback_pending_ = true; |
368 // Figure out if we are reading the header or body, and the remaining bytes. | 616 // Figure out if we are reading the header or body, and the remaining bytes. |
369 uint32 num_bytes_to_read = 0; | 617 uint32 num_bytes_to_read = 0; |
370 if (header_read_buffer_->RemainingCapacity() > 0) { | 618 if (header_read_buffer_->RemainingCapacity() > 0) { |
371 current_read_buffer_ = header_read_buffer_; | 619 current_read_buffer_ = header_read_buffer_; |
372 num_bytes_to_read = header_read_buffer_->RemainingCapacity(); | 620 num_bytes_to_read = header_read_buffer_->RemainingCapacity(); |
373 DCHECK_LE(num_bytes_to_read, kMessageHeaderSize); | 621 DCHECK_LE(num_bytes_to_read, kMessageHeaderSize); |
374 } else { | 622 } else { |
375 DCHECK_GT(current_message_size_, 0U); | 623 DCHECK_GT(current_message_size_, 0U); |
(...skipping 10 matching lines...) Expand all Loading... | |
386 DVLOG(1) << "ReadData result = " << result; | 634 DVLOG(1) << "ReadData result = " << result; |
387 if (result > 0) { | 635 if (result > 0) { |
388 OnReadData(result); | 636 OnReadData(result); |
389 } else if (result != net::ERR_IO_PENDING) { | 637 } else if (result != net::ERR_IO_PENDING) { |
390 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); | 638 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); |
391 } | 639 } |
392 } | 640 } |
393 | 641 |
394 void CastSocket::OnReadData(int result) { | 642 void CastSocket::OnReadData(int result) { |
395 DCHECK(CalledOnValidThread()); | 643 DCHECK(CalledOnValidThread()); |
396 DVLOG(1) << "OnReadData result = " << result << | 644 DVLOG(1) << "OnReadData result = " << result |
397 " header offset = " << header_read_buffer_->offset() << | 645 << " header offset = " << header_read_buffer_->offset() |
398 " body offset = " << body_read_buffer_->offset(); | 646 << " body offset = " << body_read_buffer_->offset(); |
399 read_callback_pending_ = false; | 647 read_callback_pending_ = false; |
400 if (result <= 0) { | 648 if (result <= 0) { |
401 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); | 649 CloseWithError(CHANNEL_ERROR_SOCKET_ERROR); |
402 return; | 650 return; |
403 } | 651 } |
404 // We read some data. Move the offset in the current buffer forward. | 652 // We read some data. Move the offset in the current buffer forward. |
405 DCHECK_LE(current_read_buffer_->offset() + result, | 653 DCHECK_LE(current_read_buffer_->offset() + result, |
406 current_read_buffer_->capacity()); | 654 current_read_buffer_->capacity()); |
407 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); | 655 current_read_buffer_->set_offset(current_read_buffer_->offset() + result); |
408 | 656 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
452 bool CastSocket::ParseMessageFromBody() { | 700 bool CastSocket::ParseMessageFromBody() { |
453 DCHECK(CalledOnValidThread()); | 701 DCHECK(CalledOnValidThread()); |
454 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), | 702 DCHECK_EQ(static_cast<uint32>(body_read_buffer_->offset()), |
455 current_message_size_); | 703 current_message_size_); |
456 CastMessage message_proto; | 704 CastMessage message_proto; |
457 if (!message_proto.ParseFromArray( | 705 if (!message_proto.ParseFromArray( |
458 body_read_buffer_->StartOfBuffer(), | 706 body_read_buffer_->StartOfBuffer(), |
459 current_message_size_)) | 707 current_message_size_)) |
460 return false; | 708 return false; |
461 DVLOG(1) << "Parsed message " << MessageProtoToString(message_proto); | 709 DVLOG(1) << "Parsed message " << MessageProtoToString(message_proto); |
462 if (delegate_) { | 710 // If the message is an auth message then we handle it internally. |
711 if (IsAuthMessage(message_proto)) { | |
712 challenge_reply_.reset(new CastMessage(message_proto)); | |
713 OnChallengeEvent(net::OK); | |
714 } else if (delegate_) { | |
463 MessageInfo message; | 715 MessageInfo message; |
464 if (!CastMessageToMessageInfo(message_proto, &message)) | 716 if (!CastMessageToMessageInfo(message_proto, &message)) |
465 return false; | 717 return false; |
466 delegate_->OnMessage(this, message); | 718 delegate_->OnMessage(this, message); |
467 } | 719 } |
468 return true; | 720 return true; |
469 } | 721 } |
470 | 722 |
471 // static | 723 // static |
472 bool CastSocket::Serialize(const CastMessage& message_proto, | 724 bool CastSocket::Serialize(const CastMessage& message_proto, |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
577 io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(message_data), | 829 io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(message_data), |
578 message_data.size()); | 830 message_data.size()); |
579 return true; | 831 return true; |
580 } | 832 } |
581 | 833 |
582 CastSocket::WriteRequest::~WriteRequest() { } | 834 CastSocket::WriteRequest::~WriteRequest() { } |
583 | 835 |
584 } // namespace cast_channel | 836 } // namespace cast_channel |
585 } // namespace api | 837 } // namespace api |
586 } // namespace extensions | 838 } // namespace extensions |
OLD | NEW |