public LegacySslStream(Stream innerStream, bool leaveInnerStreamOpen, SslStream owner, MonoTlsProvider provider, MonoTlsSettings settings) : base(innerStream, leaveInnerStreamOpen) { SslStream = owner; Provider = provider; certificateValidator = ChainValidationHelper.GetInternalValidator(provider, settings); }
internal static object GetDefaultValidator(object settings) { #if SECURITY_DEP return(ChainValidationHelper.GetDefaultValidator((MSI.MonoTlsSettings)settings)); #else throw new NotSupportedException(); #endif }
/* * Mono-specific version of 'userCertValidationCallbackWrapper'; we're called from ChainValidationHelper.ValidateChain() here. * * Since we're built without the PrebuiltSystem alias, we can't use 'SslPolicyErrors' here. This prevents us from creating a subclass of 'ChainValidationHelper' * as well as providing a custom 'ServerCertValidationCallback'. */ bool myUserCertValidationCallbackWrapper(ServerCertValidationCallback callback, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors) { m_RemoteCertificateOrBytes = certificate == null ? null : certificate.GetRawCertData(); if (callback == null) { if (!_SslState.RemoteCertRequired) { sslPolicyErrors &= ~MonoSslPolicyErrors.RemoteCertificateNotAvailable; } return(sslPolicyErrors == MonoSslPolicyErrors.None); } return(ChainValidationHelper.InvokeCallback(callback, this, certificate, chain, sslPolicyErrors)); }
internal SslStream(Stream innerStream, bool leaveInnerStreamOpen, EncryptionPolicy encryptionPolicy, MonoTlsSettings settings) : base(innerStream, leaveInnerStreamOpen) { if (encryptionPolicy != EncryptionPolicy.RequireEncryption && encryptionPolicy != EncryptionPolicy.AllowNoEncryption && encryptionPolicy != EncryptionPolicy.NoEncryption) { throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "EncryptionPolicy"), "encryptionPolicy"); } var validationHelper = ChainValidationHelper.CloneWithCallbackWrapper(ref settings, myUserCertValidationCallbackWrapper); LocalCertSelectionCallback selectionCallback = null; if (validationHelper.HasCertificateSelectionCallback) { selectionCallback = validationHelper.SelectClientCertificate; } _Configuration = new MyConfiguration(settings, this); _SslState = new SslState(innerStream, null, selectionCallback, encryptionPolicy, _Configuration); }
public LegacySslStream(Stream innerStream, bool leaveInnerStreamOpen, MonoTlsProvider provider, MonoTlsSettings settings) : base(innerStream, leaveInnerStreamOpen) { this.provider = provider; certificateValidator = ChainValidationHelper.GetDefaultValidator(provider, settings); }
bool CreateStream (HttpWebRequest request) { try { NetworkStream serverStream = new NetworkStream (socket, false); if (request.Address.Scheme == Uri.UriSchemeHttps) { ssl = true; EnsureSSLStreamAvailable (); if (!reused || nstream == null || nstream.GetType () != sslStream) { byte [] buffer = null; if (sPoint.UseConnect) { bool ok = CreateTunnel (request, sPoint.Address, serverStream, out buffer); if (!ok) return false; } #if SECURITY_DEP #if MONOTOUCH || MONODROID nstream = new HttpsClientStream (serverStream, request.ClientCertificates, request, buffer); #else object[] args = new object [4] { serverStream, request.ClientCertificates, request, buffer}; nstream = (Stream) Activator.CreateInstance (sslStream, args); #endif SslClientStream scs = (SslClientStream) nstream; var helper = new ChainValidationHelper (request); scs.ServerCertValidation2 += (certs) => helper.ValidateChain (request.Address.Host, certs); #endif certsAvailable = false; } // we also need to set ServicePoint.Certificate // and ServicePoint.ClientCertificate but this can // only be done later (after handshake - which is // done only after a read operation). } else { ssl = false; nstream = serverStream; } } catch (Exception) { if (!request.Aborted) status = WebExceptionStatus.ConnectFailure; return false; } return true; }
public override bool ValidateCertificate(ChainValidationHelper validator, string targetHost, bool serverMode, X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain, ref SslPolicyErrors errors, ref int status11) { var errorState = UnityTls.NativeInterface.unitytls_errorstate_create(); var unityTlsChainImpl = chain.Impl as X509ChainImplUnityTls; if (unityTlsChainImpl == null) { if (certificates == null || certificates.Count == 0) { errors |= SslPolicyErrors.RemoteCertificateNotAvailable; return(false); } if (wantsChain) { chain = SystemCertificateValidator.CreateX509Chain(certificates); } } else { var cert = UnityTls.NativeInterface.unitytls_x509list_get_x509(unityTlsChainImpl.NativeCertificateChain, (size_t)0, &errorState); if (cert.handle == UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE) { errors |= SslPolicyErrors.RemoteCertificateNotAvailable; return(false); } } // fixup targetHost name by removing port if (!string.IsNullOrEmpty(targetHost)) { var pos = targetHost.IndexOf(':'); if (pos > 0) { targetHost = targetHost.Substring(0, pos); } } // convert cert to native or extract from unityTlsChainImpl. var result = UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_NOT_DONE; UnityTls.unitytls_x509list *certificatesNative = null; try { // Things the validator provides that we might want to make use of here: //validator.Settings.CheckCertificateName // not used by mono? //validator.Settings.CheckCertificateRevocationStatus // not used by mono? //validator.Settings.CertificateValidationTime //validator.Settings.CertificateSearchPaths // currently only used by MonoBtlsProvider UnityTls.unitytls_x509list_ref certificatesNativeRef; if (unityTlsChainImpl == null) { certificatesNative = UnityTls.NativeInterface.unitytls_x509list_create(&errorState); CertHelper.AddCertificatesToNativeChain(certificatesNative, certificates, &errorState); certificatesNativeRef = UnityTls.NativeInterface.unitytls_x509list_get_ref(certificatesNative, &errorState); } else { certificatesNativeRef = unityTlsChainImpl.NativeCertificateChain; } var targetHostUtf8 = Encoding.UTF8.GetBytes(targetHost); if (validator.Settings.TrustAnchors != null) { UnityTls.unitytls_x509list *trustCAnative = null; try { trustCAnative = UnityTls.NativeInterface.unitytls_x509list_create(&errorState); CertHelper.AddCertificatesToNativeChain(trustCAnative, validator.Settings.TrustAnchors, &errorState); var trustCAnativeRef = UnityTls.NativeInterface.unitytls_x509list_get_ref(trustCAnative, &errorState); fixed(byte *targetHostUtf8Ptr = targetHostUtf8) { result = UnityTls.NativeInterface.unitytls_x509verify_explicit_ca(certificatesNativeRef, trustCAnativeRef, targetHostUtf8Ptr, (size_t)targetHostUtf8.Length, null, null, &errorState); } } finally { UnityTls.NativeInterface.unitytls_x509list_free(trustCAnative); } } else { fixed(byte *targetHostUtf8Ptr = targetHostUtf8) { result = UnityTls.NativeInterface.unitytls_x509verify_default_ca(certificatesNativeRef, targetHostUtf8Ptr, (size_t)targetHostUtf8.Length, null, null, &errorState); } } } finally { UnityTls.NativeInterface.unitytls_x509list_free(certificatesNative); } errors = UnityTlsConversions.VerifyResultToPolicyErrror(result); // There should be a status per certificate, but once again we're following closely the BTLS implementation // https://github.com/mono/mono/blob/1553889bc54f87060158febca7e6b8b9910975f8/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs#L180 // which also provides only a single status for the entire chain. // It is notoriously tricky to implement in OpenSSL to get a status for all invididual certificates without finishing the handshake in the process. // This is partially the reason why unitytls_x509verify_X doesn't expose it (TODO!) and likely the reason Mono's BTLS impl ignores this. unityTlsChainImpl?.AddStatus(UnityTlsConversions.VerifyResultToChainStatus(result)); return(result == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_SUCCESS && errorState.code == UnityTls.unitytls_error_code.UNITYTLS_SUCCESS); }