Esempio n. 1
0
 private static bool IsNtlmAuthentication(HeyHttpRequest request)
 {
     if (String.IsNullOrEmpty(request.Authorization) || !request.Authorization.StartsWith("NTLM "))
     {
         return(false);
     }
     return(true);
 }
Esempio n. 2
0
 private void ReadRequestHeaders()
 {
     using (FileStream logFileStream = File.OpenWrite(logFile.FullName))
     {
         request = new HeyHttpRequest(logger);
         request.ReadHeaders(networkStream, logFileStream);
     }
 }
Esempio n. 3
0
 private static void AcceptCore()
 {
     requestHeaders = new HeyHttpRequest(logger);
     requestHeaders.ReadHeaders(networkStream, null);
     Upgrade();
     //ReadRequestBody();
     //ShowRequestDetails();
     //SendResponse("200 OK", new List<string>());
 }
Esempio n. 4
0
        private static bool IsAuthenticated(HeyHttpRequest request)
        {
            string authorization = request.GetHeader("Proxy-Authorization");

            if (!String.IsNullOrEmpty(authorization))
            {
                // Credentails are included.
                return(true);
            }

            return(false);
        }
Esempio n. 5
0
        private static bool IsNtlmMessage(HeyHttpRequest request, NtlmMessageType expectedMessageType)
        {
            if (!IsNtlmAuthentication(request))
            {
                return(false);
            }

            string message = request.Authorization.Substring("NTLM ".Length);

            byte[] buffer = Convert.FromBase64String(message);

            // Validate signature.
            string signature = Encoding.ASCII.GetString(buffer, 0, 8);

            if (signature != "NTLMSSP\0")
            {
                return(false);
            }

            // Is it negotiation message?
            uint messageType = BitConverter.ToUInt32(buffer, 8);

            if (messageType != (uint)expectedMessageType)
            {
                return(false);
            }

            if (expectedMessageType == NtlmMessageType.NegotiatieMessage)
            {
                // Domain name.
                bool hasDomainName       = (buffer[14] & 0x10) == 1;
                uint domainNameLength    = BitConverter.ToUInt16(buffer, 16);
                uint domainNameMaxLength = BitConverter.ToUInt16(buffer, 18);
                uint domainNameOffset    = BitConverter.ToUInt32(buffer, 20);
            }

            return(true);
        }
Esempio n. 6
0
        private static void ProcessDigestAuthorization(HeyHttpRequest request, HeyLogger logger)
        {
            string headerValue = request.Authorization.Substring("Digest ".Length);

            string[] pairs = headerValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string pair in pairs)
            {
                string[] keyAndValue = pair.Split(new char[] { '=' }, 2);
                if (keyAndValue.Length == 2)
                {
                    string key   = keyAndValue[0].Trim();
                    string value = keyAndValue[1].Trim('"');

                    logger.WriteHeadersLine(
                        String.Format("{0}: {1}", key, value));
                }
            }

            logger.WriteHeadersLine("\r\n");

            // TODO: If the password is not the expected one, clear Authorization header,
            // so a 401 Unauthorized response is sent.
        }
Esempio n. 7
0
        public static bool IsAuthorizationValid(HeyHttpRequest request)
        {
            string user     = String.Empty;
            string password = String.Empty;

            // 1. Decode headers.

            if (!String.IsNullOrEmpty(request.Authorization))
            {
                switch (GetScheme(request.Authorization))
                {
                case AuthorizationScheme.Basic:
                    ProcessBasicAuthorization(request.Authorization, out user, out password);
                    break;

                default:
                    // We cannot decode this header, assume header is valid.
                    return(true);
                }
            }

            // 2. Look for expected values and compare.

            string expectedUser;
            string expectedPassword;

            if (request.QueryStringHas("user", out expectedUser) &&
                request.QueryStringHas("password", out expectedPassword))
            {
                if (expectedUser == user && expectedPassword == password)
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 8
0
        private static void OnAccept(IAsyncResult asyncResult)
        {
            HeyLogger logger         = new HeyLogger();
            Socket    socketListener = asyncResult.AsyncState as Socket;
            Socket    client         = socketListener.EndAccept(asyncResult);

            socketListener.BeginAccept(OnAccept, asyncResult.AsyncState);

            try
            {
                HeyHttpRequest request = new HeyHttpRequest(logger);

                // Client got connected.
                logger.WriteLine(String.Format("Connected: {0}", client.RemoteEndPoint));

                // Read HTTP headers.
                NetworkStream clientStream = new NetworkStream(client);
                MemoryStream  tempStream   = new MemoryStream();
                request.ReadHeaders(clientStream, tempStream);

                // Authentication.
                if (settings.AuthenticationRequired && !IsAuthenticated(request))
                {
                    Reply407AndClose(logger, clientStream);
                    return;
                }

                // Find server host name.
                logger.WriteLine(String.Format("Trying to connect to {0}", request.Host));

                // Get IP address for the given server hostname.
                IPHostEntry hostEntry = Dns.GetHostEntry(request.Host);
                if (hostEntry.AddressList.Length == 0)
                {
                    throw new Exception("Unknow server hostname.");
                }
                IPAddress address = hostEntry.AddressList[0];

                // Connect to server.
                Socket server = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                server.Connect(new IPEndPoint(address, request.Port));

                logger.WriteLine(String.Format("Connected to {0}", request.Host));

                // Send cached data to server.
                NetworkStream serverStream = new NetworkStream(server);

                // When using the CONNECT method, proxy must send a HTTP response to client.
                // See "Tunneling TCP based protocols through Web proxy servers" internet-draft.
                if (request.Method == "CONNECT")
                {
                    HeyHttpResponse response = new HeyHttpResponse(logger);
                    response.Status = "200 Connection established";
                    response.Headers.Add("Proxy-agent: Happy-Sockets-Proxy/1.0");
                    response.CopyHeadersTo(clientStream);
                }
                else
                {
                    // Only forward headers when it is not a CONNECT request.
                    tempStream.Seek(0, SeekOrigin.Begin);
                    tempStream.CopyTo(serverStream);
                }

                // Forward data.
                ParameterizedThreadStart serverToClientStart = new ParameterizedThreadStart(ForwardData);
                Thread serverToClientThread = new Thread(serverToClientStart);
                serverToClientThread.Start(
                    new StreamsPair
                {
                    StreamA = serverStream,
                    StreamB = clientStream,
                    Label   = "server to client",
                    Logger  = logger
                });

                ParameterizedThreadStart clientToServerStart = new ParameterizedThreadStart(ForwardData);
                Thread clientToServerThread = new Thread(clientToServerStart);
                clientToServerThread.Start(
                    new StreamsPair
                {
                    StreamA = clientStream,
                    StreamB = serverStream,
                    Label   = "client to server",
                    Logger  = logger
                });

                //serverToClientThread.Join();
                //clientToServerThread.Join();

                // TODO: make sure streams do not go out of scope.
                // TODO: wait until threads end and ensure connections are close.
            }
            catch (SocketException ex)
            {
                WriteLine(ConsoleColor.Red, ex.Message);
                logger.WriteLine(ex.ToString());

                // We couldn't connect to the  server, terminate connection with the client.
                client.Close();
            }
            catch (IOException ex)
            {
                WriteLine(ConsoleColor.Red, ex.Message);
                logger.WriteLine(ex.ToString());

                // The client closed the connection, terminate the connection with the server.
                client.Close();
            }
            catch (Exception ex)
            {
                WriteLine(ConsoleColor.Red, ex.Message);
                logger.WriteLine(ex.ToString());
            }
        }
Esempio n. 9
0
        public static void Start(HeyHttpClientSettings settings)
        {
            try
            {
                Uri uri = new Uri(settings.UriString);

                //using (TcpClient client = new TcpClient(AddressFamily.InterNetworkV6))
                using (TcpClient client = new TcpClient())
                {
                    client.Connect(uri.Host, uri.Port);
                    //client.Connect(IPAddress.Parse("2001:4898:1b:4:71e6:90b3:efa0:aa9b"), 80);

                    Stream stream = client.GetStream();

                    if (uri.Port == 443)
                    {
                        SslStream sslStream = new SslStream(stream, true);
                        sslStream.AuthenticateAsClient(uri.Host);
                        stream = sslStream;
                    }

                    HeyHttpRequest request = new HeyHttpRequest(null);

                    if (!String.IsNullOrEmpty(settings.Method))
                    {
                        request.Method = settings.Method;
                    }
                    else
                    {
                        request.Method = "GET";
                    }

                    request.PathAndQuery = uri.PathAndQuery;
                    request.Version      = "HTTP/1.1";
                    request.SetHeader("Host", uri.Host);
                    request.SetHeader("Accept-Encoding", "gzip");
                    request.SetHeader("Connection", "Keep-Alive");

                    foreach (var header in settings.Headers)
                    {
                        if (!String.IsNullOrEmpty(header))
                        {
                            request.SetHeader(header);
                        }
                    }

                    byte[] requestBytes = Encoding.ASCII.GetBytes(request.ConcatenateHeaders());

                    // This is a sample on how to overwrite the command line request:
                    //StringBuilder builder = new StringBuilder();
                    //builder.Append("POST /v5.0/folder.a4fb14adbccd1917.A4FB14ADBCCD1917!32089/files HTTP/1.1\r\n");
                    //builder.Append("Accept-Encoding: \r\n");
                    //builder.Append("Authorization: Bearer EwCIAq1DBAAUGCCXc8wU/zFu9QnLdZXy%2bYnElFkAAdYrLSFwx5TYQJSLo7JvCeKfAO384WRQiHYnTK8qTQDUiiVU2H5/sLAM1/j5gfRCbPSCdZ4LP6%2bAEBtA%2boOQ9bEdr0LwbQknqjd8ZkdutBdn9EfnS7KP0mjYldAI%2beekBQOHijrFSlmloMONrdbsYj0gkM8JxRezYG%2bOZCHbRTDLRIwMbPjjZg%2bwfZyWMNVT5vDlI9jb7L1q2hDWbpGk3oVprXKll6%2b3dfTwuVsKRJmpDfQz65oaKObxotc4i5dUVpyfGwIe79JAVMT5mYyb50Wv9zSxzOdLRxkOP8PXODIYc27JZQbUNqyhjgbaIXK9TN%2b8Lp4sm35Sy19d3QKo%2bAADZgAACHgZT5b/yvk0WAEbqZFBuQO%2bZgkYIhhbykgbQiB4h%2bbeIuQIFd%2bl4bzD62I9mBppLGjyeni/j4rDbgkkGvyrt/sNrbWkFwtc0DxzFf4ITE8tLY5o1eJ69m9D1vJ/P8xwuO2y/tSK3zuQdKJXagg7w/zx3qGZJ0OMNt%2bES9xkN1MWcS1ErFadoCAd/O0feLxR3V9HxgsEoX/KPV50yOJFEPjCBVhXzoCiZKpQO8uYE0ttOfzAauVkdhcsjD4RoRBfRO1WfoFkidc1wBntxA6lPnFSYX4xbxYyIMo2WAFdHLTa1AGjLcpNksFYR6NJU8cTenlsx6baLJ6%2bAm9VHoWWiTOF4Q18Stj7yeIPzl1k8hDwAKR0VrYx00TjVABuQOWD6VgsMA0vuER4bI1Wo2siPopQz3UdAgsq/frw3kiZB4PPl89kRfvTuaXjwoljSN3I6GeSiVePvFYjCGyFEQBZr8HE2XMB\r\n");
                    ////builder.Append("Content-Length: 197\r\n");
                    //builder.Append("Content-Length: 217\r\n");
                    //builder.Append("Content-Type: multipart/form-data; boundary=8381f8b9-b470-43ce-b23b-f13cf5840014\r\n");
                    //builder.Append("Host: apis.live.net\r\n");
                    //builder.Append("Connection: Keep-Alive\r\n");
                    //builder.Append("Cache-Control: no-cache\r\n");
                    //builder.Append("\r\n");
                    //builder.Append("--8381f8b9-b470-43ce-b23b-f13cf5840014\r\n");
                    ////builder.Append("Content-Length: 9\r\n");
                    //builder.Append("Content-Type: application/octet-stream; charset=UTF-8\r\n");
                    //builder.Append("Content-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\n");
                    ////builder.Append("Content-Type: application/octet-stream\r\n");
                    //builder.Append("\r\n");
                    //builder.Append("xxxxxxxxx\r\n");
                    //builder.Append("--8381f8b9-b470-43ce-b23b-f13cf5840014--\r\n");
                    //requestBytes = Encoding.UTF8.GetBytes(builder.ToString());

                    stream.Write(requestBytes, 0, requestBytes.Length);
                    Console.WriteLine(Encoding.UTF8.GetString(requestBytes));

                    byte[] responseBytes = new byte[1024];
                    int    bytesRead;
                    do
                    {
                        // How to prevent multi-byte chars to be splitted into two buffers?
                        bytesRead = stream.Read(responseBytes, 0, responseBytes.Length);
                        string response = Encoding.UTF8.GetString(responseBytes, 0, bytesRead);
                        Console.Write(response);
                    } while (bytesRead > 0);
                }
            }
            catch (WebException ex)
            {
                Console.WriteLine(ex);
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex);
            }
        }
Esempio n. 10
0
        public static void AddAuthenticateHeaderIfNeeded(HeyHttpRequest request, HeyHttpResponse response)
        {
            // Basic Server:
            // GET --------->
            //
            // <--------- 401 Unauthorized
            //            WWW-Authenticate: Basic realm="xyz"
            //
            // GET --------->
            // Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
            //
            // <--------- 200 OK

            // Basic Proxy:
            //
            // GET --------->
            // <-------- 407 Proxy Authentication Required
            //           Proxy-Authenticate: Basic realm="xyz"
            //
            // GET --------->
            // Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
            //
            // <--------- 200 OK

            // NTLM:
            //
            // GET --------->
            // <--------- 401 Unauthorized
            // negotiate message --------->
            // <--------- challenge message
            // authenticate message --------->
            // <--------- 200 OK
            if (IsNtlmMessage(request, NtlmMessageType.NegotiatieMessage))
            {
                response.Status = "401 Unauthorized";
                response.Headers.Add("WWW-Authenticate: NTLM TlRMTVNTUAACAAAADgAOADgAAAAFgomiBTEwAGt4s6QAAAAAAAAAAPwA/ABGAAAABgLwIwAAAA9SAEUARABNAE8ATgBEAAIADgBSAEUARABNAE8ATgBEAAEAHgBXAEkATgAtAEQARgBHADEAMABFADIAOABLADEANgAEADQAcgBlAGQAbQBvAG4AZAAuAGMAbwByAHAALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAAMAVABXAEkATgAtAEQARgBHADEAMABFADIAOABLADEANgAuAHIAZQBkAG0AbwBuAGQALgBjAG8AcgBwAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAFACQAYwBvAHIAcAAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ABwAIADJX/d1Cjc0BAAAAAA==");
            }

            // Require basic access authentication.
            if (request.QueryStringHasTrueValue("basic") && !IsAuthorizationValid(request))
            {
                response.Status = "401 Unauthorized";
                response.Headers.Add("WWW-Authenticate: Basic realm=\"Secure Area\"");
                request.Path = "";
            }

            // Require digest access authentication.
            if (request.QueryStringHasTrueValue("digest") && !IsAuthorizationValid(request))
            {
                response.Status = "401 Unauthorized";
                response.Headers.Add(String.Format(
                                         "WWW-Authenticate: Digest realm=\"{0}\", qop=\"{1}\", nonce=\"{2}\", opaque=\"{3}\"",
                                         digestRealm,
                                         digestQop,
                                         digestNonce,
                                         digestOpaque));
                request.Path = "";
            }

            // Require NTLM credentials.
            if (request.QueryStringHasTrueValue("negotiate") && !IsAuthorizationValid(request))
            {
                response.Status = "401 Unauthorized";
                response.Headers.Add("WWW-Authenticate: Negotiate");
                request.Path = "";
            }

            // NTLM authentication.
            if (request.QueryStringHasTrueValue("ntlm") && !IsAuthorizationValid(request))
            {
                response.Status = "401 Unauthorized";
                response.Headers.Add("WWW-Authenticate: NTLM");
                request.Path = "";
            }
        }