private async Task ApplyClientCertificateSettings() { if (ClientCertificateOptions == ClientCertificateOption.Manual) { if (_clientCertificates != null && _clientCertificates.Count > 0) { X509Certificate2 clientCert = CertificateHelper.GetEligibleClientCertificate(_clientCertificates); if (clientCert == null) { return; } RTCertificate rtClientCert = await CertificateHelper.ConvertDotNetClientCertToWinRtClientCertAsync(clientCert).ConfigureAwait(false); if (rtClientCert == null) { throw new PlatformNotSupportedException(SR.Format(CultureInfo.InvariantCulture, SR.net_http_feature_UWPClientCertSupportRequiresCertInPersonalCertificateStore)); } _rtFilter.ClientCertificate = rtClientCert; } return; } else { X509Certificate2 clientCert = CertificateHelper.GetEligibleClientCertificate(); if (clientCert == null) { return; } // Unlike in the .Manual case above, the conversion to WinRT Certificate should always work; // so we just use an Assert. All the possible client certs were enumerated from that store and // filtered down to a single client cert. RTCertificate rtClientCert = await CertificateHelper.ConvertDotNetClientCertToWinRtClientCertAsync(clientCert).ConfigureAwait(false); Debug.Assert(rtClientCert != null); _rtFilter.ClientCertificate = rtClientCert; } }
private bool RTServerCertificateCallbackHelper( RTHttpRequestMessage requestMessage, RTCertificate cert, IReadOnlyList <RTCertificate> intermediateCerts, IReadOnlyList <RTChainValidationResult> certErrors) { // Convert WinRT certificate to .NET certificate. X509Certificate2 serverCert = CertificateHelper.ConvertPublicKeyCertificate(cert); // Create .NET X509Chain from the WinRT information. We need to rebuild the chain since WinRT only // gives us an array of intermediate certificates and not a X509Chain object. var serverChain = new X509Chain(); SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None; foreach (RTCertificate intermediateCert in intermediateCerts) { serverChain.ChainPolicy.ExtraStore.Add(CertificateHelper.ConvertPublicKeyCertificate(cert)); } serverChain.ChainPolicy.RevocationMode = X509RevocationMode.Online; // WinRT always checks revocation. serverChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; // Authenticate the remote party: (e.g. when operating in client mode, authenticate the server). serverChain.ChainPolicy.ApplicationPolicy.Add(s_serverAuthOid); if (!serverChain.Build(serverCert)) { sslPolicyErrors |= SslPolicyErrors.RemoteCertificateChainErrors; } // Determine name-mismatch error from the existing WinRT information since .NET X509Chain.Build does not // return that in the X509Chain.ChainStatus fields. foreach (RTChainValidationResult result in certErrors) { if (result == RTChainValidationResult.InvalidName) { sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch; break; } } // Get the .NET HttpRequestMessage we saved in the property bag of the WinRT HttpRequestMessage. HttpRequestMessage request = (HttpRequestMessage)requestMessage.Properties[RequestMessageLookupKey]; // Call the .NET callback. bool success = false; try { success = _serverCertificateCustomValidationCallback(request, serverCert, serverChain, sslPolicyErrors); } catch (Exception ex) { // Save the exception info. We will return it later via the SendAsync response processing. requestMessage.Properties.Add( SavedExceptionDispatchInfoLookupKey, ExceptionDispatchInfo.Capture(ex)); } finally { serverChain.Dispose(); serverCert.Dispose(); } return(success); }