OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 /** | 7 /** |
8 * A high-level class for communicating securely over a TCP socket, using | 8 * A high-level class for communicating securely over a TCP socket, using |
9 * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an | 9 * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an |
10 * [IOSink] interface, making it ideal for using together with | 10 * [IOSink] interface, making it ideal for using together with |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 * socket as its address value. | 67 * socket as its address value. |
68 * | 68 * |
69 * See [connect] for more information on the arguments. | 69 * See [connect] for more information on the arguments. |
70 * | 70 * |
71 */ | 71 */ |
72 static Future<SecureSocket> secure( | 72 static Future<SecureSocket> secure( |
73 Socket socket, | 73 Socket socket, |
74 {host, | 74 {host, |
75 SecurityContext context, | 75 SecurityContext context, |
76 bool onBadCertificate(X509Certificate certificate)}) { | 76 bool onBadCertificate(X509Certificate certificate)}) { |
77 return ((socket as dynamic/*_Socket*/)._detachRaw() as Future) | 77 var completer = new Completer(); |
78 .then/*<RawSecureSocket>*/((detachedRaw) { | 78 (socket as dynamic)._detachRaw() |
| 79 .then((detachedRaw) { |
79 return RawSecureSocket.secure( | 80 return RawSecureSocket.secure( |
80 detachedRaw[0] as RawSocket, | 81 detachedRaw[0], |
81 subscription: detachedRaw[1] as StreamSubscription<RawSocketEvent>, | 82 subscription: detachedRaw[1], |
82 host: host, | 83 host: host, |
83 context: context, | 84 context: context, |
84 onBadCertificate: onBadCertificate); | 85 onBadCertificate: onBadCertificate); |
85 }) | 86 }) |
86 .then/*<SecureSocket>*/((raw) => new SecureSocket._(raw)); | 87 .then((raw) { |
87 } | 88 completer.complete(new SecureSocket._(raw)); |
| 89 }); |
| 90 return completer.future; |
| 91 } |
88 | 92 |
89 /** | 93 /** |
90 * Takes an already connected [socket] and starts server side TLS | 94 * Takes an already connected [socket] and starts server side TLS |
91 * handshake to make the communication secure. When the returned | 95 * handshake to make the communication secure. When the returned |
92 * future completes the [SecureSocket] has completed the TLS | 96 * future completes the [SecureSocket] has completed the TLS |
93 * handshake. Using this function requires that the other end of the | 97 * handshake. Using this function requires that the other end of the |
94 * connection is going to start the TLS handshake. | 98 * connection is going to start the TLS handshake. |
95 * | 99 * |
96 * If the [socket] already has a subscription, this subscription | 100 * If the [socket] already has a subscription, this subscription |
97 * will no longer receive and events. In most cases calling | 101 * will no longer receive and events. In most cases calling |
98 * [:pause:] on this subscription before starting TLS handshake is | 102 * [:pause:] on this subscription before starting TLS handshake is |
99 * the right thing to do. | 103 * the right thing to do. |
100 * | 104 * |
101 * If some of the data of the TLS handshake has already been read | 105 * If some of the data of the TLS handshake has already been read |
102 * from the socket this data can be passed in the [bufferedData] | 106 * from the socket this data can be passed in the [bufferedData] |
103 * parameter. This data will be processed before any other data | 107 * parameter. This data will be processed before any other data |
104 * available on the socket. | 108 * available on the socket. |
105 * | 109 * |
106 * See [SecureServerSocket.bind] for more information on the | 110 * See [SecureServerSocket.bind] for more information on the |
107 * arguments. | 111 * arguments. |
108 * | 112 * |
109 */ | 113 */ |
110 static Future<SecureSocket> secureServer( | 114 static Future<SecureSocket> secureServer( |
111 Socket socket, | 115 Socket socket, |
112 SecurityContext context, | 116 SecurityContext context, |
113 {List<int> bufferedData, | 117 {List<int> bufferedData, |
114 bool requestClientCertificate: false, | 118 bool requestClientCertificate: false, |
115 bool requireClientCertificate: false, | 119 bool requireClientCertificate: false, |
116 List<String> supportedProtocols}) { | 120 List<String> supportedProtocols}) { |
117 return ((socket as dynamic/*_Socket*/)._detachRaw() as Future) | 121 var completer = new Completer(); |
118 .then/*<RawSecureSocket>*/((detachedRaw) { | 122 (socket as dynamic)._detachRaw() |
| 123 .then((detachedRaw) { |
119 return RawSecureSocket.secureServer( | 124 return RawSecureSocket.secureServer( |
120 detachedRaw[0] as RawSocket, | 125 detachedRaw[0], |
121 context, | 126 context, |
122 subscription: detachedRaw[1] as StreamSubscription<RawSocketEvent>, | 127 subscription: detachedRaw[1], |
123 bufferedData: bufferedData, | 128 bufferedData: bufferedData, |
124 requestClientCertificate: requestClientCertificate, | 129 requestClientCertificate: requestClientCertificate, |
125 requireClientCertificate: requireClientCertificate, | 130 requireClientCertificate: requireClientCertificate, |
126 supportedProtocols: supportedProtocols); | 131 supportedProtocols: supportedProtocols); |
127 }) | 132 }) |
128 .then/*<SecureSocket>*/((raw) => new SecureSocket._(raw)); | 133 .then((raw) { |
| 134 completer.complete(new SecureSocket._(raw)); |
| 135 }); |
| 136 return completer.future; |
129 } | 137 } |
130 | 138 |
131 /** | 139 /** |
132 * Get the peer certificate for a connected SecureSocket. If this | 140 * Get the peer certificate for a connected SecureSocket. If this |
133 * SecureSocket is the server end of a secure socket connection, | 141 * SecureSocket is the server end of a secure socket connection, |
134 * [peerCertificate] will return the client certificate, or null, if no | 142 * [peerCertificate] will return the client certificate, or null, if no |
135 * client certificate was received. If it is the client end, | 143 * client certificate was received. If it is the client end, |
136 * [peerCertificate] will return the server's certificate. | 144 * [peerCertificate] will return the server's certificate. |
137 */ | 145 */ |
138 X509Certificate get peerCertificate; | 146 X509Certificate get peerCertificate; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 * [host] passed is a [String] the [InternetAddress] for the | 237 * [host] passed is a [String] the [InternetAddress] for the |
230 * resulting [SecureSocket] will have this passed in [host] as its | 238 * resulting [SecureSocket] will have this passed in [host] as its |
231 * host value and the internet address of the already connected | 239 * host value and the internet address of the already connected |
232 * socket as its address value. | 240 * socket as its address value. |
233 * | 241 * |
234 * See [connect] for more information on the arguments. | 242 * See [connect] for more information on the arguments. |
235 * | 243 * |
236 */ | 244 */ |
237 static Future<RawSecureSocket> secure( | 245 static Future<RawSecureSocket> secure( |
238 RawSocket socket, | 246 RawSocket socket, |
239 {StreamSubscription<RawSocketEvent> subscription, | 247 {StreamSubscription subscription, |
240 host, | 248 host, |
241 SecurityContext context, | 249 SecurityContext context, |
242 bool onBadCertificate(X509Certificate certificate), | 250 bool onBadCertificate(X509Certificate certificate), |
243 List<String> supportedProtocols}) { | 251 List<String> supportedProtocols}) { |
244 socket.readEventsEnabled = false; | 252 socket.readEventsEnabled = false; |
245 socket.writeEventsEnabled = false; | 253 socket.writeEventsEnabled = false; |
246 return _RawSecureSocket.connect( | 254 return _RawSecureSocket.connect( |
247 host != null ? host : socket.address.host, | 255 host != null ? host : socket.address.host, |
248 socket.port, | 256 socket.port, |
249 is_server: false, | 257 is_server: false, |
(...skipping 23 matching lines...) Expand all Loading... |
273 * parameter. This data will be processed before any other data | 281 * parameter. This data will be processed before any other data |
274 * available on the socket. | 282 * available on the socket. |
275 * | 283 * |
276 * See [RawSecureServerSocket.bind] for more information on the | 284 * See [RawSecureServerSocket.bind] for more information on the |
277 * arguments. | 285 * arguments. |
278 * | 286 * |
279 */ | 287 */ |
280 static Future<RawSecureSocket> secureServer( | 288 static Future<RawSecureSocket> secureServer( |
281 RawSocket socket, | 289 RawSocket socket, |
282 SecurityContext context, | 290 SecurityContext context, |
283 {StreamSubscription<RawSocketEvent> subscription, | 291 {StreamSubscription subscription, |
284 List<int> bufferedData, | 292 List<int> bufferedData, |
285 bool requestClientCertificate: false, | 293 bool requestClientCertificate: false, |
286 bool requireClientCertificate: false, | 294 bool requireClientCertificate: false, |
287 List<String> supportedProtocols}) { | 295 List<String> supportedProtocols}) { |
288 socket.readEventsEnabled = false; | 296 socket.readEventsEnabled = false; |
289 socket.writeEventsEnabled = false; | 297 socket.writeEventsEnabled = false; |
290 return _RawSecureSocket.connect( | 298 return _RawSecureSocket.connect( |
291 socket.address, | 299 socket.address, |
292 socket.remotePort, | 300 socket.remotePort, |
293 context: context, | 301 context: context, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 | 398 |
391 var _status = HANDSHAKE; | 399 var _status = HANDSHAKE; |
392 bool _writeEventsEnabled = true; | 400 bool _writeEventsEnabled = true; |
393 bool _readEventsEnabled = true; | 401 bool _readEventsEnabled = true; |
394 int _pauseCount = 0; | 402 int _pauseCount = 0; |
395 bool _pendingReadEvent = false; | 403 bool _pendingReadEvent = false; |
396 bool _socketClosedRead = false; // The network socket is closed for reading. | 404 bool _socketClosedRead = false; // The network socket is closed for reading. |
397 bool _socketClosedWrite = false; // The network socket is closed for writing. | 405 bool _socketClosedWrite = false; // The network socket is closed for writing. |
398 bool _closedRead = false; // The secure socket has fired an onClosed event. | 406 bool _closedRead = false; // The secure socket has fired an onClosed event. |
399 bool _closedWrite = false; // The secure socket has been closed for writing. | 407 bool _closedWrite = false; // The secure socket has been closed for writing. |
400 // The network socket is gone. | 408 Completer _closeCompleter = new Completer(); // The network socket is gone. |
401 Completer<RawSecureSocket> _closeCompleter = new Completer<RawSecureSocket>(); | |
402 _FilterStatus _filterStatus = new _FilterStatus(); | 409 _FilterStatus _filterStatus = new _FilterStatus(); |
403 bool _connectPending = true; | 410 bool _connectPending = true; |
404 bool _filterPending = false; | 411 bool _filterPending = false; |
405 bool _filterActive = false; | 412 bool _filterActive = false; |
406 | 413 |
407 _SecureFilter _secureFilter = new _SecureFilter(); | 414 _SecureFilter _secureFilter = new _SecureFilter(); |
408 String _selectedProtocol; | 415 String _selectedProtocol; |
409 | 416 |
410 static Future<_RawSecureSocket> connect( | 417 static Future<_RawSecureSocket> connect( |
411 dynamic/*String|InternetAddress*/ host, | 418 dynamic/*String|InternetAddress*/ host, |
412 int requestedPort, | 419 int requestedPort, |
413 {bool is_server, | 420 {bool is_server, |
414 SecurityContext context, | 421 SecurityContext context, |
415 RawSocket socket, | 422 RawSocket socket, |
416 StreamSubscription<RawSocketEvent> subscription, | 423 StreamSubscription subscription, |
417 List<int> bufferedData, | 424 List<int> bufferedData, |
418 bool requestClientCertificate: false, | 425 bool requestClientCertificate: false, |
419 bool requireClientCertificate: false, | 426 bool requireClientCertificate: false, |
420 bool onBadCertificate(X509Certificate certificate), | 427 bool onBadCertificate(X509Certificate certificate), |
421 List<String> supportedProtocols}) { | 428 List<String> supportedProtocols}) { |
422 _verifyFields(host, requestedPort, is_server, | 429 _verifyFields(host, requestedPort, is_server, |
423 requestClientCertificate, requireClientCertificate, | 430 requestClientCertificate, requireClientCertificate, |
424 onBadCertificate); | 431 onBadCertificate); |
425 if (host is InternetAddress) host = host.host; | 432 if (host is InternetAddress) host = host.host; |
426 InternetAddress address = socket.address; | 433 InternetAddress address = socket.address; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 int available() { | 569 int available() { |
563 return _status != CONNECTED ? 0 | 570 return _status != CONNECTED ? 0 |
564 : _secureFilter.buffers[READ_PLAINTEXT].length; | 571 : _secureFilter.buffers[READ_PLAINTEXT].length; |
565 } | 572 } |
566 | 573 |
567 Future<RawSecureSocket> close() { | 574 Future<RawSecureSocket> close() { |
568 shutdown(SocketDirection.BOTH); | 575 shutdown(SocketDirection.BOTH); |
569 return _closeCompleter.future; | 576 return _closeCompleter.future; |
570 } | 577 } |
571 | 578 |
572 void _completeCloseCompleter([RawSocket dummy]) { | 579 void _completeCloseCompleter([dummy]) { |
573 if (!_closeCompleter.isCompleted) _closeCompleter.complete(this); | 580 if (!_closeCompleter.isCompleted) _closeCompleter.complete(this); |
574 } | 581 } |
575 | 582 |
576 void _close() { | 583 void _close() { |
577 _closedWrite = true; | 584 _closedWrite = true; |
578 _closedRead = true; | 585 _closedRead = true; |
579 if (_socket != null) { | 586 if (_socket != null) { |
580 _socket.close().then(_completeCloseCompleter); | 587 _socket.close().then(_completeCloseCompleter); |
581 } else { | 588 } else { |
582 _completeCloseCompleter(); | 589 _completeCloseCompleter(); |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 } | 1055 } |
1049 } | 1056 } |
1050 | 1057 |
1051 | 1058 |
1052 /** | 1059 /** |
1053 * A circular buffer backed by an external byte array. Accessed from | 1060 * A circular buffer backed by an external byte array. Accessed from |
1054 * both C++ and Dart code in an unsynchronized way, with one reading | 1061 * both C++ and Dart code in an unsynchronized way, with one reading |
1055 * and one writing. All updates to start and end are done by Dart code. | 1062 * and one writing. All updates to start and end are done by Dart code. |
1056 */ | 1063 */ |
1057 class _ExternalBuffer { | 1064 class _ExternalBuffer { |
1058 // This will be an ExternalByteArray, backed by C allocated data. | 1065 List data; // This will be a ExternalByteArray, backed by C allocated data. |
1059 List<int> data; | |
1060 int start; | 1066 int start; |
1061 int end; | 1067 int end; |
1062 final size; | 1068 final size; |
1063 | 1069 |
1064 _ExternalBuffer(this.size) { | 1070 _ExternalBuffer(this.size) { |
1065 start = end = size ~/ 2; | 1071 start = end = size ~/ 2; |
1066 } | 1072 } |
1067 | 1073 |
1068 void advanceStart(int bytes) { | 1074 void advanceStart(int bytes) { |
1069 assert(start > end || start + bytes <= end); | 1075 assert(start > end || start + bytes <= end); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 /** | 1254 /** |
1249 * An exception that happens in the handshake phase of establishing | 1255 * An exception that happens in the handshake phase of establishing |
1250 * a secure network connection, when looking up or verifying a | 1256 * a secure network connection, when looking up or verifying a |
1251 * certificate. | 1257 * certificate. |
1252 */ | 1258 */ |
1253 class CertificateException extends TlsException { | 1259 class CertificateException extends TlsException { |
1254 const CertificateException([String message = "", | 1260 const CertificateException([String message = "", |
1255 OSError osError = null]) | 1261 OSError osError = null]) |
1256 : super._("CertificateException", message, osError); | 1262 : super._("CertificateException", message, osError); |
1257 } | 1263 } |
OLD | NEW |