Beispiel #1
0
        /*++

        Routine Description:

            Assembles the data/headers for an HTTP request
             into a buffer

        Arguments:

            none.

        Return Value:

            none.

        --*/
        internal void UpdateHeaders() {
            GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::UpdateHeaders");
            GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::UpdateHeaders");

#if TRAVE
            _HttpRequestHeaders.Set("Cur-Hash-ID", ValidationHelper.HashString(this));
            _HttpRequestHeaders.AddInternal("Hash-ID", ValidationHelper.HashString(this));
#endif
            string hostString;
            // All WebsocketRequests (even with scheme http) are tunneled through proxies
            bool isTunnelRequestForHttp = IsTunnelRequest && _OriginUri.Scheme == Uri.UriSchemeHttp;

            // For CONNECT requests the proxy is not able to identify whether the origin Uri is using http or
            // https-scheme. According to the 4.0 behavior in HttpWebRequest proxies assume http-scheme when
            // calculating the default port. A CONNECT request sent form HttpWebRequest in .Net 4.0 for
            // https://hostname/someresource.htm looks like:
            //
            // CONNECT hostname:443 HTTP/1.1
            // Host: hostname
            // Proxy-Connection: Keep-Alive
            //
            // This means the Host header should contain port 80 - even if the origin Uri is using http-scheme,
            // because the proxy has no way to identify the scheme for the origin Uri and assumes https in this
            // case, because tunneling SSL/TLS through proxies is the most common use case.
            //
            // WININET is always emitting the default port for CONNECT requests.
            if (UseCustomHost) {
                hostString = GetSafeHostAndPort(_HostUri, _HostHasPort || isTunnelRequestForHttp, false);
            }
            else {
                hostString = GetSafeHostAndPort(isTunnelRequestForHttp, false);
            }

            // Set HostName Header
            // Do unusual encoding so that host header value gets serialized to wire properly
            HostHeaderString hhs = new HostHeaderString(hostString);
            string host = WebHeaderCollection.HeaderEncoding.GetString(hhs.Bytes, 0, hhs.ByteCount);
            _HttpRequestHeaders.ChangeInternal( HttpKnownHeaderNames.Host, host);
            // about to create the headers we're going to send. Check if any
            // modules want to inspect or modify them
            if (_CookieContainer != null) {
                CookieModule.OnSendingHeaders(this);
            }
            GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::UpdateHeaders");
        }
Beispiel #2
0
        /*++

        Routine Description:

            Assembles the status line for an HTTP request
             specifically to a proxy...

        Arguments:

            headersSize - size of the Header string that we send after
                this request line

        Return Value:

            int - number of bytes written out

        --*/
        private int GenerateProxyRequestLine(int headersSize) {
            //
            // Handle Proxy Case, i.e. "GET http://hostname-outside-of-proxy.somedomain.edu:999"
            // consider handling other schemes
            //
            // Note that we will take the scheme off the URI, hence may issue other but http request
            // through the proxy on redirect. While this is not allowed by RFC,
            // this it used to work in IE and we have already tested permissions for that destination Uri.
            if ((object)_Uri.Scheme == (object)Uri.UriSchemeFtp) {
                // FTP
                return GenerateFtpProxyRequestLine(headersSize);
            }
            // HTTP
            int offset = 0;
            string scheme = _Uri.GetComponents(UriComponents.Scheme | UriComponents.KeepDelimiter, UriFormat.UriEscaped);
            HostHeaderString host = new HostHeaderString(GetSafeHostAndPort(false, true));
            string path = _Uri.GetComponents(UriComponents.Path | UriComponents.Query, UriFormat.UriEscaped);

            int writeBufferLength = CurrentMethod.Name.Length +
                                    scheme.Length +
                                    host.ByteCount +
                                    path.Length +
                                    RequestLineConstantSize +
                                    headersSize;
            _WriteBuffer = new byte[writeBufferLength];

            offset = Encoding.ASCII.GetBytes(CurrentMethod.Name, 0, CurrentMethod.Name.Length, WriteBuffer, 0);
            WriteBuffer[offset++] = (byte)' ';
            offset += Encoding.ASCII.GetBytes(scheme, 0, scheme.Length, WriteBuffer, offset);
            host.Copy(WriteBuffer, offset);
            offset += host.ByteCount;
            offset += Encoding.ASCII.GetBytes(path, 0, path.Length, WriteBuffer, offset);
            WriteBuffer[offset++] = (byte)' ';
            return offset;
        }
Beispiel #3
0
        private int GenerateFtpProxyRequestLine(int headersSize) {
            // Special handling for FTP via HTTP proxy
            int offset = 0;
            string scheme = _Uri.GetComponents(UriComponents.Scheme | UriComponents.KeepDelimiter, UriFormat.UriEscaped);
            string userInfo = _Uri.GetComponents(UriComponents.UserInfo | UriComponents.KeepDelimiter, UriFormat.UriEscaped);
            HostHeaderString host = new HostHeaderString(GetSafeHostAndPort(false, true));
            string path = _Uri.GetComponents(UriComponents.Path | UriComponents.Query, UriFormat.UriEscaped);

            if (userInfo == "") {
                // No userinfo so see if we can add from Credentials
                string username = null;
                string password = null;
                NetworkCredential networkCreds = Credentials.GetCredential(_Uri, "basic");
                if (networkCreds != null
                    && (object)networkCreds
                       != (object)FtpWebRequest.DefaultNetworkCredential)
                {
                    username = networkCreds.InternalGetDomainUserName();
                    password = networkCreds.InternalGetPassword();
                    password = (password == null) ? string.Empty : password;
                }
                if (username != null) {
                    // For FTP proxy we don't escape the username and password strings
                    // Since some servers don't seem to support it
                    // Only escape the absolute minimum that is required for
                    // a valid Uri which is (: \ / ? # %)
                    username = username.Replace(":",  "%3A");
                    password = password.Replace(":",  "%3A");
                    username = username.Replace("\\", "%5C");
                    password = password.Replace("\\", "%5C");
                    username = username.Replace("/",  "%2F");
                    password = password.Replace("/",  "%2F");
                    username = username.Replace("?",  "%3F");
                    password = password.Replace("?",  "%3F");
                    username = username.Replace("#",  "%23");
                    password = password.Replace("#",  "%23");
                    username = username.Replace("%",  "%25");
                    password = password.Replace("%",  "%25");
                    username = username.Replace("@",  "%40");
                    password = password.Replace("@",  "%40");

                    // build complete userinfo
                    userInfo = username + ":" + password + "@";
                }
            }

            // construct request line from components
            int writeBufferLength = CurrentMethod.Name.Length +
                                    scheme.Length +
                                    userInfo.Length +
                                    host.ByteCount +
                                    path.Length +
                                    RequestLineConstantSize +
                                    headersSize;
            _WriteBuffer = new byte[writeBufferLength];

            offset = Encoding.ASCII.GetBytes(CurrentMethod.Name, 0, CurrentMethod.Name.Length, WriteBuffer, 0);
            WriteBuffer[offset++] = (byte)' ';
            offset += Encoding.ASCII.GetBytes(scheme, 0, scheme.Length, WriteBuffer, offset);
            offset += Encoding.ASCII.GetBytes(userInfo, 0, userInfo.Length, WriteBuffer, offset);
            host.Copy(WriteBuffer, offset);
            offset += host.ByteCount;
            offset += Encoding.ASCII.GetBytes(path, 0, path.Length, WriteBuffer, offset);
            WriteBuffer[offset++] = (byte)' ';
            return offset;
        }
Beispiel #4
0
        /*++

        Routine Description:

            Assembles the status line for an HTTP request
             specifically for CONNECT style verbs, that create a pipe

        Arguments:

            headersSize - size of the Header string that we send after
                this request line

        Return Value:

            int - number of bytes written out

        --*/
        private int GenerateConnectRequestLine(int headersSize) {
            int offset = 0;

            HostHeaderString host = new HostHeaderString(GetSafeHostAndPort(true, true));

            //
            // Handle Connect Case, i.e. "CONNECT hostname.domain.edu:999"
            //

            int writeBufferLength = CurrentMethod.Name.Length +
                                    host.ByteCount +
                                    RequestLineConstantSize +
                                    headersSize;
            _WriteBuffer = new byte[writeBufferLength];
            offset = Encoding.ASCII.GetBytes(CurrentMethod.Name, 0, CurrentMethod.Name.Length, WriteBuffer, 0);
            WriteBuffer[offset++] = (byte)' ';
            host.Copy(WriteBuffer, offset);
            offset += host.ByteCount;
            WriteBuffer[offset++] = (byte)' ';
            return offset;
        }