private static void OnRequestSendRequestComplete(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestSendRequestComplete: state is null");
            Debug.Assert(state.LifecycleAwaitable != null, "OnRequestSendRequestComplete: LifecycleAwaitable is null");

            state.LifecycleAwaitable.SetResult(1);
        }
        public static void AddResponseCookiesToContainer(WinHttpRequestState state)
        {
            HttpRequestMessage request         = state.RequestMessage;
            SafeWinHttpHandle  requestHandle   = state.RequestHandle;
            CookieContainer    cookieContainer = state.Handler.CookieContainer;

            Debug.Assert(state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer);
            Debug.Assert(cookieContainer != null);

            // Get 'Set-Cookie' headers from response.
            char[] buffer = null;
            uint   index  = 0;
            string cookieHeader;

            while (WinHttpResponseParser.GetResponseHeader(
                       requestHandle, Interop.WinHttp.WINHTTP_QUERY_SET_COOKIE, ref buffer, ref index, out cookieHeader))
            {
                try
                {
                    cookieContainer.SetCookies(request.RequestUri, cookieHeader);
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(cookieContainer, $"Added cookie: {cookieHeader}");
                    }
                }
                catch (CookieException)
                {
                    // We ignore malformed cookies in the response.
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(cookieContainer, $"Ignoring invalid cookie: {cookieHeader}");
                    }
                }
            }
        }
        public static void WinHttpCallback(
            IntPtr handle,
            IntPtr context,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            WinHttpTraceHelper.TraceCallbackStatus("WinHttpCallback", handle, context, internetStatus);

            if (Environment.HasShutdownStarted)
            {
                WinHttpTraceHelper.Trace("WinHttpCallback: Environment.HasShutdownStarted returned True");
                return;
            }

            if (context == IntPtr.Zero)
            {
                return;
            }

            WinHttpRequestState state = WinHttpRequestState.FromIntPtr(context);

            Debug.Assert(state != null, "WinHttpCallback must have a non-null state object");

            RequestCallback(handle, state, internetStatus, statusInformation, statusInformationLength);
        }
        private static void OnRequestReceiveResponseHeadersComplete(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestReceiveResponseHeadersComplete: state is null");
            Debug.Assert(state.LifecycleAwaitable != null, "LifecycleAwaitable is null");

            state.LifecycleAwaitable.SetResult(1);
        }
Ejemplo n.º 5
0
        private void SetRequestHandleCredentialsOptions(WinHttpRequestState state)
        {
            // Set WinHTTP to send/prevent default credentials for either proxy or server auth.
            bool useDefaultCredentials = false;

            if (state.ServerCredentials == CredentialCache.DefaultCredentials)
            {
                useDefaultCredentials = true;
            }
            else if (state.WindowsProxyUsePolicy != WindowsProxyUsePolicy.DoNotUseProxy)
            {
                if (state.Proxy == null && _defaultProxyCredentials == CredentialCache.DefaultCredentials)
                {
                    useDefaultCredentials = true;
                }
                else if (state.Proxy != null && state.Proxy.Credentials == CredentialCache.DefaultCredentials)
                {
                    useDefaultCredentials = true;
                }
            }

            uint optionData = useDefaultCredentials ?
                              Interop.WinHttp.WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW :
                              Interop.WinHttp.WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH;

            SetWinHttpOption(state.RequestHandle, Interop.WinHttp.WINHTTP_OPTION_AUTOLOGON_POLICY, ref optionData);
        }
        public static void AddResponseCookiesToContainer(WinHttpRequestState state)
        {
            HttpRequestMessage request = state.RequestMessage;
            SafeWinHttpHandle requestHandle = state.RequestHandle;
            CookieContainer cookieContainer = state.Handler.CookieContainer;
            
            Debug.Assert(state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer);
            Debug.Assert(cookieContainer != null);

            // Get 'Set-Cookie' headers from response.
            List<string> cookieHeaders =
                WinHttpResponseParser.GetResponseHeaders(requestHandle, Interop.WinHttp.WINHTTP_QUERY_SET_COOKIE);
            WinHttpTraceHelper.Trace("WINHTTP_QUERY_SET_COOKIE");
            
            foreach (string cookieHeader in cookieHeaders)
            {
                WinHttpTraceHelper.Trace(cookieHeader);
                try
                {
                    cookieContainer.SetCookies(request.RequestUri, cookieHeader);
                    WinHttpTraceHelper.Trace(cookieHeader);
                }
                catch (CookieException)
                {
                    // We ignore malformed cookies in the response.
                    WinHttpTraceHelper.Trace("Ignoring invalid cookie: {0}", cookieHeader);
                }
            }            
        }
        public static void ResetCookieRequestHeaders(WinHttpRequestState state, Uri redirectUri)
        {
            SafeWinHttpHandle requestHandle = state.RequestHandle;
            
            Debug.Assert(state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer);
            
            // Clear cookies.
            if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                requestHandle,
                CookieHeaderNameWithColon,
                (uint)CookieHeaderNameWithColon.Length,
                Interop.WinHttp.WINHTTP_ADDREQ_FLAG_REPLACE))
            {
                int lastError = Marshal.GetLastWin32Error();
                if (lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)
                {
                    throw WinHttpException.CreateExceptionUsingError(lastError);
                }
            }

            // Re-add cookies. The GetCookieHeader() method will return the correct set of
            // cookies based on the redirectUri.
            string cookieHeader = GetCookieHeader(redirectUri, state.Handler.CookieContainer);
            if (!string.IsNullOrEmpty(cookieHeader))
            {
                if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                    requestHandle,
                    cookieHeader,
                    (uint)cookieHeader.Length,
                    Interop.WinHttp.WINHTTP_ADDREQ_FLAG_ADD))
                {
                    WinHttpException.ThrowExceptionUsingLastError();
                }
            }
        }
Ejemplo n.º 8
0
        private static void OnRequestReadComplete(WinHttpRequestState state, uint bytesRead)
        {
            Debug.Assert(state != null, "OnRequestReadComplete: state is null");
            Debug.Assert(state.TcsReadFromResponseStream != null, "TcsReadFromResponseStream is null");
            Debug.Assert(!state.TcsReadFromResponseStream.Task.IsCompleted, "TcsReadFromResponseStream.Task is completed");

            state.DisposeCtrReadFromResponseStream();

            // If we read to the end of the stream and we're using 'Content-Length' semantics on the response body,
            // then verify we read at least the number of bytes required.
            if (bytesRead == 0 &&
                state.ExpectedBytesToRead.HasValue &&
                state.CurrentBytesRead < state.ExpectedBytesToRead.Value)
            {
                state.TcsReadFromResponseStream.TrySetException(
                    new IOException(string.Format(
                                        SR.net_http_io_read_incomplete,
                                        state.ExpectedBytesToRead.Value,
                                        state.CurrentBytesRead)).InitializeStackTrace());
            }
            else
            {
                state.CurrentBytesRead += (long)bytesRead;
                state.TcsReadFromResponseStream.TrySetResult((int)bytesRead);
            }
        }
        public static void AddResponseCookiesToContainer(WinHttpRequestState state)
        {
            HttpRequestMessage request         = state.RequestMessage;
            SafeWinHttpHandle  requestHandle   = state.RequestHandle;
            CookieContainer    cookieContainer = state.Handler.CookieContainer;

            Debug.Assert(state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer);
            Debug.Assert(cookieContainer != null);

            // Get 'Set-Cookie' headers from response.
            List <string> cookieHeaders =
                WinHttpResponseParser.GetResponseHeaders(requestHandle, Interop.WinHttp.WINHTTP_QUERY_SET_COOKIE);

            WinHttpTraceHelper.Trace("WINHTTP_QUERY_SET_COOKIE");

            foreach (string cookieHeader in cookieHeaders)
            {
                WinHttpTraceHelper.Trace(cookieHeader);
                try
                {
                    cookieContainer.SetCookies(request.RequestUri, cookieHeader);
                    WinHttpTraceHelper.Trace(cookieHeader);
                }
                catch (CookieException)
                {
                    // We ignore malformed cookies in the response.
                    WinHttpTraceHelper.Trace("Ignoring invalid cookie: {0}", cookieHeader);
                }
            }
        }
Ejemplo n.º 10
0
        private static void OnRequestReceiveResponseHeadersComplete(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestReceiveResponseHeadersComplete: state is null");
            Debug.Assert(state.TcsReceiveResponseHeaders != null, "TcsReceiveResponseHeaders is null");
            Debug.Assert(!state.TcsReceiveResponseHeaders.Task.IsCompleted, "TcsReceiveResponseHeaders.Task is completed");

            state.TcsReceiveResponseHeaders.TrySetResult(true);
        }
Ejemplo n.º 11
0
        private static void OnRequestDataAvailable(WinHttpRequestState state, int bytesAvailable)
        {
            Debug.Assert(state != null, "OnRequestDataAvailable: state is null");
            Debug.Assert(state.TcsQueryDataAvailable != null, "TcsQueryDataAvailable is null");
            Debug.Assert(!state.TcsQueryDataAvailable.Task.IsCompleted, "TcsQueryDataAvailable.Task is completed");

            state.TcsQueryDataAvailable.TrySetResult(bytesAvailable);
        }
Ejemplo n.º 12
0
        private static void OnRequestSendRequestComplete(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestSendRequestComplete: state is null");
            Debug.Assert(state.TcsSendRequest != null, "OnRequestSendRequestComplete: TcsSendRequest is null");
            Debug.Assert(!state.TcsSendRequest.Task.IsCompleted, "OnRequestSendRequestComplete: TcsSendRequest.Task is completed");

            state.TcsSendRequest.TrySetResult(true);
        }
        private static void OnRequestWriteComplete(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestWriteComplete: state is null");
            Debug.Assert(state.TcsInternalWriteDataToRequestStream != null, "TcsInternalWriteDataToRequestStream is null");
            Debug.Assert(!state.TcsInternalWriteDataToRequestStream.Task.IsCompleted, "TcsInternalWriteDataToRequestStream.Task is completed");

            state.TcsInternalWriteDataToRequestStream.TrySetResult(true);
        }
Ejemplo n.º 14
0
        private static void OnRequestReadComplete(WinHttpRequestState state, uint bytesRead)
        {
            Debug.Assert(state != null, "OnRequestReadComplete: state is null");
            Debug.Assert(state.TcsReadFromResponseStream != null, "TcsReadFromResponseStream is null");
            Debug.Assert(!state.TcsReadFromResponseStream.Task.IsCompleted, "TcsReadFromResponseStream.Task is completed");

            state.TcsReadFromResponseStream.TrySetResult((int)bytesRead);
        }
Ejemplo n.º 15
0
        public void PreAuthenticateRequest(WinHttpRequestState state, uint proxyAuthScheme)
        {
            // Set proxy credentials if we have them.
            // If a proxy authentication challenge was responded to, reset
            // those credentials before each SendRequest, because the proxy
            // may require re-authentication after responding to a 401 or
            // to a redirect. If you don't, you can get into a
            // 407-401-407-401- loop.
            if (proxyAuthScheme != 0)
            {
                ICredentials proxyCredentials;
                Uri          proxyUri;
                if (state.Proxy != null)
                {
                    proxyCredentials = state.Proxy.Credentials;
                    proxyUri         = state.Proxy.GetProxy(state.RequestMessage.RequestUri);
                }
                else
                {
                    proxyCredentials = state.DefaultProxyCredentials;
                    proxyUri         = state.RequestMessage.RequestUri;
                }

                SetWinHttpCredential(
                    state.RequestHandle,
                    proxyCredentials,
                    proxyUri,
                    proxyAuthScheme,
                    Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);
            }

            // Apply pre-authentication headers for server authentication?
            if (state.PreAuthenticate)
            {
                uint authScheme;
                NetworkCredential serverCredentials;
                if (GetServerCredentialsFromCache(
                        state.RequestMessage.RequestUri,
                        out authScheme,
                        out serverCredentials))
                {
                    SetWinHttpCredential(
                        state.RequestHandle,
                        serverCredentials,
                        state.RequestMessage.RequestUri,
                        authScheme,
                        Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);
                    state.LastStatusCode = HttpStatusCode.Unauthorized; // Remember we already set the creds.
                }

                // No cached credential to use at this time. The request will first go out with no
                // 'Authorization' header. Later, if a 401 occurs, we will be able to cache the credential
                // since we will then know the proper auth scheme to use.
                //
                // TODO: Issue #2165. Adding logging to highlight the 'cache miss'.
            }
        }
Ejemplo n.º 16
0
        private static void RequestCallback(
            IntPtr handle,
            WinHttpRequestState state,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            try
            {
                switch (internetStatus)
                {
                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
                    OnRequestSendRequestComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
                    OnRequestReadComplete(state, statusInformationLength);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
                    OnRequestWriteComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
                    OnRequestReceiveResponseHeadersComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REDIRECT:
                    string redirectUriString = Marshal.PtrToStringUni(statusInformation);
                    var    redirectUri       = new Uri(redirectUriString);
                    OnRequestRedirect(state, redirectUri);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SENDING_REQUEST:
                    OnRequestSendingRequest(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
                    Debug.Assert(
                        statusInformationLength == Marshal.SizeOf <Interop.WinHttp.WINHTTP_ASYNC_RESULT>(),
                        "RequestCallback: statusInformationLength=" + statusInformationLength +
                        " must be sizeof(WINHTTP_ASYNC_RESULT)=" + Marshal.SizeOf <Interop.WinHttp.WINHTTP_ASYNC_RESULT>());

                    var asyncResult = Marshal.PtrToStructure <Interop.WinHttp.WINHTTP_ASYNC_RESULT>(statusInformation);
                    OnRequestError(state, asyncResult);
                    return;

                default:
                    return;
                }
            }
            catch (Exception ex)
            {
                Interop.WinHttp.WinHttpCloseHandle(handle);
                state.SavedException = ex;
            }
        }
        private static void OnRequestHandleClosing(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestSendRequestComplete: state is null");

            // This is the last notification callback that WinHTTP will send. Therefore, we can
            // now explicitly dispose the state object which will free its corresponding GCHandle.
            // This will then allow the state object to be garbage collected.
            state.Dispose();
        }
Ejemplo n.º 18
0
        internal WinHttpRequestStream(WinHttpRequestState state, WinHttpChunkMode chunkedMode)
        {
            _state       = state;
            _chunkedMode = chunkedMode;

            // Take copy of handle from state.
            // The state's request handle will be set to null once the response stream starts.
            _requestHandle = _state.RequestHandle;
        }
Ejemplo n.º 19
0
        private static void RequestCallback(
            IntPtr handle,
            WinHttpRequestState state,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            try
            {
                switch (internetStatus)
                {
                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
                        OnRequestSendRequestComplete(state);
                        return;
                        
                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
                        OnRequestReadComplete(state, statusInformationLength);
                        return;
                        
                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
                        OnRequestWriteComplete(state);
                        return;
                        
                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
                        OnRequestReceiveResponseHeadersComplete(state);
                        return;

                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REDIRECT:
                        string redirectUriString = Marshal.PtrToStringUni(statusInformation);
                        var redirectUri = new Uri(redirectUriString);
                        OnRequestRedirect(state, redirectUri);
                        return;

                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SENDING_REQUEST:
                        OnRequestSendingRequest(state);
                        return;

                    case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
                        Debug.Assert(
                            statusInformationLength == Marshal.SizeOf<Interop.WinHttp.WINHTTP_ASYNC_RESULT>(),
                            "RequestCallback: statusInformationLength=" + statusInformationLength +
                            " must be sizeof(WINHTTP_ASYNC_RESULT)=" + Marshal.SizeOf<Interop.WinHttp.WINHTTP_ASYNC_RESULT>());

                        var asyncResult = Marshal.PtrToStructure<Interop.WinHttp.WINHTTP_ASYNC_RESULT>(statusInformation);
                        OnRequestError(state, asyncResult);
                        return;

                    default:
                        return;
                }
            }
            catch (Exception ex)
            {
                Interop.WinHttp.WinHttpCloseHandle(handle);
                state.SavedException = ex;
            }
        }
Ejemplo n.º 20
0
        protected override Task <HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
#endif
        {
            if (request == null)
            {
                throw new ArgumentNullException("request", SR.net_http_handler_norequest);
            }

            // Check for invalid combinations of properties.
            if (_proxy != null && _windowsProxyUsePolicy != WindowsProxyUsePolicy.UseCustomProxy)
            {
                throw new InvalidOperationException(SR.net_http_invalid_proxyusepolicy);
            }

            if (_windowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy && _proxy == null)
            {
                throw new InvalidOperationException(SR.net_http_invalid_proxy);
            }

            if (_cookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer &&
                _cookieContainer == null)
            {
                throw new InvalidOperationException(SR.net_http_invalid_cookiecontainer);
            }

            CheckDisposed();

            SetOperationStarted();

            TaskCompletionSource <HttpResponseMessage> tcs = new TaskCompletionSource <HttpResponseMessage>();

            // Create state object and save current values of handler settings.
            var state = new WinHttpRequestState();

            state.Tcs = tcs;
            state.CancellationToken = cancellationToken;
            state.RequestMessage    = request;
            state.Handler           = this;
            state.CheckCertificateRevocationList      = _checkCertificateRevocationList;
            state.ServerCertificateValidationCallback = _serverCertificateValidationCallback;
            state.WindowsProxyUsePolicy = _windowsProxyUsePolicy;
            state.Proxy                   = _proxy;
            state.ServerCredentials       = _serverCredentials;
            state.DefaultProxyCredentials = _defaultProxyCredentials;
            state.PreAuthenticate         = _preAuthenticate;

            Task.Factory.StartNew(
                s => ((WinHttpRequestState)s).Handler.StartRequest(s),
                state,
                CancellationToken.None,
                TaskCreationOptions.DenyChildAttach,
                TaskScheduler.Default);

            return(tcs.Task);
        }
Ejemplo n.º 21
0
 private void SetRequestHandleOptions(WinHttpRequestState state)
 {
     SetRequestHandleProxyOptions(state);
     SetRequestHandleDecompressionOptions(state.RequestHandle);
     SetRequestHandleRedirectionOptions(state.RequestHandle);
     SetRequestHandleCookieOptions(state.RequestHandle);
     SetRequestHandleTlsOptions(state.RequestHandle);
     SetRequestHandleClientCertificateOptions(state.RequestHandle, state.RequestMessage.RequestUri);
     SetRequestHandleCredentialsOptions(state);
     SetRequestHandleBufferingOptions(state.RequestHandle);
 }
Ejemplo n.º 22
0
        private async Task InternalSendRequestBodyAsync(WinHttpRequestState state, bool chunkedModeForSend)
        {
            using (var requestStream = new WinHttpRequestStream(state, chunkedModeForSend))
            {
                await state.RequestMessage.Content.CopyToAsync(
                    requestStream,
                    state.TransportContext).ConfigureAwait(false);

                await requestStream.EndUploadAsync(state.CancellationToken).ConfigureAwait(false);
            }
        }
Ejemplo n.º 23
0
        private Task <bool> InternalReceiveResponseHeadersAsync(WinHttpRequestState state)
        {
            state.TcsReceiveResponseHeaders = new TaskCompletionSource <bool>();

            lock (state.Lock)
            {
                if (!Interop.WinHttp.WinHttpReceiveResponse(state.RequestHandle, IntPtr.Zero))
                {
                    throw WinHttpException.CreateExceptionUsingLastError();
                }
            }

            return(state.TcsReceiveResponseHeaders.Task);
        }
        private static void ResetAuthRequestHeaders(WinHttpRequestState state)
        {
            const string      AuthHeaderNameWithColon = "Authorization:";
            SafeWinHttpHandle requestHandle           = state.RequestHandle;

            // Clear auth headers.
            if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                    requestHandle,
                    AuthHeaderNameWithColon,
                    (uint)AuthHeaderNameWithColon.Length,
                    Interop.WinHttp.WINHTTP_ADDREQ_FLAG_REPLACE))
            {
                int lastError = Marshal.GetLastWin32Error();
                if (lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)
                {
                    throw WinHttpException.CreateExceptionUsingError(lastError, "WINHTTP_CALLBACK_STATUS_REDIRECT/WinHttpAddRequestHeaders");
                }
            }
        }
Ejemplo n.º 25
0
 private void HandleAsyncException(WinHttpRequestState state, Exception ex)
 {
     if (state.CancellationToken.IsCancellationRequested)
     {
         // If the exception was due to the cancellation token being canceled, throw cancellation exception.
         state.Tcs.TrySetCanceled(state.CancellationToken);
     }
     else if (ex is WinHttpException || ex is IOException)
     {
         // Wrap expected exceptions as HttpRequestExceptions since this is considered an error during
         // execution. All other exception types, including ArgumentExceptions and ProtocolViolationExceptions
         // are 'unexpected' or caused by user error and should not be wrapped.
         state.Tcs.TrySetException(new HttpRequestException(SR.net_http_client_execution_error, ex));
     }
     else
     {
         state.Tcs.TrySetException(ex);
     }
 }
Ejemplo n.º 26
0
        private static void OnRequestRedirect(WinHttpRequestState state, Uri redirectUri)
        {
            Debug.Assert(state != null, "OnRequestRedirect: state is null");
            Debug.Assert(state.Handler != null, "OnRequestRedirect: state.Handler is null");
            Debug.Assert(state.RequestMessage != null, "OnRequestRedirect: state.RequestMessage is null");
            Debug.Assert(redirectUri != null, "OnRequestRedirect: redirectUri is null");

            // If we're manually handling cookies, we need to reset them based on the new URI.
            if (state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer)
            {
                // Add any cookies that may have arrived with redirect response.
                WinHttpCookieContainerAdapter.AddResponseCookiesToContainer(state);

                // Reset cookie request headers based on redirectUri.
                WinHttpCookieContainerAdapter.ResetCookieRequestHeaders(state, redirectUri);
            }

            state.RequestMessage.RequestUri = redirectUri;

            // Redirection to a new uri may require a new connection through a potentially different proxy.
            // If so, we will need to respond to additional 407 proxy auth demands and re-attach any
            // proxy credentials. The ProcessResponse() method looks at the state.LastStatusCode
            // before attaching proxy credentials and marking the HTTP request to be re-submitted.
            // So we need to reset the LastStatusCode remembered. Otherwise, it will see additional 407
            // responses as an indication that proxy auth failed and won't retry the HTTP request.
            if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
            {
                state.LastStatusCode = 0;
            }

            // For security reasons, we drop the server credential if it is a
            // NetworkCredential.  But we allow credentials in a CredentialCache
            // since they are specifically tied to URI's.
            if (!(state.ServerCredentials is CredentialCache))
            {
                state.ServerCredentials = null;
            }

            // Similarly, we need to clear any Auth headers that were added to the request manually or
            // through the default headers.
            ResetAuthRequestHeaders(state);
        }
        private static void OnRequestReadComplete(WinHttpRequestState state, uint bytesRead)
        {
            Debug.Assert(state != null, "OnRequestReadComplete: state is null");

            // If we read to the end of the stream and we're using 'Content-Length' semantics on the response body,
            // then verify we read at least the number of bytes required.
            if (bytesRead == 0 &&
                state.ExpectedBytesToRead.HasValue &&
                state.CurrentBytesRead < state.ExpectedBytesToRead.Value)
            {
                state.LifecycleAwaitable.SetException(new IOException(string.Format(
                                                                          SR.net_http_io_read_incomplete,
                                                                          state.ExpectedBytesToRead.Value,
                                                                          state.CurrentBytesRead)));
            }
            else
            {
                state.CurrentBytesRead += (long)bytesRead;
                state.LifecycleAwaitable.SetResult((int)bytesRead);
            }
        }
Ejemplo n.º 28
0
        private Task <bool> InternalSendRequestAsync(WinHttpRequestState state)
        {
            state.TcsSendRequest = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            lock (state.Lock)
            {
                if (!Interop.WinHttp.WinHttpSendRequest(
                        state.RequestHandle,
                        null,
                        0,
                        IntPtr.Zero,
                        0,
                        0,
                        state.ToIntPtr()))
                {
                    WinHttpException.ThrowExceptionUsingLastError();
                }
            }

            return(state.TcsSendRequest.Task);
        }
Ejemplo n.º 29
0
        public static void ResetCookieRequestHeaders(WinHttpRequestState state, Uri redirectUri)
        {
            SafeWinHttpHandle?requestHandle = state.RequestHandle;

            Debug.Assert(state.Handler != null);
            Debug.Assert(state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer);
            Debug.Assert(state.Handler.CookieContainer != null);
            Debug.Assert(requestHandle != null);

            // Clear cookies.
            if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                    requestHandle,
                    CookieHeaderNameWithColon,
                    (uint)CookieHeaderNameWithColon.Length,
                    Interop.WinHttp.WINHTTP_ADDREQ_FLAG_REPLACE))
            {
                int lastError = Marshal.GetLastWin32Error();
                if (lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)
                {
                    throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpAddRequestHeaders));
                }
            }

            // Re-add cookies. The GetCookieHeader() method will return the correct set of
            // cookies based on the redirectUri.
            string?cookieHeader = GetCookieHeader(redirectUri, state.Handler.CookieContainer);

            if (!string.IsNullOrEmpty(cookieHeader))
            {
                if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                        requestHandle,
                        cookieHeader,
                        (uint)cookieHeader.Length,
                        Interop.WinHttp.WINHTTP_ADDREQ_FLAG_ADD))
                {
                    WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpAddRequestHeaders));
                }
            }
        }
Ejemplo n.º 30
0
        public static void WinHttpCallback(
            IntPtr handle,
            IntPtr context,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            bool invokeCallback = false;

            if (Environment.HasShutdownStarted)
            {
                return;
            }

            if (context == IntPtr.Zero)
            {
                return;
            }

            WinHttpRequestState state = WinHttpRequestState.FromIntPtr(context);

            if (state != null &&
                state.RequestHandle != null &&
                !state.RequestHandle.IsInvalid &&
                state.RequestHandle.DangerousGetHandle() == handle)
            {
                invokeCallback = true;
            }

            WinHttpTraceHelper.TraceCallbackStatus("WinHttpCallback", handle, invokeCallback, internetStatus);

            if (invokeCallback)
            {
                RequestCallback(handle, state, internetStatus, statusInformation, statusInformationLength);
            }
        }
Ejemplo n.º 31
0
        private static void OnRequestReceiveResponseHeadersComplete(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestReceiveResponseHeadersComplete: state is null");
            Debug.Assert(state.TcsReceiveResponseHeaders != null, "TcsReceiveResponseHeaders is null");
            Debug.Assert(!state.TcsReceiveResponseHeaders.Task.IsCompleted, "TcsReceiveResponseHeaders.Task is completed");

            state.TcsReceiveResponseHeaders.TrySetResult(true);
        }
Ejemplo n.º 32
0
 private static void OnRequestReadComplete(WinHttpRequestState state, uint bytesRead)
 {
     Debug.Assert(state != null, "OnRequestReadComplete: state is null");
     Debug.Assert(state.TcsReadFromResponseStream != null, "TcsReadFromResponseStream is null");
     Debug.Assert(!state.TcsReadFromResponseStream.Task.IsCompleted, "TcsReadFromResponseStream.Task is completed");
     
     state.TcsReadFromResponseStream.TrySetResult((int)bytesRead);
 }
Ejemplo n.º 33
0
 private static void OnRequestWriteComplete(WinHttpRequestState state)
 {
     Debug.Assert(state != null, "OnRequestWriteComplete: state is null");
     Debug.Assert(state.TcsInternalWriteDataToRequestStream != null, "TcsInternalWriteDataToRequestStream is null");
     Debug.Assert(!state.TcsInternalWriteDataToRequestStream.Task.IsCompleted, "TcsInternalWriteDataToRequestStream.Task is completed");
     
     state.TcsInternalWriteDataToRequestStream.TrySetResult(true);
 }
Ejemplo n.º 34
0
        private void SetRequestHandleProxyOptions(WinHttpRequestState state)
        {
            // We've already set the proxy on the session handle if we're using no proxy or default proxy settings.
            // We only need to change it on the request handle if we have a specific IWebProxy or need to manually
            // implement Wininet-style auto proxy detection.
            if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy ||
                state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinInetProxy)
            {
                var proxyInfo = new Interop.WinHttp.WINHTTP_PROXY_INFO();
                bool updateProxySettings = false;
                Uri uri = state.RequestMessage.RequestUri;

                try
                {
                    if (state.Proxy != null)
                    {
                        Debug.Assert(state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy);
                        updateProxySettings = true;
                        if (state.Proxy.IsBypassed(uri))
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
                        }
                        else
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                            Uri proxyUri = state.Proxy.GetProxy(uri);
                            string proxyString = proxyUri.Scheme + "://" + proxyUri.Authority;
                            proxyInfo.Proxy = Marshal.StringToHGlobalUni(proxyString);
                        }
                    }
                    else if (_proxyHelper != null && _proxyHelper.AutoSettingsUsed)
                    {
                        if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo))
                        {
                            updateProxySettings = true;
                        }
                    }

                    if (updateProxySettings)
                    {
                        GCHandle pinnedHandle = GCHandle.Alloc(proxyInfo, GCHandleType.Pinned);

                        try
                        {
                            SetWinHttpOption(
                                state.RequestHandle,
                                Interop.WinHttp.WINHTTP_OPTION_PROXY,
                                pinnedHandle.AddrOfPinnedObject(),
                                (uint)Marshal.SizeOf(proxyInfo));
                        }
                        finally
                        {
                            pinnedHandle.Free();
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(proxyInfo.Proxy);
                    Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
                }
            }
        }
Ejemplo n.º 35
0
 private static void OnRequestSendRequestComplete(WinHttpRequestState state)
 {
     Debug.Assert(state != null, "OnRequestSendRequestComplete: state is null");
     Debug.Assert(state.TcsSendRequest != null, "OnRequestSendRequestComplete: TcsSendRequest is null");
     Debug.Assert(!state.TcsSendRequest.Task.IsCompleted, "OnRequestSendRequestComplete: TcsSendRequest.Task is completed");
     
     state.TcsSendRequest.TrySetResult(true);
 }
Ejemplo n.º 36
0
        private Task<bool> InternalReceiveResponseHeadersAsync(WinHttpRequestState state)
        {
            state.TcsReceiveResponseHeaders =
                new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            
            lock (state.Lock)
            {
                if (!Interop.WinHttp.WinHttpReceiveResponse(state.RequestHandle, IntPtr.Zero))
                {
                    throw WinHttpException.CreateExceptionUsingLastError();
                }
            }

            return state.TcsReceiveResponseHeaders.Task;
        }
Ejemplo n.º 37
0
 private void SetRequestHandleOptions(WinHttpRequestState state)
 {
     SetRequestHandleProxyOptions(state);
     SetRequestHandleDecompressionOptions(state.RequestHandle);
     SetRequestHandleRedirectionOptions(state.RequestHandle);
     SetRequestHandleCookieOptions(state.RequestHandle);
     SetRequestHandleTlsOptions(state.RequestHandle);
     SetRequestHandleClientCertificateOptions(state.RequestHandle, state.RequestMessage.RequestUri);
     SetRequestHandleCredentialsOptions(state);
     SetRequestHandleBufferingOptions(state.RequestHandle);
     SetRequestHandleHttp2Options(state.RequestHandle, state.RequestMessage.Version);
 }
Ejemplo n.º 38
0
        private static void OnRequestError(WinHttpRequestState state, Interop.WinHttp.WINHTTP_ASYNC_RESULT asyncResult)
        {
            WinHttpTraceHelper.TraceAsyncError("OnRequestError", asyncResult);
            
            Debug.Assert(state != null, "OnRequestError: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)asyncResult.dwError);

            switch ((uint)asyncResult.dwResult.ToInt32())
            {
                case Interop.WinHttp.API_SEND_REQUEST:
                    state.TcsSendRequest.TrySetException(innerException);
                    break;
                    
                case Interop.WinHttp.API_RECEIVE_RESPONSE:
                    if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_RESEND_REQUEST)
                    {
                        state.RetryRequest = true;
                        state.TcsReceiveResponseHeaders.TrySetResult(false);
                    }
                    else if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
                    {
                        // WinHttp will automatically drop any client SSL certificates that we
                        // have pre-set into the request handle including the NULL certificate
                        // (which means we have no certs to send). For security reasons, we don't
                        // allow the certificate to be re-applied. But we need to tell WinHttp
                        // explicitly that we don't have any certificate to send.
                        WinHttpHandler.SetNoClientCertificate(state.RequestHandle);
                        state.RetryRequest = true;
                        state.TcsReceiveResponseHeaders.TrySetResult(false);
                    }
                    else if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
                    {
                        state.TcsReceiveResponseHeaders.TrySetCanceled(state.CancellationToken);
                    }
                    else
                    {
                        state.TcsReceiveResponseHeaders.TrySetException(innerException);
                    }
                    break;

                case Interop.WinHttp.API_READ_DATA:
                    if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
                    {
                        // TODO: Issue #2165. We need to pass in the cancellation token from the
                        // user's ReadAsync() call into the TrySetCanceled().
                        Debug.WriteLine("RequestCallback: API_READ_DATA - ERROR_WINHTTP_OPERATION_CANCELLED");
                        state.TcsReadFromResponseStream.TrySetCanceled();
                    }
                    else
                    {
                        state.TcsReadFromResponseStream.TrySetException(
                            new IOException(SR.net_http_io_read, innerException));
                    }
                    break;

                case Interop.WinHttp.API_WRITE_DATA:
                    if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
                    {
                        // TODO: Issue #2165. We need to pass in the cancellation token from the
                        // user's WriteAsync() call into the TrySetCanceled().
                        Debug.WriteLine("RequestCallback: API_WRITE_DATA - ERROR_WINHTTP_OPERATION_CANCELLED");
                        state.TcsInternalWriteDataToRequestStream.TrySetCanceled();
                    }
                    else
                    {
                        state.TcsInternalWriteDataToRequestStream.TrySetException(
                            new IOException(SR.net_http_io_write, innerException));
                    }
                    break;

                default:
                    Debug.Fail(
                        "OnRequestError: Result (" + asyncResult.dwResult + ") is not expected.",
                        "Error code: " + asyncResult.dwError + " (" + innerException.Message + ")");
                    break;
            }
        }
Ejemplo n.º 39
0
 internal WinHttpResponseStream(SafeWinHttpHandle requestHandle, WinHttpRequestState state)
 {
     _state = state;
     _requestHandle = requestHandle;
 }
Ejemplo n.º 40
0
 private async Task InternalSendRequestBodyAsync(WinHttpRequestState state, bool chunkedModeForSend)
 {
     using (var requestStream = new WinHttpRequestStream(state, chunkedModeForSend))
     {
         await state.RequestMessage.Content.CopyToAsync(
             requestStream,
             state.TransportContext).ConfigureAwait(false);
         await requestStream.EndUploadAsync(state.CancellationToken).ConfigureAwait(false);
     }
 }
Ejemplo n.º 41
0
        private RendezvousAwaitable<int> InternalReceiveResponseHeadersAsync(WinHttpRequestState state)
        {
            lock (state.Lock)
            {
                if (!Interop.WinHttp.WinHttpReceiveResponse(state.RequestHandle, IntPtr.Zero))
                {
                    throw WinHttpException.CreateExceptionUsingLastError();
                }
            }

            return state.LifecycleAwaitable;
        }
Ejemplo n.º 42
0
        private RendezvousAwaitable<int> InternalSendRequestAsync(WinHttpRequestState state)
        {
            lock (state.Lock)
            {
                state.Pin();
                if (!Interop.WinHttp.WinHttpSendRequest(
                    state.RequestHandle,
                    null,
                    0,
                    IntPtr.Zero,
                    0,
                    0,
                    state.ToIntPtr()))
                {
                    // Dispose (which will unpin) the state object. Since this failed, WinHTTP won't associate
                    // our context value (state object) to the request handle. And thus we won't get HANDLE_CLOSING
                    // notifications which would normally cause the state object to be unpinned and disposed.
                    state.Dispose();
                    WinHttpException.ThrowExceptionUsingLastError();
                }
            }

            return state.LifecycleAwaitable;
        }
Ejemplo n.º 43
0
 private void HandleAsyncException(WinHttpRequestState state, Exception ex)
 {
     if (state.CancellationToken.IsCancellationRequested)
     {
         // If the exception was due to the cancellation token being canceled, throw cancellation exception.
         state.Tcs.TrySetCanceled(state.CancellationToken);
     }
     else if (ex is WinHttpException || ex is IOException)
     {
         // Wrap expected exceptions as HttpRequestExceptions since this is considered an error during 
         // execution. All other exception types, including ArgumentExceptions and ProtocolViolationExceptions
         // are 'unexpected' or caused by user error and should not be wrapped.
         state.Tcs.TrySetException(new HttpRequestException(SR.net_http_client_execution_error, ex));
     }
     else
     {
         state.Tcs.TrySetException(ex);
     }
 }
Ejemplo n.º 44
0
 private void SetRequestHandleCredentialsOptions(WinHttpRequestState state)
 {
     // By default, WinHTTP sets the default credentials policy such that it automatically sends default credentials
     // (current user's logged on Windows credentials) to a proxy when needed (407 response). It only sends
     // default credentials to a server (401 response) if the server is considered to be on the Intranet.
     // WinHttpHandler uses a more granual opt-in model for using default credentials that can be different between
     // proxy and server credentials. It will explicitly allow default credentials to be sent at a later stage in
     // the request processing (after getting a 401/407 response) when the proxy or server credential is set as
     // CredentialCache.DefaultNetworkCredential. For now, we set the policy to prevent any default credentials
     // from being automatically sent until we get a 401/407 response.
     _authHelper.ChangeDefaultCredentialsPolicy(
         state.RequestHandle,
         Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER,
         allowDefaultCredentials:false);
 }
Ejemplo n.º 45
0
        private static void OnRequestRedirect(WinHttpRequestState state, Uri redirectUri)
        {
            const string EmptyCookieHeader = "Cookie:";

            Debug.Assert(state != null, "OnRequestRedirect: state is null");
            Debug.Assert(redirectUri != null, "OnRequestRedirect: redirectUri is null");
            Debug.Assert(state.TcsReceiveResponseHeaders != null, "TcsReceiveResponseHeaders is null");
            Debug.Assert(!state.TcsReceiveResponseHeaders.Task.IsCompleted, "TcsReceiveResponseHeaders.Task is completed");

            // If we're manually handling cookies, we need to reset them based on the new URI.
            if (state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer)
            {
                // Clear cookies.
                if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                    state.RequestHandle,
                    EmptyCookieHeader,
                    (uint)EmptyCookieHeader.Length,
                    Interop.WinHttp.WINHTTP_ADDREQ_FLAG_REPLACE))
                {
                    int lastError = Marshal.GetLastWin32Error();
                    if (lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)
                    {
                        throw WinHttpException.CreateExceptionUsingError(lastError);
                    }
                }

                // Re-add cookies. The GetCookieHeader() method will return the correct set of
                // cookies based on the redirectUri.
                string cookieHeader = WinHttpHandler.GetCookieHeader(redirectUri, state.Handler.CookieContainer);
                if (!string.IsNullOrEmpty(cookieHeader))
                {
                    if (!Interop.WinHttp.WinHttpAddRequestHeaders(
                        state.RequestHandle,
                        cookieHeader,
                        (uint)cookieHeader.Length,
                        Interop.WinHttp.WINHTTP_ADDREQ_FLAG_ADD))
                    {
                        WinHttpException.ThrowExceptionUsingLastError();
                    }
                }
            }

            state.RequestMessage.RequestUri = redirectUri;
            
            // Redirection to a new uri may require a new connection through a potentially different proxy.
            // If so, we will need to respond to additional 407 proxy auth demands and re-attach any
            // proxy credentials. The ProcessResponse() method looks at the state.LastStatusCode
            // before attaching proxy credentials and marking the HTTP request to be re-submitted.
            // So we need to reset the LastStatusCode remembered. Otherwise, it will see additional 407
            // responses as an indication that proxy auth failed and won't retry the HTTP request.
            if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
            {
                state.LastStatusCode = 0;
            }

            // For security reasons, we drop the server credential if it is a 
            // NetworkCredential.  But we allow credentials in a CredentialCache
            // since they are specifically tied to URI's.
            if (!(state.ServerCredentials is CredentialCache))
            {
                state.ServerCredentials = null;
            }
        }
Ejemplo n.º 46
0
        private void SetRequestHandleProxyOptions(WinHttpRequestState state)
        {
            // We've already set the proxy on the session handle if we're using no proxy or default proxy settings.
            // We only need to change it on the request handle if we have a specific IWebProxy or need to manually
            // implement Wininet-style auto proxy detection.
            if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy ||
                state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinInetProxy)
            {
                var  proxyInfo           = new Interop.WinHttp.WINHTTP_PROXY_INFO();
                bool updateProxySettings = false;
                Uri  uri = state.RequestMessage.RequestUri;

                try
                {
                    if (state.Proxy != null)
                    {
                        Debug.Assert(state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy);
                        updateProxySettings = true;
                        if (state.Proxy.IsBypassed(uri))
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
                        }
                        else
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                            Uri    proxyUri    = state.Proxy.GetProxy(uri);
                            string proxyString = string.Format(
                                CultureInfo.InvariantCulture,
                                "{0}://{1}",
                                proxyUri.Scheme,
                                proxyUri.Authority);
                            proxyInfo.Proxy = Marshal.StringToHGlobalUni(proxyString);
                        }
                    }
                    else if (_proxyHelper != null && _proxyHelper.AutoSettingsUsed)
                    {
                        updateProxySettings = true;
                        _proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo);
                    }

                    if (updateProxySettings)
                    {
                        GCHandle pinnedHandle = GCHandle.Alloc(proxyInfo, GCHandleType.Pinned);

                        try
                        {
                            SetWinHttpOption(
                                state.RequestHandle,
                                Interop.WinHttp.WINHTTP_OPTION_PROXY,
                                pinnedHandle.AddrOfPinnedObject(),
                                (uint)Marshal.SizeOf(proxyInfo));
                        }
                        finally
                        {
                            pinnedHandle.Free();
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(proxyInfo.Proxy);
                    Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
                }
            }
        }
Ejemplo n.º 47
0
        private static void OnRequestSendingRequest(WinHttpRequestState state)
        {
            Debug.Assert(state != null, "OnRequestSendingRequest: state 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();
                    throw WinHttpException.CreateExceptionUsingError(lastError);
                }
                
                // 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;

                try
                {
                    WinHttpCertificateHelper.BuildChain(
                        serverCertificate,
                        state.RequestMessage.RequestUri.Host,
                        state.CheckCertificateRevocationList,
                        out chain,
                        out sslPolicyErrors);

                    bool result = state.ServerCertificateValidationCallback(
                        state.RequestMessage,
                        serverCertificate,
                        chain,
                        sslPolicyErrors);
                    if (!result)
                    {
                        throw WinHttpException.CreateExceptionUsingError(
                            (int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE);
                    }
                }
                finally
                {
                    if (chain != null)
                    {
                        chain.Dispose();
                    }
                }
            }
        }
Ejemplo n.º 48
0
        private Task<bool> InternalSendRequestAsync(WinHttpRequestState state)
        {
            state.TcsSendRequest = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            lock (state.Lock)
            {
                state.Pin();
                if (!Interop.WinHttp.WinHttpSendRequest(
                    state.RequestHandle,
                    null,
                    0,
                    IntPtr.Zero,
                    0,
                    0,
                    state.ToIntPtr()))
                {
                    // Dispose (which will unpin) the state object. Since this failed, WinHTTP won't associate
                    // our context value (state object) to the request handle. And thus we won't get HANDLE_CLOSING
                    // notifications which would normally cause the state object to be unpinned and disposed.
                    state.Dispose();
                    WinHttpException.ThrowExceptionUsingLastError();
                }
            }

            return state.TcsSendRequest.Task;
        }
Ejemplo n.º 49
0
 internal WinHttpRequestStream(WinHttpRequestState state, bool chunkedMode)
 {
     _state = state;
     _chunkedMode = chunkedMode;
 }
Ejemplo n.º 50
0
 internal WinHttpResponseStream(WinHttpRequestState state)
 {
     _state = state;
 }
Ejemplo n.º 51
0
        private async void StartRequest(WinHttpRequestState state)
        {
            if (state.CancellationToken.IsCancellationRequested)
            {
                state.Tcs.TrySetCanceled(state.CancellationToken);
                state.ClearSendRequestState();
                return;
            }

            SafeWinHttpHandle connectHandle = null;
            try
            {
                EnsureSessionHandleExists(state);

                // Specify an HTTP server.
                connectHandle = Interop.WinHttp.WinHttpConnect(
                    _sessionHandle,
                    state.RequestMessage.RequestUri.Host,
                    (ushort)state.RequestMessage.RequestUri.Port,
                    0);
                ThrowOnInvalidHandle(connectHandle);
                connectHandle.SetParentHandle(_sessionHandle);

                // Try to use the requested version if a known/supported version was explicitly requested.
                // Otherwise, we simply use winhttp's default.
                string httpVersion = null;
                if (state.RequestMessage.Version == HttpVersionInternal.Version10)
                {
                    httpVersion = "HTTP/1.0";
                }
                else if (state.RequestMessage.Version == HttpVersionInternal.Version11)
                {
                    httpVersion = "HTTP/1.1";
                }

                // Turn off additional URI reserved character escaping (percent-encoding). This matches
                // .NET Framework behavior. System.Uri establishes the baseline rules for percent-encoding
                // of reserved characters.
                uint flags = Interop.WinHttp.WINHTTP_FLAG_ESCAPE_DISABLE;
                if (state.RequestMessage.RequestUri.Scheme == UriScheme.Https)
                {
                    flags |= Interop.WinHttp.WINHTTP_FLAG_SECURE;
                }

                // Create an HTTP request handle.
                state.RequestHandle = Interop.WinHttp.WinHttpOpenRequest(
                    connectHandle,
                    state.RequestMessage.Method.Method,
                    state.RequestMessage.RequestUri.PathAndQuery,
                    httpVersion,
                    Interop.WinHttp.WINHTTP_NO_REFERER,
                    Interop.WinHttp.WINHTTP_DEFAULT_ACCEPT_TYPES,
                    flags);
                ThrowOnInvalidHandle(state.RequestHandle);
                state.RequestHandle.SetParentHandle(connectHandle);

                // Set callback function.
                SetStatusCallback(state.RequestHandle, WinHttpRequestCallback.StaticCallbackDelegate);

                // Set needed options on the request handle.
                SetRequestHandleOptions(state);

                bool chunkedModeForSend = IsChunkedModeForSend(state.RequestMessage);

                AddRequestHeaders(
                    state.RequestHandle,
                    state.RequestMessage,
                    _cookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer ? _cookieContainer : null);

                uint proxyAuthScheme = 0;
                uint serverAuthScheme = 0;
                state.RetryRequest = false;

                // The only way to abort pending async operations in WinHTTP is to close the WinHTTP handle.
                // We will detect a cancellation request on the cancellation token by registering a callback.
                // If the callback is invoked, then we begin the abort process by disposing the handle. This
                // will have the side-effect of WinHTTP cancelling any pending I/O and accelerating its callbacks
                // on the handle and thus releasing the awaiting tasks in the loop below. This helps to provide
                // a more timely, cooperative, cancellation pattern.
                using (state.CancellationToken.Register(s => ((WinHttpRequestState)s).RequestHandle.Dispose(), state))                
                {
                    do
                    {
                        _authHelper.PreAuthenticateRequest(state, proxyAuthScheme);

                        await InternalSendRequestAsync(state);

                        if (state.RequestMessage.Content != null)
                        {
                            await InternalSendRequestBodyAsync(state, chunkedModeForSend).ConfigureAwait(false);
                        }

                        bool receivedResponse = await InternalReceiveResponseHeadersAsync(state) != 0;
                        if (receivedResponse)
                        {
                            // If we're manually handling cookies, we need to add them to the container after
                            // each response has been received.
                            if (state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer)
                            {
                                WinHttpCookieContainerAdapter.AddResponseCookiesToContainer(state);
                            }

                            _authHelper.CheckResponseForAuthentication(
                                state,
                                ref proxyAuthScheme,
                                ref serverAuthScheme);
                        }
                    } while (state.RetryRequest);
                }

                state.CancellationToken.ThrowIfCancellationRequested();

                // Since the headers have been read, set the "receive" timeout to be based on each read
                // call of the response body data. WINHTTP_OPTION_RECEIVE_TIMEOUT sets a timeout on each
                // lower layer winsock read.
                uint optionData = (uint)_receiveDataTimeout.TotalMilliseconds;
                SetWinHttpOption(state.RequestHandle, Interop.WinHttp.WINHTTP_OPTION_RECEIVE_TIMEOUT, ref optionData);

                HttpResponseMessage responseMessage = WinHttpResponseParser.CreateResponseMessage(state, _doManualDecompressionCheck);
                state.Tcs.TrySetResult(responseMessage);
            }
            catch (Exception ex)
            {
                HandleAsyncException(state, state.SavedException ?? ex);
            }
            finally
            {
                SafeWinHttpHandle.DisposeAndClearHandle(ref connectHandle);
                state.ClearSendRequestState();
            }
        }
Ejemplo n.º 52
0
        public static HttpResponseMessage CreateResponseMessage(
            WinHttpRequestState state,
            bool doManualDecompressionCheck)
        {
            HttpRequestMessage request = state.RequestMessage;
            SafeWinHttpHandle requestHandle = state.RequestHandle;
            CookieUsePolicy cookieUsePolicy = state.Handler.CookieUsePolicy;
            CookieContainer cookieContainer = state.Handler.CookieContainer;
            var response = new HttpResponseMessage();
            bool stripEncodingHeaders = false;

            // Get HTTP version, status code, reason phrase from the response headers.
            string version = GetResponseHeaderStringInfo(requestHandle, Interop.WinHttp.WINHTTP_QUERY_VERSION);
            if (string.Compare("HTTP/1.1", version, StringComparison.OrdinalIgnoreCase) == 0)
            {
                response.Version = HttpVersion.Version11;
            }
            else if (string.Compare("HTTP/1.0", version, StringComparison.OrdinalIgnoreCase) == 0)
            {
                response.Version = HttpVersion.Version10;
            }
            else
            {
                response.Version = HttpVersion.Unknown;
            }

            response.StatusCode = (HttpStatusCode)GetResponseHeaderNumberInfo(
                requestHandle,
                Interop.WinHttp.WINHTTP_QUERY_STATUS_CODE);
            response.ReasonPhrase = GetResponseHeaderStringInfo(
                requestHandle,
                Interop.WinHttp.WINHTTP_QUERY_STATUS_TEXT);

            // Create response stream and wrap it in a StreamContent object.
            var responseStream = new WinHttpResponseStream(state);
            Stream decompressedStream = responseStream;

            if (doManualDecompressionCheck)
            {
                string contentEncoding = GetResponseHeaderStringInfo(
                    requestHandle,
                    Interop.WinHttp.WINHTTP_QUERY_CONTENT_ENCODING);
                if (!string.IsNullOrEmpty(contentEncoding))
                {
                    if (contentEncoding.IndexOf(EncodingNameDeflate, StringComparison.OrdinalIgnoreCase) > -1)
                    {
                        decompressedStream = new DeflateStream(responseStream, CompressionMode.Decompress);
                        stripEncodingHeaders = true;
                    }
                    else if (contentEncoding.IndexOf(EncodingNameGzip, StringComparison.OrdinalIgnoreCase) > -1)
                    {
                        decompressedStream = new GZipStream(responseStream, CompressionMode.Decompress);
                        stripEncodingHeaders = true;
                    }
                }
            }

            var content = new StreamContent(decompressedStream);

            response.Content = content;
            response.RequestMessage = request;

            // Parse raw response headers and place them into response message.
            ParseResponseHeaders(requestHandle, response, stripEncodingHeaders);

            // Store response header cookies into custom CookieContainer.
            if (cookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer)
            {
                Debug.Assert(cookieContainer != null);

                if (response.Headers.Contains(HeaderNameSetCookie))
                {
                    IEnumerable<string> cookieHeaders = response.Headers.GetValues(HeaderNameSetCookie);
                    foreach (var cookieHeader in cookieHeaders)
                    {
                        try
                        {
                            cookieContainer.SetCookies(request.RequestUri, cookieHeader);
                        }
                        catch (CookieException)
                        {
                            // We ignore malformed cookies in the response.
                        }
                    }
                }
            }

            return response;
        }
Ejemplo n.º 53
0
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
#endif
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request), SR.net_http_handler_norequest);
            }

            // Check for invalid combinations of properties.
            if (_proxy != null && _windowsProxyUsePolicy != WindowsProxyUsePolicy.UseCustomProxy)
            {
                throw new InvalidOperationException(SR.net_http_invalid_proxyusepolicy);
            }

            if (_windowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy && _proxy == null)
            {
                throw new InvalidOperationException(SR.net_http_invalid_proxy);
            }

            if (_cookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer &&
                _cookieContainer == null)
            {
                throw new InvalidOperationException(SR.net_http_invalid_cookiecontainer);
            }

            CheckDisposed();

            Guid loggingRequestId = s_diagnosticListener.LogHttpRequest(request);

            SetOperationStarted();

            TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();

            // Create state object and save current values of handler settings.
            var state = new WinHttpRequestState();
            state.Tcs = tcs;
            state.CancellationToken = cancellationToken;
            state.RequestMessage = request;
            state.Handler = this;
            state.CheckCertificateRevocationList = _checkCertificateRevocationList;
            state.ServerCertificateValidationCallback = _serverCertificateValidationCallback;
            state.WindowsProxyUsePolicy = _windowsProxyUsePolicy;
            state.Proxy = _proxy;
            state.ServerCredentials = _serverCredentials;
            state.DefaultProxyCredentials = _defaultProxyCredentials;
            state.PreAuthenticate = _preAuthenticate;

            Task.Factory.StartNew(
                s => {
                    var whrs = (WinHttpRequestState)s;
                    whrs.Handler.StartRequest(whrs);
                },
                state,
                CancellationToken.None,
                TaskCreationOptions.DenyChildAttach,
                TaskScheduler.Default);

            s_diagnosticListener.LogHttpResponse(tcs.Task, loggingRequestId);

            return tcs.Task;
        }
Ejemplo n.º 54
0
        public void PreAuthenticateRequest(WinHttpRequestState state, uint proxyAuthScheme)
        {
            // Set proxy credentials if we have them.
            // If a proxy authentication challenge was responded to, reset
            // those credentials before each SendRequest, because the proxy  
            // may require re-authentication after responding to a 401 or  
            // to a redirect. If you don't, you can get into a 
            // 407-401-407-401- loop.
            if (proxyAuthScheme != 0)
            {
                SetWinHttpCredential(
                    state.RequestHandle,
                    state.Proxy == null ? state.DefaultProxyCredentials : state.Proxy.Credentials,
                    state.RequestMessage.RequestUri,
                    proxyAuthScheme,
                    Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);
            }

            // Apply pre-authentication headers for server authentication?
            if (state.PreAuthenticate)
            {
                uint authScheme;
                NetworkCredential serverCredentials;
                if (GetServerCredentialsFromCache(
                        state.RequestMessage.RequestUri,
                        out authScheme,
                        out serverCredentials))
                {
                    SetWinHttpCredential(
                        state.RequestHandle,
                        serverCredentials,
                        state.RequestMessage.RequestUri,
                        authScheme,
                        Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);
                    state.LastStatusCode = HttpStatusCode.Unauthorized; // Remember we already set the creds.
                }
                
                // No cached credential to use at this time. The request will first go out with no
                // 'Authorization' header. Later, if a 401 occurs, we will be able to cache the credential
                // since we will then know the proper auth scheme to use.
                //
                // TODO: Issue #2165. Adding logging to highlight the 'cache miss'.
            }
        }
Ejemplo n.º 55
0
        private void EnsureSessionHandleExists(WinHttpRequestState state)
        {
            if (_sessionHandle == null)
            {
                lock (_lockObject)
                {
                    if (_sessionHandle == null)
                    {
                        SafeWinHttpHandle sessionHandle;
                        uint accessType;

                        // If a custom proxy is specified and it is really the system web proxy
                        // (initial WebRequest.DefaultWebProxy) then we need to update the settings
                        // since that object is only a sentinel.
                        if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy)
                        {
                            Debug.Assert(state.Proxy != null);
                            try
                            {
                                state.Proxy.GetProxy(state.RequestMessage.RequestUri);
                            }
                            catch (PlatformNotSupportedException)
                            {
                                // This is the system web proxy.
                                state.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy;
                                state.Proxy = null;
                            }
                        }

                        if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.DoNotUseProxy ||
                            state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy)
                        {
                            // Either no proxy at all or a custom IWebProxy proxy is specified.
                            // For a custom IWebProxy, we'll need to calculate and set the proxy
                            // on a per request handle basis using the request Uri.  For now,
                            // we set the session handle to have no proxy.
                            accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
                        }
                        else if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinHttpProxy)
                        {
                            // Use WinHTTP per-machine proxy settings which are set using the "netsh winhttp" command.
                            accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
                        }
                        else
                        {
                            // Use WinInet per-user proxy settings.
                            accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY;
                        }
                        WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: proxy accessType={0}", accessType);

                        sessionHandle = Interop.WinHttp.WinHttpOpen(
                            IntPtr.Zero,
                            accessType,
                            Interop.WinHttp.WINHTTP_NO_PROXY_NAME,
                            Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS,
                            (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC);
                            
                        if (sessionHandle.IsInvalid)
                        {
                            int lastError = Marshal.GetLastWin32Error();
                            WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: error={0}", lastError);
                            if (lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER)
                            {
                                ThrowOnInvalidHandle(sessionHandle);
                            }

                            // We must be running on a platform earlier than Win8.1/Win2K12R2 which doesn't support
                            // WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY.  So, we'll need to read the Wininet style proxy
                            // settings ourself using our WinInetProxyHelper object.
                            _proxyHelper = new WinInetProxyHelper();
                            sessionHandle = Interop.WinHttp.WinHttpOpen(
                                IntPtr.Zero,
                                _proxyHelper.ManualSettingsOnly ? Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY : Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY,
                                _proxyHelper.ManualSettingsOnly ? _proxyHelper.Proxy : Interop.WinHttp.WINHTTP_NO_PROXY_NAME,
                                _proxyHelper.ManualSettingsOnly ? _proxyHelper.ProxyBypass : Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS,
                                (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC);
                            ThrowOnInvalidHandle(sessionHandle);
                        }

                        uint optionAssuredNonBlockingTrue = 1; // TRUE

                        if (!Interop.WinHttp.WinHttpSetOption(
                            sessionHandle,
                            Interop.WinHttp.WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS,
                            ref optionAssuredNonBlockingTrue,
                            (uint)Marshal.SizeOf<uint>()))
                        {
                            // This option is not available on downlevel Windows versions. While it improves
                            // performance, we can ignore the error that the option is not available.
                            int lastError = Marshal.GetLastWin32Error();
                            if (lastError != Interop.WinHttp.ERROR_WINHTTP_INVALID_OPTION)
                            {
                                throw WinHttpException.CreateExceptionUsingError(lastError);
                            }
                        }

                        SetSessionHandleOptions(sessionHandle);
                        _sessionHandle = sessionHandle;
                    }
                }
            }
        }
Ejemplo n.º 56
0
        public void CheckResponseForAuthentication(
            WinHttpRequestState state,
            ref uint proxyAuthScheme,
            ref uint serverAuthScheme)
        {
            uint supportedSchemes = 0;
            uint firstSchemeIgnored = 0;
            uint authTarget = 0;
            Uri uri = state.RequestMessage.RequestUri;

            state.RetryRequest = false;

            // Check the status code and retry the request applying credentials if needed.
            var statusCode = (HttpStatusCode)WinHttpResponseParser.GetResponseHeaderNumberInfo(
                state.RequestHandle,
                Interop.WinHttp.WINHTTP_QUERY_STATUS_CODE);

            switch (statusCode)
            {
                case HttpStatusCode.Unauthorized:
                    if (state.ServerCredentials == null || state.LastStatusCode == HttpStatusCode.Unauthorized)
                    {
                        // Either we don't have server credentials or we already tried 
                        // to set the credentials and it failed before.
                        // So we will let the 401 be the final status code returned.
                        break;
                    }
                    
                    state.LastStatusCode = statusCode;

                    // Determine authorization scheme to use. We ignore the firstScheme
                    // parameter which is included in the supportedSchemes flags already.
                    // We pass the schemes to ChooseAuthScheme which will pick the scheme
                    // based on most secure scheme to least secure scheme ordering.
                    if (!Interop.WinHttp.WinHttpQueryAuthSchemes(
                        state.RequestHandle,
                        out supportedSchemes,
                        out firstSchemeIgnored,
                        out authTarget))
                    {
                        WinHttpException.ThrowExceptionUsingLastError();
                    }

                    // WinHTTP returns the proper authTarget based on the status code (401, 407).
                    // But we can validate with assert.
                    Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);

                    serverAuthScheme = ChooseAuthScheme(supportedSchemes);
                    if (serverAuthScheme != 0)
                    {
                        SetWinHttpCredential(
                            state.RequestHandle,
                            state.ServerCredentials,
                            uri,
                            serverAuthScheme,
                            authTarget);

                        state.RetryRequest = true;
                    }
                    
                    break;

                case HttpStatusCode.ProxyAuthenticationRequired:
                    if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
                    {
                        // We tried already to set the credentials.
                        break;
                    }
                    
                    state.LastStatusCode = statusCode;

                    // Determine authorization scheme to use. We ignore the firstScheme
                    // parameter which is included in the supportedSchemes flags already.
                    // We pass the schemes to ChooseAuthScheme which will pick the scheme
                    // based on most secure scheme to least secure scheme ordering.
                    if (!Interop.WinHttp.WinHttpQueryAuthSchemes(
                        state.RequestHandle,
                        out supportedSchemes,
                        out firstSchemeIgnored,
                        out authTarget))
                    {
                        WinHttpException.ThrowExceptionUsingLastError();
                    }

                    // WinHTTP returns the proper authTarget based on the status code (401, 407).
                    // But we can validate with assert.
                    Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);

                    proxyAuthScheme = ChooseAuthScheme(supportedSchemes);
                    state.RetryRequest = true;
                    break;

                default:
                    if (state.PreAuthenticate && serverAuthScheme != 0)
                    {
                        SaveServerCredentialsToCache(uri, serverAuthScheme, state.ServerCredentials);
                    }
                    break;
            }
        }
Ejemplo n.º 57
0
 internal WinHttpRequestStream(WinHttpRequestState state, bool chunkedMode)
 {
     _state       = state;
     _chunkedMode = chunkedMode;
 }
Ejemplo n.º 58
0
        private void SetRequestHandleCredentialsOptions(WinHttpRequestState state)
        {
            // Set WinHTTP to send/prevent default credentials for either proxy or server auth.
            bool useDefaultCredentials = false;
            if (state.ServerCredentials == CredentialCache.DefaultCredentials)
            {
                useDefaultCredentials = true;
            }
            else if (state.WindowsProxyUsePolicy != WindowsProxyUsePolicy.DoNotUseProxy)
            {
                if (state.Proxy == null && _defaultProxyCredentials == CredentialCache.DefaultCredentials)
                {
                    useDefaultCredentials = true;
                }
                else if (state.Proxy != null && state.Proxy.Credentials == CredentialCache.DefaultCredentials)
                {
                    useDefaultCredentials = true;
                }
            }

            uint optionData = useDefaultCredentials ? 
                Interop.WinHttp.WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW : 
                Interop.WinHttp.WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH;
            SetWinHttpOption(state.RequestHandle, Interop.WinHttp.WINHTTP_OPTION_AUTOLOGON_POLICY, ref optionData);
        }
Ejemplo n.º 59
0
        public void CheckResponseForAuthentication(
            WinHttpRequestState state,
            ref uint proxyAuthScheme,
            ref uint serverAuthScheme)
        {
            uint supportedSchemes   = 0;
            uint firstSchemeIgnored = 0;
            uint authTarget         = 0;
            Uri  uri = state.RequestMessage.RequestUri;

            state.RetryRequest = false;

            // Check the status code and retry the request applying credentials if needed.
            var statusCode = (HttpStatusCode)WinHttpResponseParser.GetResponseHeaderNumberInfo(
                state.RequestHandle,
                Interop.WinHttp.WINHTTP_QUERY_STATUS_CODE);

            switch (statusCode)
            {
            case HttpStatusCode.Unauthorized:
                if (state.ServerCredentials == null || state.LastStatusCode == HttpStatusCode.Unauthorized)
                {
                    // Either we don't have server credentials or we already tried
                    // to set the credentials and it failed before.
                    // So we will let the 401 be the final status code returned.
                    break;
                }

                state.LastStatusCode = statusCode;

                // Determine authorization scheme to use. We ignore the firstScheme
                // parameter which is included in the supportedSchemes flags already.
                // We pass the schemes to ChooseAuthScheme which will pick the scheme
                // based on most secure scheme to least secure scheme ordering.
                if (!Interop.WinHttp.WinHttpQueryAuthSchemes(
                        state.RequestHandle,
                        out supportedSchemes,
                        out firstSchemeIgnored,
                        out authTarget))
                {
                    WinHttpException.ThrowExceptionUsingLastError();
                }

                // WinHTTP returns the proper authTarget based on the status code (401, 407).
                // But we can validate with assert.
                Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);

                serverAuthScheme = ChooseAuthScheme(supportedSchemes);
                if (serverAuthScheme != 0)
                {
                    SetWinHttpCredential(
                        state.RequestHandle,
                        state.ServerCredentials,
                        uri,
                        serverAuthScheme,
                        authTarget);

                    state.RetryRequest = true;
                }

                break;

            case HttpStatusCode.ProxyAuthenticationRequired:
                if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
                {
                    // We tried already to set the credentials.
                    break;
                }

                state.LastStatusCode = statusCode;

                // If we don't have any proxy credentials to try, then we end up with 407.
                ICredentials proxyCreds = state.Proxy == null ?
                                          state.DefaultProxyCredentials :
                                          state.Proxy.Credentials;
                if (proxyCreds == null)
                {
                    break;
                }

                // Determine authorization scheme to use. We ignore the firstScheme
                // parameter which is included in the supportedSchemes flags already.
                // We pass the schemes to ChooseAuthScheme which will pick the scheme
                // based on most secure scheme to least secure scheme ordering.
                if (!Interop.WinHttp.WinHttpQueryAuthSchemes(
                        state.RequestHandle,
                        out supportedSchemes,
                        out firstSchemeIgnored,
                        out authTarget))
                {
                    WinHttpException.ThrowExceptionUsingLastError();
                }

                // WinHTTP returns the proper authTarget based on the status code (401, 407).
                // But we can validate with assert.
                Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);

                proxyAuthScheme    = ChooseAuthScheme(supportedSchemes);
                state.RetryRequest = true;
                break;

            default:
                if (state.PreAuthenticate && serverAuthScheme != 0)
                {
                    SaveServerCredentialsToCache(uri, serverAuthScheme, state.ServerCredentials);
                }
                break;
            }
        }
Ejemplo n.º 60
0
        private Task<bool> InternalSendRequestAsync(WinHttpRequestState state)
        {
            state.TcsSendRequest = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            lock (state.Lock)
            {
                if (!Interop.WinHttp.WinHttpSendRequest(
                    state.RequestHandle,
                    null,
                    0,
                    IntPtr.Zero,
                    0,
                    0,
                    state.ToIntPtr()))
                {
                    WinHttpException.ThrowExceptionUsingLastError();
                }
            }

            return state.TcsSendRequest.Task;
        }