示例#1
0
        public void AuthenticateMessage()
        {
            NtlmChallengeMessageGenerator    type2Message = new NtlmChallengeMessageGenerator(type2Challenge);
            NtlmAuthenticateMessageGenerator generator    = new NtlmAuthenticateMessageGenerator(randomNumberGenerator, testTime, null, null, userName, password, type2Message.Challenge, type2Message.Flags, type2Message.Target, type2Message.TargetInfo);

            byte[] actualAuthBytes = generator.GetAuthorizationBytes();
            string actualAuthValue = generator.GetAuthorizationValue();

            string calculatedValue = Convert.ToBase64String(actualAuthBytes);

            Assert.That(calculatedValue, Is.EqualTo(expectedType3));
            Assert.That(actualAuthValue, Is.EqualTo(expectedType3));
        }
        public async Task TestNtlm()
        {
            string authType       = NtlmGenerator.AuthorizationHeaderMarker;
            string userName       = "******";
            string password       = "******";
            string relativeUri    = "/api/auth/ntlm";
            Uri    fullUri        = new Uri(baseUri, relativeUri);
            string initialRequest = CreateInitialRequest(fullUri);

            using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                socket.Connect("localhost", port);
                HttpResponse initialResponse = await SendRequestAndGetResponse(socket, initialRequest);

                Assert.That(initialResponse.StatusCode, Is.EqualTo(401));
                Assert.That(initialResponse.Headers.ContainsKey("WWW-Authenticate"));

                string authHeader = GetDesiredAuthHeader(authType, initialResponse);
                Assert.That(authHeader, Is.Not.Null);

                NtlmNegotiateMessageGenerator type1Generator = new NtlmNegotiateMessageGenerator();
                string       negotioateRequest = CreateRequest(fullUri, type1Generator.GenerateAuthorizationHeader());
                HttpResponse challengeResponse = await SendRequestAndGetResponse(socket, negotioateRequest);

                Assert.That(challengeResponse.StatusCode, Is.EqualTo(401));
                Assert.That(challengeResponse.Headers.ContainsKey("WWW-Authenticate"));

                string challengeAuthHeader = GetDesiredAuthHeader(authType, challengeResponse);
                Assert.That(challengeAuthHeader, Is.Not.Null);

                NtlmChallengeMessageGenerator    type2Generator = new NtlmChallengeMessageGenerator(challengeAuthHeader);
                NtlmAuthenticateMessageGenerator type3Generator = new NtlmAuthenticateMessageGenerator(null, null, userName, password, type2Generator);

                string       authorizeRequest   = CreateRequest(fullUri, type3Generator.GenerateAuthorizationHeader());
                HttpResponse authorizedResponse = await SendRequestAndGetResponse(socket, authorizeRequest);

                Assert.That(authorizedResponse.StatusCode, Is.EqualTo(200));
                socket.Close();
            }
        }
        private void ProcessResponse(ProcessingContext context)
        {
            // Only do any processing on the response if the response is 401,
            // or "Unauthorized".
            if (context.ResponseHeader != null && context.ResponseHeader.StatusCode == 401)
            {
                //context.ServerStream.ReadTimeout = 5000;
                //context.ServerStream.WriteTimeout = 5000;
                var reader = new StreamReader(context.ServerStream);
                if (context.ResponseHeader.EntityHeaders.ContentLength != 0)
                {
                    ReadFromStream(reader);
                }
                // We do not want the proxy to do any further processing after
                // handling this message.
                context.StopProcessing();


                if (context.ResponseHeader.WWWAuthenticate.Contains(BasicGenerator.AuthorizationHeaderMarker))
                {
                    // This is the generation of the HTTP Basic authorization header value.
                    var basicAuthHeaderValue = $"user:pass";
                    var encodedHeaderValue   = Convert.ToBase64String(Encoding.ASCII.GetBytes(basicAuthHeaderValue));
                    context.RequestHeader.Authorization = "Basic " + encodedHeaderValue;

                    // Resend the request (with the Authorization header) to the server
                    // using BenderProxy's HttpMessageWriter.
                    var writer = new HttpMessageWriter(context.ServerStream);
                    writer.Write(context.RequestHeader);

                    // Get the authorized response, and forward it on to the browser, using
                    // BenderProxy's HttpHeaderReader and support classes.
                    var    headerReader = new HttpHeaderReader(reader);
                    var    header       = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                    var    body         = ReadFromStream(reader);
                    Stream bodyStream   = new MemoryStream(Encoding.UTF8.GetBytes(body));
                    new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
                }
                else if (context.ResponseHeader.WWWAuthenticate.Contains(NtlmGenerator.AuthorizationHeaderMarker))
                {
                    // Read the WWW-Authenticate header. Because of the way the test
                    // web app is configured, it returns multiple headers, with
                    // different schemes. We need to select the correct one.
                    var authHeader = GetAuthenticationHeader(context.ResponseHeader.WWWAuthenticate,
                                                             NtlmGenerator.AuthorizationHeaderMarker);

                    var type1            = new NtlmNegotiateMessageGenerator();
                    var type1HeaderValue = type1.GenerateAuthorizationHeader();
                    context.RequestHeader.Authorization = type1HeaderValue;
                    var writer = new HttpMessageWriter(context.ServerStream);
                    writer.Write(context.RequestHeader);

                    var headerReader        = new HttpHeaderReader(reader);
                    var challengeHeader     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                    var challengeAuthHeader = challengeHeader.WWWAuthenticate;
                    var challengeBody       = ReadFromStream(reader);

                    if (!string.IsNullOrEmpty(challengeAuthHeader) &&
                        challengeAuthHeader.StartsWith(NtlmGenerator.AuthorizationHeaderMarker))
                    {
                        // If a proper message was received (the "type 2" or "Challenge" message),
                        // parse it, and generate the proper authentication header (the "type 3"
                        // or "Authorization" message).
                        var type2            = new NtlmChallengeMessageGenerator(challengeAuthHeader);
                        var type3            = new NtlmAuthenticateMessageGenerator(null, null, "user", "pass", type2);
                        var type3HeaderValue = type3.GenerateAuthorizationHeader();
                        context.RequestHeader.Authorization = type3HeaderValue;
                        writer.Write(context.RequestHeader);

                        // Get the authorized response from the server, and forward it on to
                        // the browser.
                        var    header     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                        var    body       = ReadFromStream(reader);
                        Stream bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
                        new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
                        context.ClientStream.Flush();
                    }
                }
            }
        }
示例#4
0
        /// <summary>
        /// Handles the OnResponseReceived for the proxy, which occurs after the response is
        /// received from the web server, but before it is forwarded on to the browser.
        /// </summary>
        /// <param name="context">A <see cref="BenderProxy.ProcessingContext"/> object.</param>
        public override void OnResponseReceived(ProcessingContext context)
        {
            string userName = "******";
            string password = "******";

            if (context.ResponseHeader != null && context.ResponseHeader.StatusCode == 401)
            {
                // Only process requests for localhost or the redirected-
                // via-hosts-file-entry host, and where NTLM auth is requested.
                List <string> candidateUrls = new List <string>()
                {
                    string.Format("localhost:{0}", TestWebAppPort), string.Format("{0}:{1}", TestWebAppHostName, TestWebAppPort)
                };
                if (candidateUrls.Contains(context.RequestHeader.Host) && context.ResponseHeader.WWWAuthenticate != null && context.ResponseHeader.WWWAuthenticate.Contains(NtlmGenerator.AuthorizationHeaderMarker))
                {
                    // Read the headers from the response and finish reading the response
                    // body, if any.
                    Console.WriteLine("Received 401 - Unauthorized response");
                    context.ServerStream.ReadTimeout  = 5000;
                    context.ServerStream.WriteTimeout = 5000;
                    StreamReader reader = new StreamReader(context.ServerStream);
                    if (context.ResponseHeader.EntityHeaders.ContentLength != 0)
                    {
                        string drainBody = ReadFromStream(reader);
                    }

                    // We do not want the proxy to do any further processing after
                    // handling this message.
                    context.StopProcessing();

                    // Read the WWW-Authenticate header. Because of the way the test
                    // web app is configured, it returns multiple headers, with
                    // different schemes. We need to select the correct one.
                    string authHeader = GetAuthenticationHeader(context.ResponseHeader.WWWAuthenticate, NtlmGenerator.AuthorizationHeaderMarker);
                    Console.WriteLine("Processing WWW-Authenticate header: {0}", authHeader);

                    // Generate the initial message (the "type 1" or "Negotiation" message")
                    // and get the response, using BenderProxy's HttpMessageWriter and
                    // HttpHeaderReader and support classes.
                    Console.WriteLine("Generating authorization header value for Negotiate ('Type 1') message");
                    NtlmNegotiateMessageGenerator type1 = new NtlmNegotiateMessageGenerator();
                    string type1HeaderValue             = type1.GenerateAuthorizationHeader();
                    context.RequestHeader.Authorization = type1HeaderValue;
                    Console.WriteLine("Resending request with Authorization header: {0}", type1HeaderValue);
                    HttpMessageWriter writer = new HttpMessageWriter(context.ServerStream);
                    writer.Write(context.RequestHeader);

                    HttpHeaderReader   headerReader        = new HttpHeaderReader(reader);
                    HttpResponseHeader challengeHeader     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                    string             challengeAuthHeader = challengeHeader.WWWAuthenticate;
                    string             challengeBody       = ReadFromStream(reader);

                    if (!string.IsNullOrEmpty(challengeAuthHeader) && challengeAuthHeader.StartsWith(NtlmGenerator.AuthorizationHeaderMarker))
                    {
                        // If a proper message was received (the "type 2" or "Challenge" message),
                        // parse it, and generate the proper authentication header (the "type 3"
                        // or "Authorization" message).
                        Console.WriteLine("Received 401 response with Challenge ('Type 2') message: {0}", challengeAuthHeader);
                        NtlmChallengeMessageGenerator type2 = new NtlmChallengeMessageGenerator(challengeAuthHeader);
                        Console.WriteLine("Generating Authorization ('Type 3') message for user name '{0}' and password '{1}'", userName, password);
                        NtlmAuthenticateMessageGenerator type3 = new NtlmAuthenticateMessageGenerator(null, null, userName, password, type2);
                        string type3HeaderValue = type3.GenerateAuthorizationHeader();
                        Console.WriteLine("Resending request with Authorization header: {0}", type3HeaderValue);
                        context.RequestHeader.Authorization = type3HeaderValue;
                        writer.Write(context.RequestHeader);

                        // Get the authorized response from the server, and forward it on to
                        // the browser.
                        HttpResponseHeader header     = new HttpResponseHeader(headerReader.ReadHttpMessageHeader());
                        string             body       = ReadFromStream(reader);
                        Stream             bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
                        new HttpResponseWriter(context.ClientStream).Write(header, bodyStream, bodyStream.Length);
                        context.ClientStream.Flush();
                    }
                }
            }
        }