| 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 | 
|    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  Loading... | 
|    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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|  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  Loading... | 
|  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 } | 
| OLD | NEW |