예제 #1
0
        private X509Certificate2 ConvertPublicKeyCertificate(RTCertificate cert)
        {
            // Convert Windows X509v2 cert to .NET X509v2 cert.
            RTIBuffer blob = cert.GetCertificateBlob();

            return(new X509Certificate2(blob.ToArray()));
        }
예제 #2
0
        private async Task ApplyClientCertificateSettings()
        {
            if (ClientCertificateOptions == ClientCertificateOption.Manual)
            {
                if (_clientCertificates != null && _clientCertificates.Count > 0)
                {
                    RTCertificate cert = await CertificateHelper.ConvertDotNetClientCertToWinRtClientCertAsync(_clientCertificates[0]);

                    if (cert == null)
                    {
                        throw new PlatformNotSupportedException(string.Format(CultureInfo.InvariantCulture,
                                                                              SR.net_http_feature_UWPClientCertSupportRequiresCertInPersonalCertificateStore));
                    }

                    _rtFilter.ClientCertificate = cert;
                }

                return;
            }

            // Get the certs that can be used for Client Authentication.
            var query = new RTCertificateQuery();
            var ekus  = query.EnhancedKeyUsages;

            ekus.Add(ClientAuthenticationOID);
            var clientCertificates = await RTCertificateStores.FindAllAsync(query).AsTask().ConfigureAwait(false);

            if (clientCertificates.Count > 0)
            {
                _rtFilter.ClientCertificate = clientCertificates[0];
            }
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
        {
            InterlockedCheckAndUpdateState(WebSocketState.Connecting, s_validConnectStates);
            CheckValidState(s_validConnectingStates);

            _messageWebSocket = new MessageWebSocket();
            foreach (var header in options.RequestHeaders)
            {
                _messageWebSocket.SetRequestHeader((string)header, options.RequestHeaders[(string)header]);
            }

            string cookies = options.Cookies == null ? null : options.Cookies.GetCookieHeader(uri);

            if (!string.IsNullOrEmpty(cookies))
            {
                _messageWebSocket.SetRequestHeader(HeaderNameCookie, cookies);
            }

            var websocketControl = _messageWebSocket.Control;

            foreach (var subProtocol in options.RequestedSubProtocols)
            {
                websocketControl.SupportedProtocols.Add(subProtocol);
            }

            if (options.ClientCertificates.Count > 0)
            {
                if (!MessageWebSocketClientCertificateSupported)
                {
                    throw new PlatformNotSupportedException(string.Format(CultureInfo.InvariantCulture,
                                                                          SR.net_WebSockets_UWPClientCertSupportRequiresWindows10GreaterThan1703));
                }

                X509Certificate2 dotNetClientCert = CertificateHelper.GetEligibleClientCertificate(options.ClientCertificates);
                if (dotNetClientCert != null)
                {
                    RTCertificate winRtClientCert = await CertificateHelper.ConvertDotNetClientCertToWinRtClientCertAsync(dotNetClientCert).ConfigureAwait(false);

                    if (winRtClientCert == null)
                    {
                        throw new PlatformNotSupportedException(string.Format(
                                                                    CultureInfo.InvariantCulture,
                                                                    SR.net_WebSockets_UWPClientCertSupportRequiresCertInPersonalCertificateStore));
                    }

                    websocketControl.ClientCertificate = winRtClientCert;
                }
            }

            // Try to opt into PartialMessage receive mode so that we can hand partial data back to the app as it arrives.
            // If the MessageWebSocketControl.ReceiveMode API surface is not available, the MessageWebSocket.MessageReceived
            // event will only get triggered when an entire WebSocket message has been received. This results in large memory
            // footprint and prevents "streaming" scenarios (e.g., WCF) from working properly.
            if (MessageWebSocketReceiveModeSupported)
            {
                // Always enable partial message receive mode if the WinRT API supports it.
                _messageWebSocket.Control.ReceiveMode = MessageWebSocketReceiveMode.PartialMessage;
            }

            try
            {
                _receiveAsyncBufferTcs             = new TaskCompletionSource <ArraySegment <byte> >();
                _closeWebSocketReceiveResultTcs    = new TaskCompletionSource <WebSocketReceiveResult>();
                _messageWebSocket.MessageReceived += OnMessageReceived;
                _messageWebSocket.Closed          += OnCloseReceived;
                await _messageWebSocket.ConnectAsync(uri).AsTask(cancellationToken).ConfigureAwait(false);

                _subProtocol   = _messageWebSocket.Information.Protocol;
                _messageWriter = new DataWriter(_messageWebSocket.OutputStream);
            }
            catch (Exception)
            {
                UpdateState(WebSocketState.Closed);
                throw;
            }

            UpdateState(WebSocketState.Open);
        }
예제 #5
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);
        }