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

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

Issue 11308271: Add built-in root certificates to dart:io SecureSocket. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add crash to Windows status (issue 7102) Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * SecureSocket provides a secure (SSL or TLS) client connection to a server. 6 * SecureSocket provides a secure (SSL or TLS) client connection to a server.
7 * The certificate provided by the server is checked 7 * The certificate provided by the server is checked
8 * using the certificate database provided in setCertificateDatabase. 8 * using the certificate database provided in setCertificateDatabase.
9 */ 9 */
10 abstract class SecureSocket implements Socket { 10 abstract class SecureSocket implements Socket {
11 /** 11 /**
12 * Constructs a new secure client socket and connect it to the given 12 * Constructs a new secure client socket and connect it to the given
13 * host on the given port. The returned socket is not yet connected 13 * host on the given port. The returned socket is not yet connected
14 * but ready for registration of callbacks. 14 * but ready for registration of callbacks.
15 */ 15 */
16 factory SecureSocket(String host, int port) => new _SecureSocket(host, port); 16 factory SecureSocket(String host, int port) => new _SecureSocket(host, port);
17 17
18 /** 18 /**
19 * Initializes the NSS library with the path to a certificate database 19 * Initializes the NSS library with the path to a certificate database
20 * containing root certificates for verifying certificate paths on 20 * containing root certificates for verifying certificate paths on
21 * client connections, and server certificates to provide on server 21 * client connections, and server certificates to provide on server
22 * connections. The password argument should be used when creating 22 * connections. The password argument should be used when creating
23 * secure server sockets, to allow the private key of the server 23 * secure server sockets, to allow the private key of the server
24 * certificate to be fetched. 24 * certificate to be fetched. If useBuiltinRoots is true (the default),
25 * then a built-in set of root certificates for trusted certificate
26 * authorities is merged with the certificates in the database.
27 *
28 * Examples:
29 * 1) Use only the builtin root certificates:
30 * SecureSocket.initialize(); or
31 *
32 * 2) Use a specified database and the builtin roots:
33 * SecureSocket.initialize(database: 'path/to/my/database',
34 * password: 'my_password');
35 *
36 * 3) Use a specified database, without builtin roots:
37 * SecureSocket.initialize(database: 'path/to/my/database',
38 * password: 'my_password'.
39 * useBuiltinRoots: false);
25 * 40 *
26 * The database should be an NSS certificate database directory 41 * The database should be an NSS certificate database directory
27 * containing a cert9.db file, not a cert8.db file. This version of 42 * containing a cert9.db file, not a cert8.db file. This version of
28 * the database can be created using the NSS certutil tool with "sql:" in 43 * the database can be created using the NSS certutil tool with "sql:" in
29 * front of the absolute path of the database directory, or setting the 44 * front of the absolute path of the database directory, or setting the
30 * environment variable NSS_DEFAULT_DB_TYPE to "sql". 45 * environment variable NSS_DEFAULT_DB_TYPE to "sql".
31 */ 46 */
32 external static void setCertificateDatabase(String certificateDatabase, 47 external static void initialize({String database,
33 [String password]); 48 String password,
49 bool useBuiltinRoots: true});
34 } 50 }
35 51
36 52
37 class _SecureSocket implements SecureSocket { 53 class _SecureSocket implements SecureSocket {
38 // Status states 54 // Status states
39 static final int NOT_CONNECTED = 200; 55 static final int NOT_CONNECTED = 200;
40 static final int HANDSHAKE = 201; 56 static final int HANDSHAKE = 201;
41 static final int CONNECTED = 202; 57 static final int CONNECTED = 202;
42 static final int CLOSED = 203; 58 static final int CLOSED = 203;
43 59
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 scheduledDataEvent.cancel(); 205 scheduledDataEvent.cancel();
190 } 206 }
191 _status = CLOSED; 207 _status = CLOSED;
192 } 208 }
193 } 209 }
194 210
195 void _closeWrite() => close(true); 211 void _closeWrite() => close(true);
196 212
197 List<int> read([int len]) { 213 List<int> read([int len]) {
198 if (_closedRead) { 214 if (_closedRead) {
199 throw new SocketException("Reading from a closed socket"); 215 throw new SocketIOException("Reading from a closed socket");
200 } 216 }
201 if (_status != CONNECTED) { 217 if (_status != CONNECTED) {
202 return new List<int>(0); 218 return new List<int>(0);
203 } 219 }
204 var buffer = _secureFilter.buffers[READ_PLAINTEXT]; 220 var buffer = _secureFilter.buffers[READ_PLAINTEXT];
205 _readEncryptedData(); 221 _readEncryptedData();
206 int toRead = buffer.length; 222 int toRead = buffer.length;
207 if (len != null) { 223 if (len != null) {
208 if (len is! int || len < 0) { 224 if (len is! int || len < 0) {
209 throw new ArgumentError( 225 throw new ArgumentError(
210 "Invalid len parameter in SecureSocket.read (len: $len)"); 226 "Invalid len parameter in SecureSocket.read (len: $len)");
211 } 227 }
212 if (len < toRead) { 228 if (len < toRead) {
213 toRead = len; 229 toRead = len;
214 } 230 }
215 } 231 }
216 List<int> result = buffer.data.getRange(buffer.start, toRead); 232 List<int> result = buffer.data.getRange(buffer.start, toRead);
217 buffer.advanceStart(toRead); 233 buffer.advanceStart(toRead);
218 _setHandlersAfterRead(); 234 _setHandlersAfterRead();
219 return result; 235 return result;
220 } 236 }
221 237
222 int readList(List<int> data, int offset, int bytes) { 238 int readList(List<int> data, int offset, int bytes) {
223 if (_closedRead) { 239 if (_closedRead) {
224 throw new SocketException("Reading from a closed socket"); 240 throw new SocketIOException("Reading from a closed socket");
225 } 241 }
226 if (offset < 0 || bytes < 0 || offset + bytes > data.length) { 242 if (offset < 0 || bytes < 0 || offset + bytes > data.length) {
227 throw new ArgumentError( 243 throw new ArgumentError(
228 "Invalid offset or bytes in SecureSocket.readList"); 244 "Invalid offset or bytes in SecureSocket.readList");
229 } 245 }
230 if (_status != CONNECTED && _status != CLOSED) { 246 if (_status != CONNECTED && _status != CLOSED) {
231 return 0; 247 return 0;
232 } 248 }
233 249
234 int bytesRead = 0; 250 int bytesRead = 0;
(...skipping 13 matching lines...) Expand all
248 264
249 _setHandlersAfterRead(); 265 _setHandlersAfterRead();
250 return bytesRead; 266 return bytesRead;
251 } 267 }
252 268
253 // Write the data to the socket, and flush it as much as possible 269 // Write the data to the socket, and flush it as much as possible
254 // until it would block. If the write would block, _writeEncryptedData sets 270 // until it would block. If the write would block, _writeEncryptedData sets
255 // up handlers to flush the pipeline when possible. 271 // up handlers to flush the pipeline when possible.
256 int writeList(List<int> data, int offset, int bytes) { 272 int writeList(List<int> data, int offset, int bytes) {
257 if (_closedWrite) { 273 if (_closedWrite) {
258 throw new SocketException("Writing to a closed socket"); 274 throw new SocketIOException("Writing to a closed socket");
259 } 275 }
260 if (_status != CONNECTED) return 0; 276 if (_status != CONNECTED) return 0;
261 var buffer = _secureFilter.buffers[WRITE_PLAINTEXT]; 277 var buffer = _secureFilter.buffers[WRITE_PLAINTEXT];
262 if (bytes > buffer.free) { 278 if (bytes > buffer.free) {
263 bytes = buffer.free; 279 bytes = buffer.free;
264 } 280 }
265 if (bytes > 0) { 281 if (bytes > 0) {
266 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); 282 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset);
267 buffer.length += bytes; 283 buffer.length += bytes;
268 } 284 }
(...skipping 22 matching lines...) Expand all
291 // We must be able to set onWrite from the onWrite callback. 307 // We must be able to set onWrite from the onWrite callback.
292 var handler = _socketWriteHandler; 308 var handler = _socketWriteHandler;
293 // Reset the one-shot handler. 309 // Reset the one-shot handler.
294 _socketWriteHandler = null; 310 _socketWriteHandler = null;
295 handler(); 311 handler();
296 } 312 }
297 } 313 }
298 314
299 void _secureDataHandler() { 315 void _secureDataHandler() {
300 if (_status == HANDSHAKE) { 316 if (_status == HANDSHAKE) {
301 _secureHandshake(); 317 try {
318 _secureHandshake();
319 } catch (e) { _reportError(e, "SecureSocket error"); }
302 } else { 320 } else {
303 _writeEncryptedData(); // TODO(whesse): Removing this causes a failure. 321 try {
304 _readEncryptedData(); 322 _writeEncryptedData(); // TODO(whesse): Removing this causes a failure.
323 _readEncryptedData();
324 } catch (e) { _reportError(e, "SecureSocket error"); }
305 if (!_filterReadEmpty) { 325 if (!_filterReadEmpty) {
306 // Call the onData event. 326 // Call the onData event.
307 if (scheduledDataEvent != null) { 327 if (scheduledDataEvent != null) {
308 scheduledDataEvent.cancel(); 328 scheduledDataEvent.cancel();
309 scheduledDataEvent = null; 329 scheduledDataEvent = null;
310 } 330 }
311 if (_socketDataHandler != null) { 331 if (_socketDataHandler != null) {
312 _socketDataHandler(); 332 _socketDataHandler();
313 } 333 }
314 } 334 }
315 } 335 }
316 } 336 }
317 337
318 void _secureErrorHandler(e) { 338 void _secureErrorHandler(e) {
319 _reportError(e, 'Error on underlying Socket'); 339 _reportError(e, 'Error on underlying Socket');
320 } 340 }
321 341
322 void _reportError(error, String message) { 342 void _reportError(error, String message) {
323 // TODO(whesse): Call _reportError from all internal functions that throw. 343 // TODO(whesse): Call _reportError from all internal functions that throw.
324 var e; 344 var e;
325 if (error is SocketIOException) { 345 if (error is SocketIOException) {
326 e = new SocketIOException('$message (${error.message})', error.osError); 346 e = new SocketIOException('$message (${error.message})', error.osError);
327 } else if (error is OSError) { 347 } else if (error is OSError) {
328 e = new SocketIOException(message, error); 348 e = new SocketIOException(message, error);
329 } else { 349 } else {
330 e = new SocketIOException('$message (${error.toString()})', null); 350 e = new SocketIOException('$message (${error.toString()})', null);
331 } 351 }
352 close(false);
332 bool reported = false; 353 bool reported = false;
333 if (_socketErrorHandler != null) { 354 if (_socketErrorHandler != null) {
334 reported = true; 355 reported = true;
335 _socketErrorHandler(e); 356 _socketErrorHandler(e);
336 } 357 }
337 if (_inputStream != null) { 358 if (_inputStream != null) {
338 reported = reported || _inputStream._onSocketError(e); 359 reported = reported || _inputStream._onSocketError(e);
339 } 360 }
340 if (_outputStream != null) { 361 if (_outputStream != null) {
341 reported = reported || _outputStream._onSocketError(e); 362 reported = reported || _outputStream._onSocketError(e);
342 } 363 }
343
344 if (!reported) throw e; 364 if (!reported) throw e;
345 } 365 }
346 366
347 void _secureCloseHandler() { 367 void _secureCloseHandler() {
348 _socketClosedRead = true; 368 _socketClosedRead = true;
349 if (_filterReadEmpty) { 369 if (_filterReadEmpty) {
350 _closedRead = true; 370 _closedRead = true;
351 _fireCloseEvent(); 371 _fireCloseEvent();
352 if (_socketClosedWrite) { 372 if (_socketClosedWrite) {
353 _secureFilter.destroy(); 373 _secureFilter.destroy();
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 bool is_server, 581 bool is_server,
562 String certificateName); 582 String certificateName);
563 void destroy(); 583 void destroy();
564 void handshake(); 584 void handshake();
565 void init(); 585 void init();
566 int processBuffer(int bufferIndex); 586 int processBuffer(int bufferIndex);
567 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); 587 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
568 588
569 List<_ExternalBuffer> get buffers; 589 List<_ExternalBuffer> get buffers;
570 } 590 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/io_patch.dart ('k') | tests/standalone/io/https_client_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698