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;
            }
        }
Beispiel #2
0
        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);
        }