// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. patch class SecureSocket { /* patch */ factory SecureSocket._(RawSecureSocket rawSocket) => new _SecureSocket(rawSocket); } patch class _SecureFilter { /* patch */ factory _SecureFilter() => new _SecureFilterImpl(); } patch class X509Certificate { /* patch */ factory X509Certificate._() => new _X509CertificateImpl(); } class _SecureSocket extends _Socket implements SecureSocket { _SecureSocket(RawSecureSocket raw) : super(raw); void set onBadCertificate(bool callback(X509Certificate certificate)) { if (_raw == null) { throw new StateError("onBadCertificate called on destroyed SecureSocket"); } _raw.onBadCertificate = callback; } void renegotiate({bool useSessionCache: true, bool requestClientCertificate: false, bool requireClientCertificate: false}) { _raw.renegotiate(useSessionCache: useSessionCache, requestClientCertificate: requestClientCertificate, requireClientCertificate: requireClientCertificate); } X509Certificate get peerCertificate { if (_raw == null) { throw new StateError("peerCertificate called on destroyed SecureSocket"); } return _raw.peerCertificate; } String get selectedProtocol { if (_raw == null) { throw new StateError("selectedProtocol called on destroyed SecureSocket"); } return _raw.selectedProtocol; } } /** * _SecureFilterImpl wraps a filter that encrypts and decrypts data travelling * over an encrypted socket. The filter also handles the handshaking * and certificate verification. * * The filter exposes its input and output buffers as Dart objects that * are backed by an external C array of bytes, so that both Dart code and * native code can access the same data. */ class _SecureFilterImpl extends NativeFieldWrapperClass1 implements _SecureFilter { // Performance is improved if a full buffer of plaintext fits // in the encrypted buffer, when encrypted. static final int SIZE = 8 * 1024; static final int ENCRYPTED_SIZE = 10 * 1024; _SecureFilterImpl() { buffers = new List<_ExternalBuffer>(_RawSecureSocket.NUM_BUFFERS); for (int i = 0; i < _RawSecureSocket.NUM_BUFFERS; ++i) { buffers[i] = new _ExternalBuffer(_RawSecureSocket._isBufferEncrypted(i) ? ENCRYPTED_SIZE : SIZE); } } void connect(String hostName, SecurityContext context, bool is_server, bool requestClientCertificate, bool requireClientCertificate, Uint8List protocols) native "SecureSocket_Connect"; void destroy() { buffers = null; _destroy(); } void _destroy() native "SecureSocket_Destroy"; void handshake() native "SecureSocket_Handshake"; String selectedProtocol() native "SecureSocket_GetSelectedProtocol"; void renegotiate(bool useSessionCache, bool requestClientCertificate, bool requireClientCertificate) native "SecureSocket_Renegotiate"; void init() native "SecureSocket_Init"; X509Certificate get peerCertificate native "SecureSocket_PeerCertificate"; void registerBadCertificateCallback(Function callback) native "SecureSocket_RegisterBadCertificateCallback"; void registerHandshakeCompleteCallback(Function handshakeCompleteHandler) native "SecureSocket_RegisterHandshakeCompleteCallback"; // This is a security issue, as it exposes a raw pointer to Dart code. int _pointer() native "SecureSocket_FilterPointer"; List<_ExternalBuffer> buffers; } patch class SecurityContext { /* patch */ factory SecurityContext() { return new _SecurityContext(); } /* patch */ static SecurityContext get defaultContext { return _SecurityContext.defaultContext; } } class _SecurityContext extends NativeFieldWrapperClass1 implements SecurityContext { _SecurityContext() { _createNativeContext(); } void _createNativeContext() native "SecurityContext_Allocate"; static final SecurityContext defaultContext = new _SecurityContext().._trustBuiltinRoots(); Future usePrivateKey(String keyFile, {String password}) { return (new File(keyFile)).readAsBytes().then((bytes) { usePrivateKeyAsBytes(bytes, password: password); }); } void usePrivateKeyAsBytes(List keyBytes, {String password}) native "SecurityContext_UsePrivateKeyAsBytes"; void setTrustedCertificates({String file, String directory}) native "SecurityContext_SetTrustedCertificates"; void useCertificateChain(String file) native "SecurityContext_UseCertificateChain"; void setClientAuthorities(String file) native "SecurityContext_SetClientAuthorities"; void setAlpnProtocols(List protocols, bool isServer) { Uint8List encodedProtocols = SecurityContext._protocolsToLengthEncoding(protocols); _setAlpnProtocols(encodedProtocols, isServer); } void _setAlpnProtocols(Uint8List protocols, bool isServer) native "SecurityContext_SetAlpnProtocols"; void _trustBuiltinRoots() native "SecurityContext_TrustBuiltinRoots"; } /** * _X509CertificateImpl wraps an X509 certificate object held by the BoringSSL * library. It exposes the fields of the certificate object. */ class _X509CertificateImpl extends NativeFieldWrapperClass1 implements X509Certificate { // The native field must be set manually on a new object, in native code. // This is done by WrappedX509 in secure_socket.cc. _X509CertificateImpl(); String get subject native "X509_Subject"; String get issuer native "X509_Issuer"; DateTime get startValidity { return new DateTime.fromMillisecondsSinceEpoch(_startValidity(), isUtc: true); } DateTime get endValidity { return new DateTime.fromMillisecondsSinceEpoch(_endValidity(), isUtc: true); } int _startValidity() native "X509_StartValidity"; int _endValidity() native "X509_EndValidity"; }