diff options
author | monojenkins <jo.shields+jenkins@xamarin.com> | 2018-08-22 12:48:00 +0300 |
---|---|---|
committer | Alexander Köplinger <alex.koeplinger@outlook.com> | 2018-08-22 12:47:59 +0300 |
commit | a51f37f6c59d51ace1b09f66b016067465a8b29b (patch) | |
tree | bebb1024600e72c7c6a61dda812563d4a1dcabf1 /mcs | |
parent | 16dceddbb9f29214a7876b4339990ab3aae5b57c (diff) |
An implementation of the ChainStatus property for Btls. (#10216)
When we execute the certificate verification callback we just don't test for success and set status11. Now we get the error (if any) and map the error code to those defined by ChainStatusFlags and add it to a list of X509ChainStatus objects for that chain. Now when get_ChainStatus is called we convert that list to an array of X509ChainStatus and return it.
Diffstat (limited to 'mcs')
5 files changed, 109 insertions, 2 deletions
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs b/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs index 0db248b9912..d3d7e8f8a9b 100644 --- a/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs +++ b/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs @@ -33,6 +33,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using System.Net.Security; +using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Authentication; @@ -213,12 +214,96 @@ namespace Mono.Btls X509Chain chain, MonoBtlsX509StoreCtx storeCtx, bool success, ref MonoSslPolicyErrors errors, ref int status11) { + status11 = unchecked((int)0); if (!success) { errors = MonoSslPolicyErrors.RemoteCertificateChainErrors; - status11 = unchecked((int)0x800B010B); + var error = storeCtx.GetError(); + if (error != Mono.Btls.MonoBtlsX509Error.OK & + error != Mono.Btls.MonoBtlsX509Error.CRL_NOT_YET_VALID) { + chain.Impl.AddStatus(MapVerifyErrorToChainStatus(error)); + status11 = unchecked((int)0x800B010B); + } } } + internal static X509ChainStatusFlags MapVerifyErrorToChainStatus(MonoBtlsX509Error code) + { + switch (code) + { + case Mono.Btls.MonoBtlsX509Error.OK : + return X509ChainStatusFlags.NoError; + + case Mono.Btls.MonoBtlsX509Error.CERT_NOT_YET_VALID : + case Mono.Btls.MonoBtlsX509Error.CERT_HAS_EXPIRED: + case Mono.Btls.MonoBtlsX509Error.ERROR_IN_CERT_NOT_BEFORE_FIELD: + case Mono.Btls.MonoBtlsX509Error.ERROR_IN_CERT_NOT_AFTER_FIELD: + return X509ChainStatusFlags.NotTimeValid; + + case Mono.Btls.MonoBtlsX509Error.CERT_REVOKED: + return X509ChainStatusFlags.Revoked; + + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case Mono.Btls.MonoBtlsX509Error.CERT_SIGNATURE_FAILURE: + return X509ChainStatusFlags.NotSignatureValid; + + case Mono.Btls.MonoBtlsX509Error.CERT_UNTRUSTED: + case Mono.Btls.MonoBtlsX509Error.DEPTH_ZERO_SELF_SIGNED_CERT: + case Mono.Btls.MonoBtlsX509Error.SELF_SIGNED_CERT_IN_CHAIN: + return X509ChainStatusFlags.UntrustedRoot; + + case Mono.Btls.MonoBtlsX509Error.CRL_HAS_EXPIRED: + return X509ChainStatusFlags.OfflineRevocation; + + case Mono.Btls.MonoBtlsX509Error.CRL_NOT_YET_VALID: + case Mono.Btls.MonoBtlsX509Error.CRL_SIGNATURE_FAILURE: + case Mono.Btls.MonoBtlsX509Error.ERROR_IN_CRL_LAST_UPDATE_FIELD: + case Mono.Btls.MonoBtlsX509Error.ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case Mono.Btls.MonoBtlsX509Error.KEYUSAGE_NO_CRL_SIGN: + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_GET_CRL: + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_GET_CRL_ISSUER: + case Mono.Btls.MonoBtlsX509Error.UNHANDLED_CRITICAL_CRL_EXTENSION: + return X509ChainStatusFlags.RevocationStatusUnknown; + + case Mono.Btls.MonoBtlsX509Error.INVALID_EXTENSION: + return X509ChainStatusFlags.InvalidExtension; + + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_GET_ISSUER_CERT: + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + case Mono.Btls.MonoBtlsX509Error.UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return X509ChainStatusFlags.PartialChain; + + case Mono.Btls.MonoBtlsX509Error.INVALID_PURPOSE: + return X509ChainStatusFlags.NotValidForUsage; + + case Mono.Btls.MonoBtlsX509Error.INVALID_CA: + case Mono.Btls.MonoBtlsX509Error.INVALID_NON_CA: + case Mono.Btls.MonoBtlsX509Error.PATH_LENGTH_EXCEEDED: + case Mono.Btls.MonoBtlsX509Error.KEYUSAGE_NO_CERTSIGN: + case Mono.Btls.MonoBtlsX509Error.KEYUSAGE_NO_DIGITAL_SIGNATURE: + return X509ChainStatusFlags.InvalidBasicConstraints; + + case Mono.Btls.MonoBtlsX509Error.INVALID_POLICY_EXTENSION: + case Mono.Btls.MonoBtlsX509Error.NO_EXPLICIT_POLICY: + return X509ChainStatusFlags.InvalidPolicyConstraints; + + case Mono.Btls.MonoBtlsX509Error.CERT_REJECTED: + return X509ChainStatusFlags.ExplicitDistrust; + + case Mono.Btls.MonoBtlsX509Error.UNHANDLED_CRITICAL_EXTENSION: + return X509ChainStatusFlags.HasNotSupportedCriticalExtension; + + case Mono.Btls.MonoBtlsX509Error.CERT_CHAIN_TOO_LONG: + throw new CryptographicException(); + + case Mono.Btls.MonoBtlsX509Error.OUT_OF_MEM: + throw new OutOfMemoryException(); + + default: + throw new CryptographicException("Unrecognized X509VerifyStatusCode:" + code); + } + } + internal static void SetupCertificateStore (MonoBtlsX509Store store, MonoTlsSettings settings, bool server) { /* diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs index 9b8e82bb5e2..435efb36b13 100644 --- a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs @@ -142,6 +142,11 @@ namespace Mono.Btls return mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr); } + public int GetErrorDepth () + { + return mono_btls_x509_store_ctx_get_error_depth (Handle.DangerousGetHandle ()); + } + public MonoBtlsX509Exception GetException () { IntPtr error_string_ptr; diff --git a/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs b/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs index 13596686e85..a50a0ecf34d 100644 --- a/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs +++ b/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. #if SECURITY_DEP && MONO_FEATURE_BTLS using System; +using System.Collections.Generic; using System.Text; using System.Security; using System.Security.Cryptography; @@ -42,6 +43,7 @@ namespace Mono.Btls X509Certificate2Collection untrusted; X509Certificate2[] certificates; X509ChainPolicy policy; + List<X509ChainStatus> chainStatusList; internal X509ChainImplBtls (MonoBtlsX509Chain chain) { @@ -124,7 +126,16 @@ namespace Mono.Btls } public override X509ChainStatus[] ChainStatus { - get { throw new NotImplementedException (); } + get { + return chainStatusList.ToArray(); + } + } + + public override void AddStatus (X509ChainStatusFlags errorCode) + { + if (chainStatusList == null) + chainStatusList = new List<X509ChainStatus>(); + chainStatusList.Add (new X509ChainStatus(errorCode)); } public override bool Build (X509Certificate2 certificate) diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs index 2a4c9cf168b..c6e9d3fbee8 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImpl.cs @@ -59,6 +59,8 @@ namespace System.Security.Cryptography.X509Certificates public abstract bool Build (X509Certificate2 certificate); + public abstract void AddStatus (X509ChainStatusFlags errorCode); + public abstract void Reset (); public void Dispose () diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs index de9b1990e86..bd495699665 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs @@ -110,6 +110,10 @@ namespace System.Security.Cryptography.X509Certificates { // methods + public override void AddStatus (X509ChainStatusFlags error) + { + } + [MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")] public override bool Build (X509Certificate2 certificate) { |