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

Side by Side Diff: sdk/lib/io/secure_socket.dart

Issue 1319703002: Breaking Change: merge BoringSSL branch into master (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months 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
« no previous file with comments | « sdk/lib/io/secure_server_socket.dart ('k') | sdk/lib/io/security_context.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 * other [Stream]s. 11 * other [Stream]s.
12 */ 12 */
13 abstract class SecureSocket implements Socket { 13 abstract class SecureSocket implements Socket {
14 external factory SecureSocket._(RawSecureSocket rawSocket); 14 external factory SecureSocket._(RawSecureSocket rawSocket);
15 15
16 /** 16 /**
17 * Constructs a new secure client socket and connect it to the given 17 * Constructs a new secure client socket and connect it to the given
18 * [host] on port [port]. The returned Future will complete with a 18 * [host] on port [port]. The returned Future will complete with a
19 * [SecureSocket] that is connected and ready for subscription. 19 * [SecureSocket] that is connected and ready for subscription.
20 * 20 *
21 * If [sendClientCertificate] is set to true, the socket will send a client
22 * certificate if one is requested by the server.
23 *
24 * If [certificateName] is the nickname of a certificate in the certificate
25 * database, that certificate will be sent.
26 *
27 * If [certificateName] is null, which is the usual use case, an
28 * appropriate certificate will be searched for in the database and
29 * sent automatically, based on what the server says it will accept.
30 *
31 * [onBadCertificate] is an optional handler for unverifiable certificates. 21 * [onBadCertificate] is an optional handler for unverifiable certificates.
32 * The handler receives the [X509Certificate], and can inspect it and 22 * The handler receives the [X509Certificate], and can inspect it and
33 * decide (or let the user decide) whether to accept 23 * decide (or let the user decide) whether to accept
34 * the connection or not. The handler should return true 24 * the connection or not. The handler should return true
35 * to continue the [SecureSocket] connection. 25 * to continue the [SecureSocket] connection.
36 */ 26 */
37 static Future<SecureSocket> connect( 27 static Future<SecureSocket> connect(
38 host, 28 host,
39 int port, 29 int port,
40 {bool sendClientCertificate: false, 30 {SecurityContext context,
41 String certificateName,
42 bool onBadCertificate(X509Certificate certificate), 31 bool onBadCertificate(X509Certificate certificate),
32 bool sendClientCertificate,
43 List<String> supportedProtocols}) { 33 List<String> supportedProtocols}) {
44 return RawSecureSocket.connect(host, 34 return RawSecureSocket.connect(host,
45 port, 35 port,
46 sendClientCertificate: sendClientCertificate, 36 context: context,
47 certificateName: certificateName,
48 onBadCertificate: onBadCertificate, 37 onBadCertificate: onBadCertificate,
49 supportedProtocols: supportedProtocols) 38 supportedProtocols: supportedProtocols)
50 .then((rawSocket) => new SecureSocket._(rawSocket)); 39 .then((rawSocket) => new SecureSocket._(rawSocket));
51 } 40 }
52 41
53 /** 42 /**
54 * Takes an already connected [socket] and starts client side TLS 43 * Takes an already connected [socket] and starts client side TLS
55 * handshake to make the communication secure. When the returned 44 * handshake to make the communication secure. When the returned
56 * future completes the [SecureSocket] has completed the TLS 45 * future completes the [SecureSocket] has completed the TLS
57 * handshake. Using this function requires that the other end of the 46 * handshake. Using this function requires that the other end of the
(...skipping 14 matching lines...) Expand all
72 * resulting [SecureSocket] will have the passed in [host] as its 61 * resulting [SecureSocket] will have the passed in [host] as its
73 * host value and the internet address of the already connected 62 * host value and the internet address of the already connected
74 * socket as its address value. 63 * socket as its address value.
75 * 64 *
76 * See [connect] for more information on the arguments. 65 * See [connect] for more information on the arguments.
77 * 66 *
78 */ 67 */
79 static Future<SecureSocket> secure( 68 static Future<SecureSocket> secure(
80 Socket socket, 69 Socket socket,
81 {host, 70 {host,
82 bool sendClientCertificate: false, 71 SecurityContext context,
83 String certificateName,
84 bool onBadCertificate(X509Certificate certificate)}) { 72 bool onBadCertificate(X509Certificate certificate)}) {
85 var completer = new Completer(); 73 var completer = new Completer();
86 (socket as dynamic)._detachRaw() 74 (socket as dynamic)._detachRaw()
87 .then((detachedRaw) { 75 .then((detachedRaw) {
88 return RawSecureSocket.secure( 76 return RawSecureSocket.secure(
89 detachedRaw[0], 77 detachedRaw[0],
90 subscription: detachedRaw[1], 78 subscription: detachedRaw[1],
91 host: host, 79 host: host,
92 sendClientCertificate: sendClientCertificate, 80 context: context,
93 onBadCertificate: onBadCertificate); 81 onBadCertificate: onBadCertificate);
94 }) 82 })
95 .then((raw) { 83 .then((raw) {
96 completer.complete(new SecureSocket._(raw)); 84 completer.complete(new SecureSocket._(raw));
97 }); 85 });
98 return completer.future; 86 return completer.future;
99 } 87 }
100 88
101 /** 89 /**
102 * Takes an already connected [socket] and starts server side TLS 90 * Takes an already connected [socket] and starts server side TLS
(...skipping 11 matching lines...) Expand all
114 * from the socket this data can be passed in the [bufferedData] 102 * from the socket this data can be passed in the [bufferedData]
115 * parameter. This data will be processed before any other data 103 * parameter. This data will be processed before any other data
116 * available on the socket. 104 * available on the socket.
117 * 105 *
118 * See [SecureServerSocket.bind] for more information on the 106 * See [SecureServerSocket.bind] for more information on the
119 * arguments. 107 * arguments.
120 * 108 *
121 */ 109 */
122 static Future<SecureSocket> secureServer( 110 static Future<SecureSocket> secureServer(
123 Socket socket, 111 Socket socket,
124 String certificateName, 112 SecurityContext context,
125 {List<int> bufferedData, 113 {List<int> bufferedData,
126 bool requestClientCertificate: false, 114 bool requestClientCertificate: false,
127 bool requireClientCertificate: false, 115 bool requireClientCertificate: false,
128 List<String> supportedProtocols}) { 116 List<String> supportedProtocols}) {
129 var completer = new Completer(); 117 var completer = new Completer();
130 (socket as dynamic)._detachRaw() 118 (socket as dynamic)._detachRaw()
131 .then((detachedRaw) { 119 .then((detachedRaw) {
132 return RawSecureSocket.secureServer( 120 return RawSecureSocket.secureServer(
133 detachedRaw[0], 121 detachedRaw[0],
134 certificateName, 122 context,
135 subscription: detachedRaw[1], 123 subscription: detachedRaw[1],
136 bufferedData: bufferedData, 124 bufferedData: bufferedData,
137 requestClientCertificate: requestClientCertificate, 125 requestClientCertificate: requestClientCertificate,
138 requireClientCertificate: requireClientCertificate, 126 requireClientCertificate: requireClientCertificate,
139 supportedProtocols: supportedProtocols); 127 supportedProtocols: supportedProtocols);
140 }) 128 })
141 .then((raw) { 129 .then((raw) {
142 completer.complete(new SecureSocket._(raw)); 130 completer.complete(new SecureSocket._(raw));
143 }); 131 });
144 return completer.future; 132 return completer.future;
(...skipping 16 matching lines...) Expand all
161 /** 149 /**
162 * Renegotiate an existing secure connection, renewing the session keys 150 * Renegotiate an existing secure connection, renewing the session keys
163 * and possibly changing the connection properties. 151 * and possibly changing the connection properties.
164 * 152 *
165 * This repeats the SSL or TLS handshake, with options that allow clearing 153 * This repeats the SSL or TLS handshake, with options that allow clearing
166 * the session cache and requesting a client certificate. 154 * the session cache and requesting a client certificate.
167 */ 155 */
168 void renegotiate({bool useSessionCache: true, 156 void renegotiate({bool useSessionCache: true,
169 bool requestClientCertificate: false, 157 bool requestClientCertificate: false,
170 bool requireClientCertificate: false}); 158 bool requireClientCertificate: false});
171
172 /**
173 * Initializes the NSS library. If [initialize] is not called, the library
174 * is automatically initialized as if [initialize] were called with no
175 * arguments. If [initialize] is called more than once, or called after
176 * automatic initialization has happened (when a secure connection is made),
177 * then a TlsException is thrown.
178 *
179 * The optional argument [database] is the path to a certificate database
180 * directory containing root certificates for verifying certificate paths on
181 * client connections, and server certificates to provide on server
182 * connections. The argument [password] should be used when creating
183 * secure server sockets, to allow the private key of the server
184 * certificate to be fetched. If [useBuiltinRoots] is true (the default),
185 * then a built-in set of root certificates for trusted certificate
186 * authorities is merged with the certificates in the database.
187 * The list of built-in root certificates, and documentation about this
188 * default database, is available at
189 * http://www.mozilla.org/projects/security/certs/included/ .
190 *
191 * If the [database] argument is omitted, then only the
192 * builtin root certificates are used. If [useBuiltinRoots] is also false,
193 * then no certificates are available.
194 *
195 * Examples:
196 * 1) Use only the builtin root certificates:
197 * SecureSocket.initialize(); or
198 *
199 * 2) Use a specified database directory and the builtin roots:
200 * SecureSocket.initialize(database: 'path/to/my/database',
201 * password: 'my_password');
202 *
203 * 3) Use a specified database directory, without builtin roots:
204 * SecureSocket.initialize(database: 'path/to/my/database',
205 * password: 'my_password'.
206 * useBuiltinRoots: false);
207 *
208 * The database should be an NSS certificate database directory
209 * containing a cert9.db file, not a cert8.db file. This version of
210 * the database can be created using the NSS certutil tool with "sql:" in
211 * front of the absolute path of the database directory, or setting the
212 * environment variable [[NSS_DEFAULT_DB_TYPE]] to "sql".
213 */
214 external static void initialize({String database,
215 String password,
216 bool useBuiltinRoots: true});
217 } 159 }
218 160
219 161
220 /** 162 /**
221 * RawSecureSocket provides a secure (SSL or TLS) network connection. 163 * RawSecureSocket provides a secure (SSL or TLS) network connection.
222 * Client connections to a server are provided by calling 164 * Client connections to a server are provided by calling
223 * RawSecureSocket.connect. A secure server, created with 165 * RawSecureSocket.connect. A secure server, created with
224 * RawSecureServerSocket, also returns RawSecureSocket objects representing 166 * RawSecureServerSocket, also returns RawSecureSocket objects representing
225 * the server end of a secure connection. 167 * the server end of a secure connection.
226 * The certificate provided by the server is checked 168 * The certificate provided by the server is checked
227 * using the certificate database provided in SecureSocket.initialize, and/or 169 * using the trusted certificates set in the SecurityContext object and/or
228 * the default built-in root certificates. 170 * the default built-in root certificates.
229 */ 171 */
230 abstract class RawSecureSocket implements RawSocket { 172 abstract class RawSecureSocket implements RawSocket {
231 /** 173 /**
232 * Constructs a new secure client socket and connect it to the given 174 * Constructs a new secure client socket and connect it to the given
233 * host on the given port. The returned Future is completed with the 175 * host on the given port. The returned Future is completed with the
234 * RawSecureSocket when it is connected and ready for subscription. 176 * RawSecureSocket when it is connected and ready for subscription.
235 * 177 *
236 * The certificate provided by the server is checked using the certificate 178 * The certificate provided by the server is checked
237 * database provided in [SecureSocket.initialize], and/or the default built-in 179 * using the trusted certificates set in the SecurityContext object and/or
180 * the default built-in
238 * root certificates. If [sendClientCertificate] is 181 * root certificates. If [sendClientCertificate] is
239 * set to true, the socket will send a client certificate if one is 182 * set to true, the socket will send a client certificate if one is
240 * requested by the server. If [certificateName] is the nickname of 183 * requested by the server. If [certificateName] is the nickname of
241 * a certificate in the certificate database, that certificate will be sent. 184 * a certificate in the certificate database, that certificate will be sent.
242 * If [certificateName] is null, which is the usual use case, an 185 * If [certificateName] is null, which is the usual use case, an
243 * appropriate certificate will be searched for in the database and 186 * appropriate certificate will be searched for in the database and
244 * sent automatically, based on what the server says it will accept. 187 * sent automatically, based on what the server says it will accept.
245 * 188 *
246 * [onBadCertificate] is an optional handler for unverifiable certificates. 189 * [onBadCertificate] is an optional handler for unverifiable certificates.
247 * The handler receives the [X509Certificate], and can inspect it and 190 * The handler receives the [X509Certificate], and can inspect it and
248 * decide (or let the user decide) whether to accept 191 * decide (or let the user decide) whether to accept
249 * the connection or not. The handler should return true 192 * the connection or not. The handler should return true
250 * to continue the [RawSecureSocket] connection. 193 * to continue the [RawSecureSocket] connection.
251 */ 194 */
252 static Future<RawSecureSocket> connect( 195 static Future<RawSecureSocket> connect(
253 host, 196 host,
254 int port, 197 int port,
255 {bool sendClientCertificate: false, 198 {SecurityContext context,
256 String certificateName,
257 bool onBadCertificate(X509Certificate certificate), 199 bool onBadCertificate(X509Certificate certificate),
258 List<String> supportedProtocols}) { 200 List<String> supportedProtocols}) {
259 _RawSecureSocket._verifyFields( 201 _RawSecureSocket._verifyFields(
260 host, 202 host,
261 port, 203 port,
262 certificateName,
263 false, 204 false,
264 false, 205 false,
265 false, 206 false,
266 sendClientCertificate,
267 onBadCertificate); 207 onBadCertificate);
268 return RawSocket.connect(host, port) 208 return RawSocket.connect(host, port)
269 .then((socket) { 209 .then((socket) {
270 return secure(socket, 210 return secure(socket,
271 sendClientCertificate: sendClientCertificate, 211 context: context,
272 certificateName: certificateName,
273 onBadCertificate: onBadCertificate, 212 onBadCertificate: onBadCertificate,
274 supportedProtocols: supportedProtocols); 213 supportedProtocols: supportedProtocols);
275 }); 214 });
276 } 215 }
277 216
278 /** 217 /**
279 * Takes an already connected [socket] and starts client side TLS 218 * Takes an already connected [socket] and starts client side TLS
280 * handshake to make the communication secure. When the returned 219 * handshake to make the communication secure. When the returned
281 * future completes the [RawSecureSocket] has completed the TLS 220 * future completes the [RawSecureSocket] has completed the TLS
282 * handshake. Using this function requires that the other end of the 221 * handshake. Using this function requires that the other end of the
(...skipping 17 matching lines...) Expand all
300 * host value and the internet address of the already connected 239 * host value and the internet address of the already connected
301 * socket as its address value. 240 * socket as its address value.
302 * 241 *
303 * See [connect] for more information on the arguments. 242 * See [connect] for more information on the arguments.
304 * 243 *
305 */ 244 */
306 static Future<RawSecureSocket> secure( 245 static Future<RawSecureSocket> secure(
307 RawSocket socket, 246 RawSocket socket,
308 {StreamSubscription subscription, 247 {StreamSubscription subscription,
309 host, 248 host,
310 bool sendClientCertificate: false, 249 SecurityContext context,
311 String certificateName,
312 bool onBadCertificate(X509Certificate certificate), 250 bool onBadCertificate(X509Certificate certificate),
313 List<String> supportedProtocols}) { 251 List<String> supportedProtocols}) {
314 socket.readEventsEnabled = false; 252 socket.readEventsEnabled = false;
315 socket.writeEventsEnabled = false; 253 socket.writeEventsEnabled = false;
316 return _RawSecureSocket.connect( 254 return _RawSecureSocket.connect(
317 host != null ? host : socket.address.host, 255 host != null ? host : socket.address.host,
318 socket.port, 256 socket.port,
319 certificateName,
320 is_server: false, 257 is_server: false,
321 socket: socket, 258 socket: socket,
322 subscription: subscription, 259 subscription: subscription,
323 sendClientCertificate: sendClientCertificate, 260 context: context,
324 onBadCertificate: onBadCertificate, 261 onBadCertificate: onBadCertificate,
325 supportedProtocols: supportedProtocols); 262 supportedProtocols: supportedProtocols);
326 } 263 }
327 264
328 /** 265 /**
329 * Takes an already connected [socket] and starts server side TLS 266 * Takes an already connected [socket] and starts server side TLS
330 * handshake to make the communication secure. When the returned 267 * handshake to make the communication secure. When the returned
331 * future completes the [RawSecureSocket] has completed the TLS 268 * future completes the [RawSecureSocket] has completed the TLS
332 * handshake. Using this function requires that the other end of the 269 * handshake. Using this function requires that the other end of the
333 * connection is going to start the TLS handshake. 270 * connection is going to start the TLS handshake.
334 * 271 *
335 * If the [socket] already has a subscription, pass the existing 272 * If the [socket] already has a subscription, pass the existing
336 * subscription in the [subscription] parameter. The [secureServer] 273 * subscription in the [subscription] parameter. The [secureServer]
337 * operation will take over the subscription by replacing the 274 * operation will take over the subscription by replacing the
338 * handlers with it own secure processing. The caller must not touch 275 * handlers with it own secure processing. The caller must not touch
339 * this subscription anymore. Passing a paused subscription is an 276 * this subscription anymore. Passing a paused subscription is an
340 * error. 277 * error.
341 * 278 *
342 * If some of the data of the TLS handshake has already been read 279 * If some of the data of the TLS handshake has already been read
343 * from the socket this data can be passed in the [bufferedData] 280 * from the socket this data can be passed in the [bufferedData]
344 * parameter. This data will be processed before any other data 281 * parameter. This data will be processed before any other data
345 * available on the socket. 282 * available on the socket.
346 * 283 *
347 * See [RawSecureServerSocket.bind] for more information on the 284 * See [RawSecureServerSocket.bind] for more information on the
348 * arguments. 285 * arguments.
349 * 286 *
350 */ 287 */
351 static Future<RawSecureSocket> secureServer( 288 static Future<RawSecureSocket> secureServer(
352 RawSocket socket, 289 RawSocket socket,
353 String certificateName, 290 SecurityContext context,
354 {StreamSubscription subscription, 291 {StreamSubscription subscription,
355 List<int> bufferedData, 292 List<int> bufferedData,
356 bool requestClientCertificate: false, 293 bool requestClientCertificate: false,
357 bool requireClientCertificate: false, 294 bool requireClientCertificate: false,
358 List<String> supportedProtocols}) { 295 List<String> supportedProtocols}) {
359 socket.readEventsEnabled = false; 296 socket.readEventsEnabled = false;
360 socket.writeEventsEnabled = false; 297 socket.writeEventsEnabled = false;
361 return _RawSecureSocket.connect( 298 return _RawSecureSocket.connect(
362 socket.address, 299 socket.address,
363 socket.remotePort, 300 socket.remotePort,
364 certificateName, 301 context: context,
365 is_server: true, 302 is_server: true,
366 socket: socket, 303 socket: socket,
367 subscription: subscription, 304 subscription: subscription,
368 bufferedData: bufferedData, 305 bufferedData: bufferedData,
369 requestClientCertificate: requestClientCertificate, 306 requestClientCertificate: requestClientCertificate,
370 requireClientCertificate: requireClientCertificate, 307 requireClientCertificate: requireClientCertificate,
371 supportedProtocols: supportedProtocols); 308 supportedProtocols: supportedProtocols);
372 } 309 }
373 310
374 /** 311 /**
(...skipping 20 matching lines...) Expand all
395 * Get the protocol which was selected during protocol negotiation. 332 * Get the protocol which was selected during protocol negotiation.
396 */ 333 */
397 String get selectedProtocol; 334 String get selectedProtocol;
398 } 335 }
399 336
400 337
401 /** 338 /**
402 * X509Certificate represents an SSL certificate, with accessors to 339 * X509Certificate represents an SSL certificate, with accessors to
403 * get the fields of the certificate. 340 * get the fields of the certificate.
404 */ 341 */
405 class X509Certificate { 342 abstract class X509Certificate {
406 X509Certificate(this.subject, 343 external factory X509Certificate._();
407 this.issuer, 344
408 this.startValidity, 345 String get subject;
409 this.endValidity); 346 String get issuer;
410 final String subject; 347 DateTime get startValidity;
411 final String issuer; 348 DateTime get endValidity;
412 final DateTime startValidity;
413 final DateTime endValidity;
414 } 349 }
415 350
416 351
417 class _FilterStatus { 352 class _FilterStatus {
418 bool progress = false; // The filter read or wrote data to the buffers. 353 bool progress = false; // The filter read or wrote data to the buffers.
419 bool readEmpty = true; // The read buffers and decryption filter are empty. 354 bool readEmpty = true; // The read buffers and decryption filter are empty.
420 bool writeEmpty = true; // The write buffers and encryption filter are empty. 355 bool writeEmpty = true; // The write buffers and encryption filter are empty.
421 // These are set if a buffer changes state from empty or full. 356 // These are set if a buffer changes state from empty or full.
422 bool readPlaintextNoLongerEmpty = false; 357 bool readPlaintextNoLongerEmpty = false;
423 bool writePlaintextNoLongerFull = false; 358 bool writePlaintextNoLongerFull = false;
(...skipping 25 matching lines...) Expand all
449 RawSocket _socket; 384 RawSocket _socket;
450 final Completer<_RawSecureSocket> _handshakeComplete = 385 final Completer<_RawSecureSocket> _handshakeComplete =
451 new Completer<_RawSecureSocket>(); 386 new Completer<_RawSecureSocket>();
452 StreamController<RawSocketEvent> _controller; 387 StreamController<RawSocketEvent> _controller;
453 Stream<RawSocketEvent> _stream; 388 Stream<RawSocketEvent> _stream;
454 StreamSubscription<RawSocketEvent> _socketSubscription; 389 StreamSubscription<RawSocketEvent> _socketSubscription;
455 List<int> _bufferedData; 390 List<int> _bufferedData;
456 int _bufferedDataIndex = 0; 391 int _bufferedDataIndex = 0;
457 final InternetAddress address; 392 final InternetAddress address;
458 final bool is_server; 393 final bool is_server;
459 final String certificateName; 394 SecurityContext context;
460 final bool requestClientCertificate; 395 final bool requestClientCertificate;
461 final bool requireClientCertificate; 396 final bool requireClientCertificate;
462 final bool sendClientCertificate;
463 final Function onBadCertificate; 397 final Function onBadCertificate;
464 398
465 var _status = HANDSHAKE; 399 var _status = HANDSHAKE;
466 bool _writeEventsEnabled = true; 400 bool _writeEventsEnabled = true;
467 bool _readEventsEnabled = true; 401 bool _readEventsEnabled = true;
468 int _pauseCount = 0; 402 int _pauseCount = 0;
469 bool _pendingReadEvent = false; 403 bool _pendingReadEvent = false;
470 bool _socketClosedRead = false; // The network socket is closed for reading. 404 bool _socketClosedRead = false; // The network socket is closed for reading.
471 bool _socketClosedWrite = false; // The network socket is closed for writing. 405 bool _socketClosedWrite = false; // The network socket is closed for writing.
472 bool _closedRead = false; // The secure socket has fired an onClosed event. 406 bool _closedRead = false; // The secure socket has fired an onClosed event.
473 bool _closedWrite = false; // The secure socket has been closed for writing. 407 bool _closedWrite = false; // The secure socket has been closed for writing.
474 Completer _closeCompleter = new Completer(); // The network socket is gone. 408 Completer _closeCompleter = new Completer(); // The network socket is gone.
475 _FilterStatus _filterStatus = new _FilterStatus(); 409 _FilterStatus _filterStatus = new _FilterStatus();
476 bool _connectPending = true; 410 bool _connectPending = true;
477 bool _filterPending = false; 411 bool _filterPending = false;
478 bool _filterActive = false; 412 bool _filterActive = false;
479 413
480 _SecureFilter _secureFilter = new _SecureFilter(); 414 _SecureFilter _secureFilter = new _SecureFilter();
481 int _filterPointer; 415 int _filterPointer;
482 String _selectedProtocol; 416 String _selectedProtocol;
483 417
484 static Future<_RawSecureSocket> connect( 418 static Future<_RawSecureSocket> connect(
485 host, 419 host,
486 int requestedPort, 420 int requestedPort,
487 String certificateName,
488 {bool is_server, 421 {bool is_server,
422 SecurityContext context,
489 RawSocket socket, 423 RawSocket socket,
490 StreamSubscription subscription, 424 StreamSubscription subscription,
491 List<int> bufferedData, 425 List<int> bufferedData,
492 bool requestClientCertificate: false, 426 bool requestClientCertificate: false,
493 bool requireClientCertificate: false, 427 bool requireClientCertificate: false,
494 bool sendClientCertificate: false, 428 bool sendClientCertificate: false,
495 bool onBadCertificate(X509Certificate certificate), 429 bool onBadCertificate(X509Certificate certificate),
496 List<String> supportedProtocols}) { 430 List<String> supportedProtocols}) {
497 _verifyFields(host, requestedPort, certificateName, is_server, 431 _verifyFields(host, requestedPort, is_server,
498 requestClientCertificate, requireClientCertificate, 432 requestClientCertificate, requireClientCertificate,
499 sendClientCertificate, onBadCertificate); 433 onBadCertificate);
500 if (host is InternetAddress) host = host.host; 434 if (host is InternetAddress) host = host.host;
501 var address = socket.address; 435 var address = socket.address;
502 if (host != null) address = address._cloneWithNewHost(host); 436 if (host != null) address = address._cloneWithNewHost(host);
503 return new _RawSecureSocket(address, 437 return new _RawSecureSocket(address,
504 requestedPort, 438 requestedPort,
505 certificateName,
506 is_server, 439 is_server,
440 context,
507 socket, 441 socket,
508 subscription, 442 subscription,
509 bufferedData, 443 bufferedData,
510 requestClientCertificate, 444 requestClientCertificate,
511 requireClientCertificate, 445 requireClientCertificate,
512 sendClientCertificate,
513 onBadCertificate, 446 onBadCertificate,
514 supportedProtocols) 447 supportedProtocols)
515 ._handshakeComplete.future; 448 ._handshakeComplete.future;
516 } 449 }
517 450
518 _RawSecureSocket( 451 _RawSecureSocket(
519 this.address, 452 this.address,
520 int requestedPort, 453 int requestedPort,
521 this.certificateName,
522 this.is_server, 454 this.is_server,
455 this.context,
523 RawSocket this._socket, 456 RawSocket this._socket,
524 this._socketSubscription, 457 this._socketSubscription,
525 this._bufferedData, 458 this._bufferedData,
526 this.requestClientCertificate, 459 this.requestClientCertificate,
527 this.requireClientCertificate, 460 this.requireClientCertificate,
528 this.sendClientCertificate,
529 this.onBadCertificate(X509Certificate certificate), 461 this.onBadCertificate(X509Certificate certificate),
530 List<String> supportedProtocols) { 462 List<String> supportedProtocols) {
463 if (context == null) {
464 context = SecurityContext.defaultContext;
465 }
531 _controller = new StreamController<RawSocketEvent>( 466 _controller = new StreamController<RawSocketEvent>(
532 sync: true, 467 sync: true,
533 onListen: _onSubscriptionStateChange, 468 onListen: _onSubscriptionStateChange,
534 onPause: _onPauseStateChange, 469 onPause: _onPauseStateChange,
535 onResume: _onPauseStateChange, 470 onResume: _onPauseStateChange,
536 onCancel: _onSubscriptionStateChange); 471 onCancel: _onSubscriptionStateChange);
537 _stream = _controller.stream; 472 _stream = _controller.stream;
538 // Throw an ArgumentError if any field is invalid. After this, all 473 // Throw an ArgumentError if any field is invalid. After this, all
539 // errors will be reported through the future or the stream. 474 // errors will be reported through the future or the stream.
540 _secureFilter.init(); 475 _secureFilter.init();
(...skipping 22 matching lines...) Expand all
563 dynamic s = _socket; // Cast to dynamic to avoid warning. 498 dynamic s = _socket; // Cast to dynamic to avoid warning.
564 if (s._socket.closedReadEventSent) { 499 if (s._socket.closedReadEventSent) {
565 _eventDispatcher(RawSocketEvent.READ_CLOSED); 500 _eventDispatcher(RawSocketEvent.READ_CLOSED);
566 } 501 }
567 _socketSubscription 502 _socketSubscription
568 ..onData(_eventDispatcher) 503 ..onData(_eventDispatcher)
569 ..onError(_reportError) 504 ..onError(_reportError)
570 ..onDone(_doneHandler); 505 ..onDone(_doneHandler);
571 } 506 }
572 try { 507 try {
508 var encodedProtocols =
509 SecurityContext._protocolsToLengthEncoding(supportedProtocols);
573 _secureFilter.connect(address.host, 510 _secureFilter.connect(address.host,
574 (address as dynamic)._in_addr, 511 context,
575 port,
576 is_server, 512 is_server,
577 certificateName,
578 requestClientCertificate || 513 requestClientCertificate ||
579 requireClientCertificate, 514 requireClientCertificate,
580 requireClientCertificate, 515 requireClientCertificate,
581 sendClientCertificate, 516 // TODO(whesse): Remove sendClientCertificate
582 _protocolsToLengthEncoding(supportedProtocols)); 517 // argument, or add it to API.
518 false, // sendClientCertificate,
519 encodedProtocols);
583 _secureHandshake(); 520 _secureHandshake();
584 } catch (e, s) { 521 } catch (e, s) {
585 _reportError(e, s); 522 _reportError(e, s);
586 } 523 }
587 } 524 }
588 525
589 /// Encodes a set of supported protocols for ALPN/NPN usage.
590 ///
591 /// The `protocols` list is expected to contain protocols in descending order
592 /// of preference.
593 ///
594 /// See RFC 7301 (https://tools.ietf.org/html/rfc7301) for the encoding of
595 /// `List<String> protocols`:
596 /// opaque ProtocolName<1..2^8-1>;
597 ///
598 /// struct {
599 /// ProtocolName protocol_name_list<2..2^16-1>
600 /// } ProtocolNameList;
601 ///
602 /// The encoding of the opaque `ProtocolName<lower..upper>` vector is
603 /// described in RFC 2246: 4.3 Vectors.
604 ///
605 /// Note: Even though this encoding scheme would allow a total
606 /// `ProtocolNameList` length of 65535, this limit cannot be reached. Testing
607 /// showed that more than ~ 65480 bytes will fail to negogiate a protocol.
608 /// We will be conservative and support only messages up to (1<<15) -1 bytes.
609 ///
610 /// Our NSS implementation will support ALPN and NPN transparently. The
611 /// default protocol will be the first in the encoded Uint8List.
612 ///
613 /// NOTE: The NSS library will treat the first protocol as the fallback
614 /// protocol. The remaining ones are sorted in (decreasing) priority order.
615 /// We therefore put the protocol least desired to the front, to make it the
616 /// default.
617 Uint8List _protocolsToLengthEncoding(List<String> protocols) {
618 if (protocols == null || protocols.length == 0) {
619 return new Uint8List(0);
620 }
621 int protocolsLength = protocols.length;
622
623 // Calculate the number of bytes we will need if it is ASCII.
624 int expectedLength = protocolsLength;
625 for (int i = 0; i < protocolsLength; i++) {
626 int length = protocols[i].length;
627 if (length > 0 && length <= 255) {
628 expectedLength += length;
629 } else {
630 throw new ArgumentError(
631 'Length of protocol must be between 1 and 255 (was: $length).');
632 }
633 }
634
635 if (expectedLength >= (1 << 15)) {
636 throw new ArgumentError(
637 'The maximum message length supported is 2^15-1.');
638 }
639
640 // Try encoding the `List<String> protocols` array using fast ASCII path.
641 var bytes = new Uint8List(expectedLength);
642 int bytesOffset = 0;
643 for (int i = 0; i < protocolsLength; i++) {
644 // The last protocol will be encoded as the first/default one in the list.
645 // (i.e. rotate `protocols` by 1 to the right).
646 int index = i;
647 if (index == 0) index = protocols.length;
648 String proto = protocols[index - 1];
649
650 // Add length byte.
651 bytes[bytesOffset++] = proto.length;
652 int bits = 0;
653
654 // Add protocol bytes.
655 for (int j = 0; j < proto.length; j++) {
656 var char = proto.codeUnitAt(j);
657 bits |= char;
658 bytes[bytesOffset++] = char & 0xff;
659 }
660
661 // Go slow case if we have encountered anything non-ascii.
662 if (bits > 0x7f) {
663 return _protocolsToLengthEncodingNonAsciiBailout(protocols);
664 }
665 }
666 return bytes;
667 }
668
669 Uint8List _protocolsToLengthEncodingNonAsciiBailout(List<String> protocols) {
670 void addProtocol(List<int> outBytes, String protocol) {
671 var protocolBytes = UTF8.encode(protocol);
672 var len = protocolBytes.length;
673
674 if (len > 255) {
675 throw new ArgumentError(
676 'Length of protocol must be between 1 and 255 (was: $len)');
677 }
678 // Add length byte.
679 outBytes.add(len);
680
681 // Add protocol bytes.
682 outBytes.addAll(protocolBytes);
683 }
684
685 List<int> bytes = [];
686 addProtocol(bytes, protocols.last);
687 for (var i = 0; i < protocols.length -1; i++) {
688 addProtocol(bytes, protocols[i]);
689 }
690
691 if (bytes.length >= (1 << 15)) {
692 throw new ArgumentError(
693 'The maximum message length supported is 2^15-1.');
694 }
695
696 return new Uint8List.fromList(bytes);
697 }
698
699 void _addProtocolBytes(List<int> outBytes, String protocol) {
700 var protocolBytes = UTF8.encode(protocol);
701 var len = protocolBytes.length;
702
703 if (len > 255) {
704 throw new ArgumentError(
705 'Cannot support protocols with more than 255 characters');
706 }
707 outBytes.add(len);
708 outBytes.addAll(protocolBytes);
709 }
710
711 StreamSubscription listen(void onData(RawSocketEvent data), 526 StreamSubscription listen(void onData(RawSocketEvent data),
712 {Function onError, 527 {Function onError,
713 void onDone(), 528 void onDone(),
714 bool cancelOnError}) { 529 bool cancelOnError}) {
715 _sendWriteEvent(); 530 _sendWriteEvent();
716 return _stream.listen(onData, 531 return _stream.listen(onData,
717 onError: onError, 532 onError: onError,
718 onDone: onDone, 533 onDone: onDone,
719 cancelOnError: cancelOnError); 534 cancelOnError: cancelOnError);
720 } 535 }
721 536
722 static void _verifyFields(host, 537 static void _verifyFields(host,
723 int requestedPort, 538 int requestedPort,
724 String certificateName,
725 bool is_server, 539 bool is_server,
726 bool requestClientCertificate, 540 bool requestClientCertificate,
727 bool requireClientCertificate, 541 bool requireClientCertificate,
728 bool sendClientCertificate,
729 Function onBadCertificate) { 542 Function onBadCertificate) {
730 if (host is! String && host is! InternetAddress) { 543 if (host is! String && host is! InternetAddress) {
731 throw new ArgumentError("host is not a String or an InternetAddress"); 544 throw new ArgumentError("host is not a String or an InternetAddress");
732 } 545 }
733 if (requestedPort is! int) { 546 if (requestedPort is! int) {
734 throw new ArgumentError("requestedPort is not an int"); 547 throw new ArgumentError("requestedPort is not an int");
735 } 548 }
736 if (requestedPort < 0 || requestedPort > 65535) { 549 if (requestedPort < 0 || requestedPort > 65535) {
737 throw new ArgumentError("requestedPort is not in the range 0..65535"); 550 throw new ArgumentError("requestedPort is not in the range 0..65535");
738 } 551 }
739 if (certificateName != null && certificateName is! String) {
740 throw new ArgumentError("certificateName is not null or a String");
741 }
742 if (certificateName == null && is_server) {
743 throw new ArgumentError("certificateName is null on a server");
744 }
745 if (requestClientCertificate is! bool) { 552 if (requestClientCertificate is! bool) {
746 throw new ArgumentError("requestClientCertificate is not a bool"); 553 throw new ArgumentError("requestClientCertificate is not a bool");
747 } 554 }
748 if (requireClientCertificate is! bool) { 555 if (requireClientCertificate is! bool) {
749 throw new ArgumentError("requireClientCertificate is not a bool"); 556 throw new ArgumentError("requireClientCertificate is not a bool");
750 } 557 }
751 if (sendClientCertificate is! bool) {
752 throw new ArgumentError("sendClientCertificate is not a bool");
753 }
754 if (onBadCertificate != null && onBadCertificate is! Function) { 558 if (onBadCertificate != null && onBadCertificate is! Function) {
755 throw new ArgumentError("onBadCertificate is not null or a Function"); 559 throw new ArgumentError("onBadCertificate is not null or a Function");
756 } 560 }
757 } 561 }
758 562
759 int get port => _socket.port; 563 int get port => _socket.port;
760 564
761 InternetAddress get remoteAddress => _socket.remoteAddress; 565 InternetAddress get remoteAddress => _socket.remoteAddress;
762 566
763 int get remotePort => _socket.remotePort; 567 int get remotePort => _socket.remotePort;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 } 688 }
885 689
886 X509Certificate get peerCertificate => _secureFilter.peerCertificate; 690 X509Certificate get peerCertificate => _secureFilter.peerCertificate;
887 691
888 String get selectedProtocol => _selectedProtocol; 692 String get selectedProtocol => _selectedProtocol;
889 693
890 bool _onBadCertificateWrapper(X509Certificate certificate) { 694 bool _onBadCertificateWrapper(X509Certificate certificate) {
891 if (onBadCertificate == null) return false; 695 if (onBadCertificate == null) return false;
892 var result = onBadCertificate(certificate); 696 var result = onBadCertificate(certificate);
893 if (result is bool) return result; 697 if (result is bool) return result;
894 throw new ArgumentError( 698 throw new HandshakeException(
895 "onBadCertificate callback returned non-boolean $result"); 699 "onBadCertificate callback returned non-boolean $result");
896 } 700 }
897 701
898 bool setOption(SocketOption option, bool enabled) { 702 bool setOption(SocketOption option, bool enabled) {
899 if (_socket == null) return false; 703 if (_socket == null) return false;
900 return _socket.setOption(option, enabled); 704 return _socket.setOption(option, enabled);
901 } 705 }
902 706
903 void _eventDispatcher(RawSocketEvent event) { 707 void _eventDispatcher(RawSocketEvent event) {
904 try { 708 try {
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 } 1157 }
1354 } 1158 }
1355 } 1159 }
1356 } 1160 }
1357 1161
1358 1162
1359 abstract class _SecureFilter { 1163 abstract class _SecureFilter {
1360 external factory _SecureFilter(); 1164 external factory _SecureFilter();
1361 1165
1362 void connect(String hostName, 1166 void connect(String hostName,
1363 Uint8List addr, 1167 SecurityContext context,
1364 int port,
1365 bool is_server, 1168 bool is_server,
1366 String certificateName,
1367 bool requestClientCertificate, 1169 bool requestClientCertificate,
1368 bool requireClientCertificate, 1170 bool requireClientCertificate,
1369 bool sendClientCertificate, 1171 bool sendClientCertificate,
1370 Uint8List protocols); 1172 Uint8List protocols);
1371 void destroy(); 1173 void destroy();
1372 void handshake(); 1174 void handshake();
1373 String selectedProtocol(); 1175 String selectedProtocol();
1374 void rehandshake(); 1176 void rehandshake();
1375 void renegotiate(bool useSessionCache, 1177 void renegotiate(bool useSessionCache,
1376 bool requestClientCertificate, 1178 bool requestClientCertificate,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 /** 1231 /**
1430 * An exception that happens in the handshake phase of establishing 1232 * An exception that happens in the handshake phase of establishing
1431 * a secure network connection, when looking up or verifying a 1233 * a secure network connection, when looking up or verifying a
1432 * certificate. 1234 * certificate.
1433 */ 1235 */
1434 class CertificateException extends TlsException { 1236 class CertificateException extends TlsException {
1435 const CertificateException([String message = "", 1237 const CertificateException([String message = "",
1436 OSError osError = null]) 1238 OSError osError = null])
1437 : super._("CertificateException", message, osError); 1239 : super._("CertificateException", message, osError);
1438 } 1240 }
OLDNEW
« no previous file with comments | « sdk/lib/io/secure_server_socket.dart ('k') | sdk/lib/io/security_context.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698