// // Extracts a remote certificate upon request. // private static X509Certificate2?GetRemoteCertificate( SafeDeleteContext?securityContext, bool retrieveChainCertificates, ref X509Chain?chain) { if (securityContext == null) { return(null); } X509Certificate2? result = null; SafeFreeCertContext?remoteContext = null; try { // SECPKG_ATTR_REMOTE_CERT_CONTEXT will not succeed before TLS handshake completes. Inside the handshake, // we need to use (more expensive) SECPKG_ATTR_REMOTE_CERT_CHAIN. That one may be unsupported on older // versions of windows. In that case, we have no option than to return null. // // We can use retrieveCollection to distinguish between in-handshake and after-handshake calls, because // the collection is retrieved for cert validation purposes after the handshake completes. if (retrieveChainCertificates) // handshake completed { SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CONTEXT(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext); } else // in handshake { SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CHAIN(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext); } if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { if (retrieveChainCertificates) { chain ??= new X509Chain(); UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext, chain.ChainPolicy.ExtraStore); } remoteContext.Dispose(); } } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Log.RemoteCertificate(result); } return(result); }
// // Extracts a remote certificate upon request. // internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateCollection) { remoteCertificateCollection = null; if (securityContext == null) { return(null); } if (GlobalLog.IsEnabled) { GlobalLog.Enter("CertificateValidationPal.Windows SecureChannel#" + LoggingHash.HashString(securityContext) + "::GetRemoteCertificate()"); } X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { remoteContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.SspiCli.ContextAttribute.RemoteCertificate) as SafeFreeCertContext; if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { remoteCertificateCollection = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); remoteContext.Dispose(); } } if (SecurityEventSource.Log.IsEnabled()) { SecurityEventSource.Log.RemoteCertificate(result == null ? "null" : result.ToString(true)); } if (GlobalLog.IsEnabled) { GlobalLog.Leave("CertificateValidationPal.Windows SecureChannel#" + LoggingHash.HashString(securityContext) + "::GetRemoteCertificate()", (result == null ? "null" : result.Subject)); } return(result); }
private static X509Certificate2?GetRemoteCertificate( SafeDeleteContext?securityContext, bool retrieveCollection, out X509Certificate2Collection?remoteCertificateCollection) { remoteCertificateCollection = null; if (securityContext == null) { return(null); } X509Certificate2? result = null; SafeFreeCertContext?remoteContext = null; try { // SECPKG_ATTR_REMOTE_CERT_CHAIN can be used even before the TLS handshake completes, which is necessary // in order to supply the certificate to the client cert selection callback. However, it is not available on // windows 7, so use the SECPKG_ATTR_REMOTE_CERT_CONTEXT as a fallback option. if (!SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CHAIN(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext)) { SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CONTEXT(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext); } if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { if (retrieveCollection) { remoteCertificateCollection = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); } remoteContext.Dispose(); } } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Log.RemoteCertificate(result); } return(result); }
private static X509Certificate2 GetRemoteCertificate( SafeDeleteContext securityContext, bool retrieveCollection, out X509Certificate2Collection remoteCertificateCollection) { remoteCertificateCollection = null; if (securityContext == null) { return(null); } if (NetEventSource.IsEnabled) { NetEventSource.Enter(securityContext); } X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { remoteContext = SSPIWrapper.QueryContextAttributes_SECPKG_ATTR_REMOTE_CERT_CONTEXT(GlobalSSPI.SSPISecureChannel, securityContext); if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { if (retrieveCollection) { remoteCertificateCollection = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); } remoteContext.Dispose(); } } if (NetEventSource.IsEnabled) { NetEventSource.Log.RemoteCertificate(result); NetEventSource.Exit(null, result, securityContext); } return(result); }
// // Extracts a remote certificate upon request. // internal override X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateStore) { remoteCertificateStore = null; if (securityContext == null) { return(null); } GlobalLog.Enter("SecureChannel#" + Logging.HashString(this) + "::RemoteCertificate{get;}"); X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { int errorCode = SSPIWrapper.QueryContextRemoteCertificate(GlobalSSPI.SSPISecureChannel, securityContext, out remoteContext); if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { remoteCertificateStore = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); remoteContext.Dispose(); } } if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_remote_certificate, (result == null ? "null" : result.ToString(true)))); } GlobalLog.Leave("SecureChannel#" + Logging.HashString(this) + "::RemoteCertificate{get;}", (result == null ? "null" : result.Subject)); return(result); }
// // Extracts a remote certificate upon request. // internal static X509Certificate2 GetRemoteCertificate(SafeDeleteContext securityContext, out X509Certificate2Collection remoteCertificateStore) { remoteCertificateStore = null; if (securityContext == null) { return(null); } GlobalLog.Enter("CertificateValidationPal.Windows SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()"); X509Certificate2 result = null; SafeFreeCertContext remoteContext = null; try { remoteContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, securityContext, Interop.Secur32.ContextAttribute.RemoteCertificate) as SafeFreeCertContext; if (remoteContext != null && !remoteContext.IsInvalid) { result = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null && !remoteContext.IsInvalid) { remoteCertificateStore = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(remoteContext); remoteContext.Dispose(); } } if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.Format(SR.net_log_remote_certificate, (result == null ? "null" : result.ToString(true)))); } GlobalLog.Leave("CertificateValidationPal.Windows SecureChannel#" + Logging.HashString(securityContext) + "::GetRemoteCertificate()", (result == null ? "null" : result.Subject)); return(result); }