internal X509Certificate2 GetRemoteCertificate(out X509Certificate2Collection remoteCertificateStore) { remoteCertificateStore = null; if (this.m_SecurityContext == null) { return(null); } X509Certificate2 certificate = null; SafeFreeCertContext certContext = null; try { certContext = SSPIWrapper.QueryContextAttributes(GlobalSSPI.SSPISecureChannel, this.m_SecurityContext, ContextAttribute.RemoteCertificate) as SafeFreeCertContext; if ((certContext != null) && !certContext.IsInvalid) { certificate = new X509Certificate2(certContext.DangerousGetHandle()); } } finally { if (certContext != null) { remoteCertificateStore = UnmanagedCertificateContext.GetStore(certContext); certContext.Close(); } } if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.GetString("net_log_remote_certificate", new object[] { (certificate == null) ? "null" : certificate.ToString(true) })); } return(certificate); }
//This method extracts a remote certificate and chain upon request. private void ExtractRemoteCertificate() { SafeFreeCertContext remoteContext = null; this.remoteCertificate = null; this.remoteCertificateChain = null; try { remoteContext = ExtractCertificateHandle(ContextAttribute.RemoteCertificate); if (remoteContext != null && !remoteContext.IsInvalid) { this.remoteCertificateChain = UnmanagedCertificateContext.GetStore(remoteContext); this.remoteCertificate = new X509Certificate2(remoteContext.DangerousGetHandle()); } } finally { if (remoteContext != null) { remoteContext.Close(); } } }
private static void OnRequestSendingRequest(WinHttpRequestState state) { Debug.Assert(state != null, "OnRequestSendingRequest: state is null"); Debug.Assert(state.RequestHandle != null, "OnRequestSendingRequest: state.RequestHandle is null"); if (state.RequestMessage.RequestUri.Scheme != UriScheme.Https) { // Not SSL/TLS. return; } // Grab the channel binding token (CBT) information from the request handle and put it into // the TransportContext object. state.TransportContext.SetChannelBinding(state.RequestHandle); if (state.ServerCertificateValidationCallback != null) { IntPtr certHandle = IntPtr.Zero; uint certHandleSize = (uint)IntPtr.Size; if (!Interop.WinHttp.WinHttpQueryOption( state.RequestHandle, Interop.WinHttp.WINHTTP_OPTION_SERVER_CERT_CONTEXT, ref certHandle, ref certHandleSize)) { int lastError = Marshal.GetLastWin32Error(); WinHttpTraceHelper.Trace( "OnRequestSendingRequest: Error getting WINHTTP_OPTION_SERVER_CERT_CONTEXT, {0}", lastError); if (lastError == Interop.WinHttp.ERROR_WINHTTP_INCORRECT_HANDLE_STATE) { // Not yet an SSL/TLS connection. This occurs while connecting thru a proxy where the // CONNECT verb hasn't yet been processed due to the proxy requiring authentication. // We need to ignore this notification. Another notification will be sent once the final // connection thru the proxy is completed. return; } throw WinHttpException.CreateExceptionUsingError(lastError); } // Get any additional certificates sent from the remote server during the TLS/SSL handshake. X509Certificate2Collection remoteCertificateStore = UnmanagedCertificateContext.GetRemoteCertificatesFromStoreContext(certHandle); // Create a managed wrapper around the certificate handle. Since this results in duplicating // the handle, we will close the original handle after creating the wrapper. var serverCertificate = new X509Certificate2(certHandle); Interop.Crypt32.CertFreeCertificateContext(certHandle); X509Chain chain = null; SslPolicyErrors sslPolicyErrors; bool result = false; try { WinHttpCertificateHelper.BuildChain( serverCertificate, remoteCertificateStore, state.RequestMessage.RequestUri.Host, state.CheckCertificateRevocationList, out chain, out sslPolicyErrors); result = state.ServerCertificateValidationCallback( state.RequestMessage, serverCertificate, chain, sslPolicyErrors); } catch (Exception ex) { throw WinHttpException.CreateExceptionUsingError( (int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE, ex); } finally { if (chain != null) { chain.Dispose(); } serverCertificate.Dispose(); } if (!result) { throw WinHttpException.CreateExceptionUsingError( (int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE); } } }