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

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

Issue 11467004: Enable client certificates in SecureSocket and SecureServerSocket (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. 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. If sendClientCertificate is
15 * set to true, the socket will send a client certificate if one is
16 * requested by the server. If clientCertificate is the nickname of
17 * a certificate in the certificate database, that certificate will be sent.
18 * If clientCertificate is null, which is the usual use case, an
19 * appropriate certificate will be searched for in the database and
20 * sent automatically, based on what the server says it will accept.
15 */ 21 */
16 factory SecureSocket(String host, int port) => new _SecureSocket(host, port); 22 factory SecureSocket(String host,
23 int port,
24 {bool sendClientCertificate: false,
25 String certificateName}) {
26 return new _SecureSocket(host,
27 port,
28 certificateName,
29 is_server: false,
30 sendClientCertificate: sendClientCertificate);
31 }
17 32
18 /** 33 /**
19 * Install a handler for unverifiable certificates. The handler can inspect 34 * Install a handler for unverifiable certificates. The handler can inspect
20 * the certificate, and decide (or let the user decide) whether to accept 35 * the certificate, and decide (or let the user decide) whether to accept
21 * the connection or not. The callback should return true 36 * the connection or not. The callback should return true
22 * to continue the SecureSocket connection. 37 * to continue the SecureSocket connection.
23 */ 38 */
24 void set onBadCertificate(bool callback(X509Certificate certificate)); 39 void set onBadCertificate(bool callback(X509Certificate certificate));
25 40
41 /**
42 * Get the peerCertificate for a connected secure socket. For a server
43 * socket, this will return the client certificate, or null, if no
44 * client certificate was received. For a client socket, this
45 * will return the server's certificate.
46 */
47 X509Certificate get peerCertificate;
48
26 /** 49 /**
27 * Initializes the NSS library with the path to a certificate database 50 * Initializes the NSS library with the path to a certificate database
28 * containing root certificates for verifying certificate paths on 51 * containing root certificates for verifying certificate paths on
29 * client connections, and server certificates to provide on server 52 * client connections, and server certificates to provide on server
30 * connections. The password argument should be used when creating 53 * connections. The password argument should be used when creating
31 * secure server sockets, to allow the private key of the server 54 * secure server sockets, to allow the private key of the server
32 * certificate to be fetched. If useBuiltinRoots is true (the default), 55 * certificate to be fetched. If useBuiltinRoots is true (the default),
33 * then a built-in set of root certificates for trusted certificate 56 * then a built-in set of root certificates for trusted certificate
34 * authorities is merged with the certificates in the database. 57 * authorities is merged with the certificates in the database.
35 * 58 *
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 static final int CLOSED = 203; 105 static final int CLOSED = 203;
83 106
84 // Buffer identifiers. 107 // Buffer identifiers.
85 // These must agree with those in the native C++ implementation. 108 // These must agree with those in the native C++ implementation.
86 static final int READ_PLAINTEXT = 0; 109 static final int READ_PLAINTEXT = 0;
87 static final int WRITE_PLAINTEXT = 1; 110 static final int WRITE_PLAINTEXT = 1;
88 static final int READ_ENCRYPTED = 2; 111 static final int READ_ENCRYPTED = 2;
89 static final int WRITE_ENCRYPTED = 3; 112 static final int WRITE_ENCRYPTED = 3;
90 static final int NUM_BUFFERS = 4; 113 static final int NUM_BUFFERS = 4;
91 114
92 int _count = 0; 115 _SecureSocket(String this.host,
93 // Constructs a new secure client socket. 116 int requestedPort,
94 factory _SecureSocket(String host, int port) => 117 String this.certificateName,
95 new _SecureSocket.internal(host, port, false); 118 {bool this.is_server,
96 119 Socket this.socket,
97 // Constructs a new secure server socket, with the named server certificate. 120 bool this.requestClientCertificate: false,
98 factory _SecureSocket.server(String host, 121 bool this.requireClientCertificate: false,
99 int port, 122 bool this.sendClientCertificate: false})
100 Socket socket, 123 : secureFilter = new _SecureFilter() {
101 String certificateName) => 124 // Throw an ArgumentError if any field is invalid.
102 new _SecureSocket.internal(host, port, true, socket, certificateName); 125 _verifyFields();
103 126 if (socket == null) {
104 _SecureSocket.internal(String host, 127 socket = new Socket(host, requestedPort);
105 int port,
106 bool is_server,
107 [Socket socket,
108 String certificateName])
109 : _host = host,
110 _port = port,
111 _socket = socket,
112 _certificateName = certificateName,
113 _is_server = is_server,
114 _secureFilter = new _SecureFilter() {
115 if (_socket == null) {
116 _socket = new Socket(host, port);
117 } 128 }
118 _socket.onConnect = _secureConnectHandler; 129 socket.onConnect = _secureConnectHandler;
119 _socket.onData = _secureDataHandler; 130 socket.onData = _secureDataHandler;
120 _socket.onClosed = _secureCloseHandler; 131 socket.onClosed = _secureCloseHandler;
121 _socket.onError = _secureErrorHandler; 132 socket.onError = _secureErrorHandler;
122 _secureFilter.init(); 133 secureFilter.init();
123 _secureFilter.registerHandshakeCompleteCallback(_secureHandshakeCompleteHand ler); 134 secureFilter.registerHandshakeCompleteCallback(
135 _secureHandshakeCompleteHandler);
124 } 136 }
125 137
126 int get port => _socket.port; 138 void _verifyFields() {
139 if (host is! String) throw new ArgumentError(
140 "SecureSocket constructor: host is not a String");
141 assert(is_server is bool);
142 assert(socket == null || socket is Socket);
143 if (certificateName != null && certificateName is! String) {
144 throw new ArgumentError(
145 "SecureSocket constructor: certificateName is not null or a String");
146 }
147 if (certificateName == null && is_server) {
148 throw new ArgumentError(
149 "SecureSocket constructor: certificateName is null on a server");
150 }
151 if (requestClientCertificate is! bool) throw new ArgumentError(
Mads Ager (google) 2012/12/11 07:45:27 Please use curly braces when using multiple lines
Bill Hesse 2012/12/11 09:20:54 Done.
152 "SecureSocket constructor: requestClientCertificate is not a bool");
153 if (requireClientCertificate is! bool) throw new ArgumentError(
154 "SecureSocket constructor: requireClientCertificate is not a bool");
155 if (sendClientCertificate is! bool) throw new ArgumentError(
156 "SecureSocket constructor: sendClientCertificate is not a bool");
157 }
127 158
128 String get remoteHost => _socket.remoteHost; 159 int get port => socket.port;
129 160
130 int get remotePort => _socket.remotePort; 161 String get remoteHost => socket.remoteHost;
162
163 int get remotePort => socket.remotePort;
131 164
132 void set onClosed(void callback()) { 165 void set onClosed(void callback()) {
133 if (_inputStream != null && callback != null) { 166 if (_inputStream != null && callback != null) {
134 throw new StreamException( 167 throw new StreamException(
135 "Cannot set close handler when input stream is used"); 168 "Cannot set close handler when input stream is used");
136 } 169 }
137 _onClosed = callback; 170 _onClosed = callback;
138 } 171 }
139 172
140 void set _onClosed(void callback()) { 173 void set _onClosed(void callback()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 if (_outputStream != null && callback != null) { 206 if (_outputStream != null && callback != null) {
174 throw new StreamException( 207 throw new StreamException(
175 "Cannot set write handler when output stream is used"); 208 "Cannot set write handler when output stream is used");
176 } 209 }
177 _onWrite = callback; 210 _onWrite = callback;
178 } 211 }
179 212
180 void set _onWrite(void callback()) { 213 void set _onWrite(void callback()) {
181 _socketWriteHandler = callback; 214 _socketWriteHandler = callback;
182 // Reset the one-shot onWrite handler. 215 // Reset the one-shot onWrite handler.
183 _socket.onWrite = _secureWriteHandler; 216 socket.onWrite = _secureWriteHandler;
184 } 217 }
185 218
186 void set onBadCertificate(bool callback(X509Certificate certificate)) { 219 void set onBadCertificate(bool callback(X509Certificate certificate)) {
187 if (callback is! Function && callback != null) { 220 if (callback is! Function && callback != null) {
188 throw new SocketIOException( 221 throw new SocketIOException(
189 "Callback provided to onBadCertificate is not a function or null"); 222 "Callback provided to onBadCertificate is not a function or null");
190 } 223 }
191 _secureFilter.registerBadCertificateCallback(callback); 224 secureFilter.registerBadCertificateCallback(callback);
192 } 225 }
193 226
194 InputStream get inputStream { 227 InputStream get inputStream {
195 if (_inputStream == null) { 228 if (_inputStream == null) {
196 if (_socketDataHandler != null || _socketCloseHandler != null) { 229 if (_socketDataHandler != null || _socketCloseHandler != null) {
197 throw new StreamException( 230 throw new StreamException(
198 "Cannot get input stream when socket handlers are used"); 231 "Cannot get input stream when socket handlers are used");
199 } 232 }
200 _inputStream = new _SocketInputStream(this); 233 _inputStream = new _SocketInputStream(this);
201 } 234 }
(...skipping 14 matching lines...) Expand all
216 int available() { 249 int available() {
217 throw new UnimplementedError("SecureSocket.available not implemented yet"); 250 throw new UnimplementedError("SecureSocket.available not implemented yet");
218 } 251 }
219 252
220 void close([bool halfClose = false]) { 253 void close([bool halfClose = false]) {
221 if (_status == CLOSED) return; 254 if (_status == CLOSED) return;
222 if (halfClose) { 255 if (halfClose) {
223 _closedWrite = true; 256 _closedWrite = true;
224 _writeEncryptedData(); 257 _writeEncryptedData();
225 if (_filterWriteEmpty) { 258 if (_filterWriteEmpty) {
226 _socket.close(true); 259 socket.close(true);
227 _socketClosedWrite = true; 260 _socketClosedWrite = true;
228 if (_closedRead) { 261 if (_closedRead) {
229 close(false); 262 close(false);
230 } 263 }
231 } 264 }
232 } else { 265 } else {
233 _closedWrite = true; 266 _closedWrite = true;
234 _closedRead = true; 267 _closedRead = true;
235 _socket.close(false); 268 socket.close(false);
236 _socketClosedWrite = true; 269 _socketClosedWrite = true;
237 _socketClosedRead = true; 270 _socketClosedRead = true;
238 _secureFilter.destroy(); 271 secureFilter.destroy();
239 _secureFilter = null; 272 secureFilter = null;
240 if (scheduledDataEvent != null) { 273 if (scheduledDataEvent != null) {
241 scheduledDataEvent.cancel(); 274 scheduledDataEvent.cancel();
242 } 275 }
243 _status = CLOSED; 276 _status = CLOSED;
244 } 277 }
245 } 278 }
246 279
247 void _closeWrite() => close(true); 280 void _closeWrite() => close(true);
248 281
249 List<int> read([int len]) { 282 List<int> read([int len]) {
250 if (_closedRead) { 283 if (_closedRead) {
251 throw new SocketIOException("Reading from a closed socket"); 284 throw new SocketIOException("Reading from a closed socket");
252 } 285 }
253 if (_status != CONNECTED) { 286 if (_status != CONNECTED) {
254 return new List<int>(0); 287 return new List<int>(0);
255 } 288 }
256 var buffer = _secureFilter.buffers[READ_PLAINTEXT]; 289 var buffer = secureFilter.buffers[READ_PLAINTEXT];
257 _readEncryptedData(); 290 _readEncryptedData();
258 int toRead = buffer.length; 291 int toRead = buffer.length;
259 if (len != null) { 292 if (len != null) {
260 if (len is! int || len < 0) { 293 if (len is! int || len < 0) {
261 throw new ArgumentError( 294 throw new ArgumentError(
262 "Invalid len parameter in SecureSocket.read (len: $len)"); 295 "Invalid len parameter in SecureSocket.read (len: $len)");
263 } 296 }
264 if (len < toRead) { 297 if (len < toRead) {
265 toRead = len; 298 toRead = len;
266 } 299 }
(...skipping 10 matching lines...) Expand all
277 } 310 }
278 if (offset < 0 || bytes < 0 || offset + bytes > data.length) { 311 if (offset < 0 || bytes < 0 || offset + bytes > data.length) {
279 throw new ArgumentError( 312 throw new ArgumentError(
280 "Invalid offset or bytes in SecureSocket.readList"); 313 "Invalid offset or bytes in SecureSocket.readList");
281 } 314 }
282 if (_status != CONNECTED && _status != CLOSED) { 315 if (_status != CONNECTED && _status != CLOSED) {
283 return 0; 316 return 0;
284 } 317 }
285 318
286 int bytesRead = 0; 319 int bytesRead = 0;
287 var buffer = _secureFilter.buffers[READ_PLAINTEXT]; 320 var buffer = secureFilter.buffers[READ_PLAINTEXT];
288 // TODO(whesse): Currently this fails if the if is turned into a while loop. 321 // TODO(whesse): Currently this fails if the if is turned into a while loop.
289 // Fix it so that it can loop and read more than one buffer's worth of data. 322 // Fix it so that it can loop and read more than one buffer's worth of data.
290 if (bytes > bytesRead) { 323 if (bytes > bytesRead) {
291 _readEncryptedData(); 324 _readEncryptedData();
292 if (buffer.length > 0) { 325 if (buffer.length > 0) {
293 int toRead = min(bytes - bytesRead, buffer.length); 326 int toRead = min(bytes - bytesRead, buffer.length);
294 data.setRange(offset, toRead, buffer.data, buffer.start); 327 data.setRange(offset, toRead, buffer.data, buffer.start);
295 buffer.advanceStart(toRead); 328 buffer.advanceStart(toRead);
296 bytesRead += toRead; 329 bytesRead += toRead;
297 offset += toRead; 330 offset += toRead;
298 } 331 }
299 } 332 }
300 333
301 _setHandlersAfterRead(); 334 _setHandlersAfterRead();
302 return bytesRead; 335 return bytesRead;
303 } 336 }
304 337
305 // Write the data to the socket, and flush it as much as possible 338 // Write the data to the socket, and flush it as much as possible
306 // until it would block. If the write would block, _writeEncryptedData sets 339 // until it would block. If the write would block, _writeEncryptedData sets
307 // up handlers to flush the pipeline when possible. 340 // up handlers to flush the pipeline when possible.
308 int writeList(List<int> data, int offset, int bytes) { 341 int writeList(List<int> data, int offset, int bytes) {
309 if (_closedWrite) { 342 if (_closedWrite) {
310 throw new SocketIOException("Writing to a closed socket"); 343 throw new SocketIOException("Writing to a closed socket");
311 } 344 }
312 if (_status != CONNECTED) return 0; 345 if (_status != CONNECTED) return 0;
313 var buffer = _secureFilter.buffers[WRITE_PLAINTEXT]; 346 var buffer = secureFilter.buffers[WRITE_PLAINTEXT];
314 if (bytes > buffer.free) { 347 if (bytes > buffer.free) {
315 bytes = buffer.free; 348 bytes = buffer.free;
316 } 349 }
317 if (bytes > 0) { 350 if (bytes > 0) {
318 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); 351 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset);
319 buffer.length += bytes; 352 buffer.length += bytes;
320 } 353 }
321 _writeEncryptedData(); // Tries to flush all pipeline stages. 354 _writeEncryptedData(); // Tries to flush all pipeline stages.
322 return bytes; 355 return bytes;
323 } 356 }
324 357
358 X509Certificate get peerCertificate => secureFilter.peerCertificate;
359
325 void _secureConnectHandler() { 360 void _secureConnectHandler() {
326 _connectPending = true; 361 _connectPending = true;
327 _secureFilter.connect(_host, _port, _is_server, _certificateName); 362 secureFilter.connect(host,
363 port,
364 is_server,
365 certificateName,
366 requestClientCertificate || requireClientCertificate,
367 requireClientCertificate,
368 sendClientCertificate);
328 _status = HANDSHAKE; 369 _status = HANDSHAKE;
329 _secureHandshake(); 370 _secureHandshake();
330 } 371 }
331 372
332 void _secureWriteHandler() { 373 void _secureWriteHandler() {
333 _writeEncryptedData(); 374 _writeEncryptedData();
334 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) { 375 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) {
335 close(true); 376 close(true);
336 } 377 }
337 if (_status == HANDSHAKE) { 378 if (_status == HANDSHAKE) {
338 _secureHandshake(); 379 _secureHandshake();
339 } else if (_status == CONNECTED && 380 } else if (_status == CONNECTED &&
340 _socketWriteHandler != null && 381 _socketWriteHandler != null &&
341 _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) { 382 secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
342 // We must be able to set onWrite from the onWrite callback. 383 // We must be able to set onWrite from the onWrite callback.
343 var handler = _socketWriteHandler; 384 var handler = _socketWriteHandler;
344 // Reset the one-shot handler. 385 // Reset the one-shot handler.
345 _socketWriteHandler = null; 386 _socketWriteHandler = null;
346 handler(); 387 handler();
347 } 388 }
348 } 389 }
349 390
350 void _secureDataHandler() { 391 void _secureDataHandler() {
351 if (_status == HANDSHAKE) { 392 if (_status == HANDSHAKE) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 _socketCloseHandler(); 454 _socketCloseHandler();
414 } 455 }
415 if (_socketClosedWrite) { 456 if (_socketClosedWrite) {
416 close(false); 457 close(false);
417 } 458 }
418 } 459 }
419 } 460 }
420 461
421 void _secureHandshake() { 462 void _secureHandshake() {
422 _readEncryptedData(); 463 _readEncryptedData();
423 _secureFilter.handshake(); 464 secureFilter.handshake();
424 _writeEncryptedData(); 465 _writeEncryptedData();
425 if (_secureFilter.buffers[WRITE_ENCRYPTED].length > 0) { 466 if (secureFilter.buffers[WRITE_ENCRYPTED].length > 0) {
426 _socket.onWrite = _secureWriteHandler; 467 socket.onWrite = _secureWriteHandler;
427 } 468 }
428 } 469 }
429 470
430 void _secureHandshakeCompleteHandler() { 471 void _secureHandshakeCompleteHandler() {
431 _status = CONNECTED; 472 _status = CONNECTED;
432 if (_connectPending && _socketConnectHandler != null) { 473 if (_connectPending && _socketConnectHandler != null) {
433 _connectPending = false; 474 _connectPending = false;
434 _socketConnectHandler(); 475 _socketConnectHandler();
435 } 476 }
436 if (_socketWriteHandler != null) { 477 if (_socketWriteHandler != null) {
437 _socket.onWrite = _secureWriteHandler; 478 socket.onWrite = _secureWriteHandler;
438 } 479 }
439 } 480 }
440 481
441 // True if the underlying socket is closed, the filter has been emptied of 482 // True if the underlying socket is closed, the filter has been emptied of
442 // all data, and the close event has been fired. 483 // all data, and the close event has been fired.
443 get _closed => _socketClosed; 484 get _closed => _socketClosed;
444 485
445 void _readEncryptedData() { 486 void _readEncryptedData() {
446 // Read from the socket, and push it through the filter as far as 487 // Read from the socket, and push it through the filter as far as
447 // possible. 488 // possible.
448 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; 489 var encrypted = secureFilter.buffers[READ_ENCRYPTED];
449 var plaintext = _secureFilter.buffers[READ_PLAINTEXT]; 490 var plaintext = secureFilter.buffers[READ_PLAINTEXT];
450 bool progress = true; 491 bool progress = true;
451 while (progress) { 492 while (progress) {
452 progress = false; 493 progress = false;
453 // Do not try to read plaintext from the filter while handshaking. 494 // Do not try to read plaintext from the filter while handshaking.
454 if ((_status == CONNECTED) && plaintext.free > 0) { 495 if ((_status == CONNECTED) && plaintext.free > 0) {
455 int bytes = _secureFilter.processBuffer(READ_PLAINTEXT); 496 int bytes = secureFilter.processBuffer(READ_PLAINTEXT);
456 if (bytes > 0) { 497 if (bytes > 0) {
457 plaintext.length += bytes; 498 plaintext.length += bytes;
458 progress = true; 499 progress = true;
459 } 500 }
460 } 501 }
461 if (encrypted.length > 0) { 502 if (encrypted.length > 0) {
462 int bytes = _secureFilter.processBuffer(READ_ENCRYPTED); 503 int bytes = secureFilter.processBuffer(READ_ENCRYPTED);
463 if (bytes > 0) { 504 if (bytes > 0) {
464 encrypted.advanceStart(bytes); 505 encrypted.advanceStart(bytes);
465 progress = true; 506 progress = true;
466 } 507 }
467 } 508 }
468 if (!_socketClosedRead) { 509 if (!_socketClosedRead) {
469 int bytes = _socket.readList(encrypted.data, 510 int bytes = socket.readList(encrypted.data,
470 encrypted.start + encrypted.length, 511 encrypted.start + encrypted.length,
471 encrypted.free); 512 encrypted.free);
472 if (bytes > 0) { 513 if (bytes > 0) {
473 encrypted.length += bytes; 514 encrypted.length += bytes;
474 progress = true; 515 progress = true;
475 } 516 }
476 } 517 }
477 } 518 }
478 // If there is any data in any stages of the filter, there should 519 // If there is any data in any stages of the filter, there should
479 // be data in the plaintext buffer after this process. 520 // be data in the plaintext buffer after this process.
480 // TODO(whesse): Verify that this is true, and there can be no 521 // TODO(whesse): Verify that this is true, and there can be no
481 // partial encrypted block stuck in the secureFilter. 522 // partial encrypted block stuck in the secureFilter.
482 _filterReadEmpty = (plaintext.length == 0); 523 _filterReadEmpty = (plaintext.length == 0);
483 } 524 }
484 525
485 void _writeEncryptedData() { 526 void _writeEncryptedData() {
486 if (_socketClosedWrite) return; 527 if (_socketClosedWrite) return;
487 var encrypted = _secureFilter.buffers[WRITE_ENCRYPTED]; 528 var encrypted = secureFilter.buffers[WRITE_ENCRYPTED];
488 var plaintext = _secureFilter.buffers[WRITE_PLAINTEXT]; 529 var plaintext = secureFilter.buffers[WRITE_PLAINTEXT];
489 while (true) { 530 while (true) {
490 if (encrypted.length > 0) { 531 if (encrypted.length > 0) {
491 // Write from the filter to the socket. 532 // Write from the filter to the socket.
492 int bytes = _socket.writeList(encrypted.data, 533 int bytes = socket.writeList(encrypted.data,
493 encrypted.start, 534 encrypted.start,
494 encrypted.length); 535 encrypted.length);
495 if (bytes == 0) { 536 if (bytes == 0) {
496 // The socket has blocked while we have data to write. 537 // The socket has blocked while we have data to write.
497 // We must be notified when it becomes unblocked. 538 // We must be notified when it becomes unblocked.
498 _socket.onWrite = _secureWriteHandler; 539 socket.onWrite = _secureWriteHandler;
499 _filterWriteEmpty = false; 540 _filterWriteEmpty = false;
500 break; 541 break;
501 } 542 }
502 encrypted.advanceStart(bytes); 543 encrypted.advanceStart(bytes);
503 } else { 544 } else {
504 var plaintext = _secureFilter.buffers[WRITE_PLAINTEXT]; 545 var plaintext = secureFilter.buffers[WRITE_PLAINTEXT];
505 if (plaintext.length > 0) { 546 if (plaintext.length > 0) {
506 int plaintext_bytes = _secureFilter.processBuffer(WRITE_PLAINTEXT); 547 int plaintext_bytes = secureFilter.processBuffer(WRITE_PLAINTEXT);
507 plaintext.advanceStart(plaintext_bytes); 548 plaintext.advanceStart(plaintext_bytes);
508 } 549 }
509 int bytes = _secureFilter.processBuffer(WRITE_ENCRYPTED); 550 int bytes = secureFilter.processBuffer(WRITE_ENCRYPTED);
510 if (bytes <= 0) { 551 if (bytes <= 0) {
511 // We know the WRITE_ENCRYPTED buffer is empty, and the 552 // We know the WRITE_ENCRYPTED buffer is empty, and the
512 // filter wrote zero bytes to it, so the filter must be empty. 553 // filter wrote zero bytes to it, so the filter must be empty.
513 // Also, the WRITE_PLAINTEXT buffer must have been empty, or 554 // Also, the WRITE_PLAINTEXT buffer must have been empty, or
514 // it would have written to the filter. 555 // it would have written to the filter.
515 // TODO(whesse): Verify that the filter works this way. 556 // TODO(whesse): Verify that the filter works this way.
516 _filterWriteEmpty = true; 557 _filterWriteEmpty = true;
517 break; 558 break;
518 } 559 }
519 encrypted.length += bytes; 560 encrypted.length += bytes;
(...skipping 30 matching lines...) Expand all
550 // This can't be an else clause: the value of _filterReadEmpty changes. 591 // This can't be an else clause: the value of _filterReadEmpty changes.
551 // This must be asynchronous, because we are in a read or readList call. 592 // This must be asynchronous, because we are in a read or readList call.
552 new Timer(0, (_) => _secureCloseHandler()); 593 new Timer(0, (_) => _secureCloseHandler());
553 } 594 }
554 } 595 }
555 } 596 }
556 597
557 bool get _socketClosed => _closedRead; 598 bool get _socketClosed => _closedRead;
558 599
559 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. 600 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor.
560 Socket _socket; 601 Socket socket;
561 String _host; 602 final String host;
562 int _port; 603 final bool is_server;
563 bool _is_server; 604 final String certificateName;
564 String _certificateName; 605 final bool requestClientCertificate;
606 final bool requireClientCertificate;
607 final bool sendClientCertificate;
565 608
566 var _status = NOT_CONNECTED; 609 var _status = NOT_CONNECTED;
567 bool _socketClosedRead = false; // The network socket is closed for reading. 610 bool _socketClosedRead = false; // The network socket is closed for reading.
568 bool _socketClosedWrite = false; // The network socket is closed for writing. 611 bool _socketClosedWrite = false; // The network socket is closed for writing.
569 bool _closedRead = false; // The secure socket has fired an onClosed event. 612 bool _closedRead = false; // The secure socket has fired an onClosed event.
570 bool _closedWrite = false; // The secure socket has been closed for writing. 613 bool _closedWrite = false; // The secure socket has been closed for writing.
571 bool _filterReadEmpty = true; // There is no buffered data to read. 614 bool _filterReadEmpty = true; // There is no buffered data to read.
572 bool _filterWriteEmpty = true; // There is no buffered data to be written. 615 bool _filterWriteEmpty = true; // There is no buffered data to be written.
573 _SocketInputStream _inputStream; 616 _SocketInputStream _inputStream;
574 _SocketOutputStream _outputStream; 617 _SocketOutputStream _outputStream;
575 bool _connectPending = false; 618 bool _connectPending = false;
576 Function _socketConnectHandler; 619 Function _socketConnectHandler;
577 Function _socketWriteHandler; 620 Function _socketWriteHandler;
578 Function _socketDataHandler; 621 Function _socketDataHandler;
579 Function _socketErrorHandler; 622 Function _socketErrorHandler;
580 Function _socketCloseHandler; 623 Function _socketCloseHandler;
581 Timer scheduledDataEvent; 624 Timer scheduledDataEvent;
582 625
583 _SecureFilter _secureFilter; 626 _SecureFilter secureFilter;
584 } 627 }
585 628
586 629
587 class _ExternalBuffer { 630 class _ExternalBuffer {
588 static final int SIZE = 8 * 1024; 631 static final int SIZE = 8 * 1024;
589 _ExternalBuffer() : start = 0, length = 0; 632 _ExternalBuffer() : start = 0, length = 0;
590 633
591 // TODO(whesse): Consider making this a circular buffer. Only if it helps. 634 // TODO(whesse): Consider making this a circular buffer. Only if it helps.
592 void advanceStart(int numBytes) { 635 void advanceStart(int numBytes) {
593 start += numBytes; 636 start += numBytes;
(...skipping 10 matching lines...) Expand all
604 int length; 647 int length;
605 } 648 }
606 649
607 650
608 abstract class _SecureFilter { 651 abstract class _SecureFilter {
609 external factory _SecureFilter(); 652 external factory _SecureFilter();
610 653
611 void connect(String hostName, 654 void connect(String hostName,
612 int port, 655 int port,
613 bool is_server, 656 bool is_server,
614 String certificateName); 657 String certificateName,
658 bool requestClientCertificate,
659 bool requireClientCertificate,
660 bool sendClientCertificate);
615 void destroy(); 661 void destroy();
616 void handshake(); 662 void handshake();
617 void init(); 663 void init();
664 X509Certificate get peerCertificate;
618 int processBuffer(int bufferIndex); 665 int processBuffer(int bufferIndex);
619 void registerBadCertificateCallback(Function callback); 666 void registerBadCertificateCallback(Function callback);
620 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); 667 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
621 668
622 List<_ExternalBuffer> get buffers; 669 List<_ExternalBuffer> get buffers;
623 } 670 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698