1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/auth/TestNTLMAuth.java,v 1.2 2004/11/07 12:31:42 olegk Exp $
3    * $Revision: 160490 $
4    * $Date: 2005-04-07 19:03:43 -0400 (Thu, 07 Apr 2005) $
5    * ====================================================================
6    *
7    *  Copyright 1999-2004 The Apache Software Foundation
8    *
9    *  Licensed under the Apache License, Version 2.0 (the "License");
10   *  you may not use this file except in compliance with the License.
11   *  You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing, software
16   *  distributed under the License is distributed on an "AS IS" BASIS,
17   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   *  See the License for the specific language governing permissions and
19   *  limitations under the License.
20   * ====================================================================
21   *
22   * This software consists of voluntary contributions made by many
23   * individuals on behalf of the Apache Software Foundation.  For more
24   * information on the Apache Software Foundation, please see
25   * <http://www.apache.org/>.
26   *
27   */
28  
29  package org.apache.commons.httpclient.auth;
30  
31  import java.io.IOException;
32  
33  import junit.framework.Test;
34  import junit.framework.TestSuite;
35  
36  import org.apache.commons.httpclient.FakeHttpMethod;
37  import org.apache.commons.httpclient.Header;
38  import org.apache.commons.httpclient.HttpClientTestBase;
39  import org.apache.commons.httpclient.HttpState;
40  import org.apache.commons.httpclient.HttpStatus;
41  import org.apache.commons.httpclient.HttpVersion;
42  import org.apache.commons.httpclient.NTCredentials;
43  import org.apache.commons.httpclient.methods.GetMethod;
44  import org.apache.commons.httpclient.protocol.Protocol;
45  import org.apache.commons.httpclient.server.HttpService;
46  import org.apache.commons.httpclient.server.RequestLine;
47  import org.apache.commons.httpclient.server.SimpleRequest;
48  import org.apache.commons.httpclient.server.SimpleResponse;
49  
50  /***
51   * Test Methods for NTLM Authentication.
52   *
53   * @author Rodney Waldhoff
54   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
55   * @version $Id: TestNTLMAuth.java 160490 2005-04-07 23:03:43Z olegk $
56   */
57  public class TestNTLMAuth extends HttpClientTestBase {
58  
59      // ------------------------------------------------------------ Constructor
60      public TestNTLMAuth(String testName) throws IOException {
61          super(testName);
62      }
63  
64      // ------------------------------------------------------------------- Main
65      public static void main(String args[]) {
66          String[] testCaseName = { TestNTLMAuth.class.getName() };
67          junit.textui.TestRunner.main(testCaseName);
68      }
69  
70      // ------------------------------------------------------- TestCase Methods
71  
72      public static Test suite() {
73          return new TestSuite(TestNTLMAuth.class);
74      }
75  
76      // --------------------------------- 
77  
78      public void testNTLMAuthenticationResponse1() throws Exception {
79          String challenge = "NTLM";
80          String expected = "NTLM TlRMTVNTUAABAAAABlIAAAYABgAkAAAABAAEACAAAABIT" +
81              "1NURE9NQUlO";
82          NTCredentials cred = new NTCredentials("username","password", "host", "domain");
83          FakeHttpMethod method = new FakeHttpMethod(); 
84          AuthScheme authscheme = new NTLMScheme(challenge);
85          authscheme.processChallenge(challenge);
86          String response = authscheme.authenticate(cred, method);
87          assertEquals(expected, response);
88          assertFalse(authscheme.isComplete());
89      }
90      
91      public void testNTLMAuthenticationResponse2() throws Exception {
92          String challenge = 
93              "NTLM TlRMTVNTUAACAAAACgAKADAAAAAGgoEAPc4kP4LtCV8AAAAAAAAAAJ4AngA" +
94              "6AAAASU5UUkFFUEhPWAIAFABJAE4AVABSAEEARQBQAEgATwBYAAEAEgBCAE8AQQB" +
95              "SAEQAUgBPAE8ATQAEACgAaQBuAHQAcgBhAGUAcABoAG8AeAAuAGUAcABoAG8AeAA" +
96              "uAGMAbwBtAAMAPABCAG8AYQByAGQAcgBvAG8AbQAuAGkAbgB0AHIAYQBlAHAAaAB" +
97              "vAHgALgBlAHAAaABvAHgALgBjAG8AbQAAAAAA";
98  
99          String expected = "NTLM TlRMTVNTUAADAAAAGAAYAFIAAAAAAAAAagAAAAYABgB" +
100             "AAAAACAAIAEYAAAAEAAQATgAAAAAAAABqAAAABlIAAERPTUFJTlVTRVJOQU1FSE" +
101             "9TVAaC+vLxUEHnUtpItj9Dp4kzwQfd61Lztg==";
102         NTCredentials cred = new NTCredentials("username","password", "host", "domain");
103         FakeHttpMethod method = new FakeHttpMethod(); 
104         AuthScheme authscheme = new NTLMScheme(challenge);
105         authscheme.processChallenge(challenge);
106         String response = authscheme.authenticate(cred, method);
107         assertEquals(expected, response);
108         assertTrue(authscheme.isComplete());
109     }
110 
111     private class NTLMAuthService implements HttpService {
112 
113         public NTLMAuthService() {
114             super();
115         }
116 
117         public boolean process(final SimpleRequest request, final SimpleResponse response)
118             throws IOException
119         {
120             RequestLine requestLine = request.getRequestLine();
121             HttpVersion ver = requestLine.getHttpVersion();
122             Header auth = request.getFirstHeader("Authorization");
123             if (auth == null) { 
124                 response.setStatusLine(ver, HttpStatus.SC_UNAUTHORIZED);
125                 response.addHeader(new Header("WWW-Authenticate", "NTLM"));
126                 response.setBodyString("Authorization required");
127                 return true;
128             } else {
129                 String authstr = auth.getValue();
130                 
131                 if (authstr.equals("NTLM TlRMTVNTUAABAAAABlIAAAYABgAkAAAABAAEACAAAABIT1NURE9NQUlO")) {
132                     response.setStatusLine(ver, HttpStatus.SC_UNAUTHORIZED);
133                     response.addHeader(new Header("WWW-Authenticate", 
134                             "NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA=="));
135                     response.setBodyString("Authorization required");
136                     return true;
137                 } if (authstr.equals("NTLM TlRMTVNTUAADAAAAGAAYAFIAAAAAAAAAagAAAAYABgBAAAAACAAIAEYAAAAEAAQATgAAAAAAAABqAAAABlIAAERPTUFJTlVTRVJOQU1FSE9TVJxndWIt46bHm11TPrt5Z6wrz7ziq04yRA==")) {
138                     response.setStatusLine(ver, HttpStatus.SC_OK);
139                     response.setBodyString("Authorization successful");
140                     return true;
141                 } else {
142                     response.setStatusLine(ver, HttpStatus.SC_UNAUTHORIZED);
143                     response.addHeader(new Header("WWW-Authenticate", "NTLM"));
144                     response.setBodyString("Authorization required");
145                     return true;
146                 }
147             }
148         }
149     }
150 
151     
152     public void testNTLMAuthenticationRetry() throws Exception {
153 
154         this.server.setHttpService(new NTLMAuthService());
155 
156         // configure the client
157         this.client.getHostConfiguration().setHost(
158                 server.getLocalAddress(), server.getLocalPort(),
159                 Protocol.getProtocol("http"));
160         
161         this.client.getState().setCredentials(AuthScope.ANY, 
162                 new NTCredentials("username", "password", "host", "domain"));
163         
164         FakeHttpMethod httpget = new FakeHttpMethod("/");
165         try {
166             client.executeMethod(httpget);
167         } finally {
168             httpget.releaseConnection();
169         }
170         assertNull(httpget.getResponseHeader("WWW-Authenticate"));
171         assertEquals(200, httpget.getStatusCode());
172     }
173 
174     private class PreemptiveNTLMAuthService implements HttpService {
175 
176         public PreemptiveNTLMAuthService() {
177             super();
178         }
179 
180         public boolean process(final SimpleRequest request, final SimpleResponse response)
181             throws IOException
182         {
183             RequestLine requestLine = request.getRequestLine();
184             HttpVersion ver = requestLine.getHttpVersion();
185             Header auth = request.getFirstHeader("Authorization");
186             if (auth == null) { 
187                 response.setStatusLine(ver, HttpStatus.SC_BAD_REQUEST);
188                 response.setBodyString("Authorization header missing");
189                 return true;
190             } else {
191                 String authstr = auth.getValue();
192                 
193                 if (authstr.indexOf("NTLM") != -1) {
194                     response.setStatusLine(ver, HttpStatus.SC_OK);
195                     return true;
196                 } else if (authstr.indexOf("Basic") != -1) {
197                     response.setStatusLine(ver, HttpStatus.SC_UNAUTHORIZED);
198                     response.addHeader(new Header("WWW-Authenticate", "Negotiate"));
199                     response.addHeader(new Header("WWW-Authenticate", "NTLM"));
200                     response.setBodyString("Authorization required");
201                     return true;
202                 } else {
203                     response.setStatusLine(ver, HttpStatus.SC_BAD_REQUEST);
204                     response.setBodyString("Unknown auth type: " + authstr);
205                     return true;
206                 }
207             }
208         }
209     }
210 
211     /***
212      * Make sure preemptive authorization works when the server requires NLM.
213      * @throws Exception
214      */
215     public void testPreemptiveAuthorization() throws Exception {
216 
217         NTCredentials creds = 
218             new NTCredentials("testuser", "testpass", "host", "domain");
219         
220         HttpState state = new HttpState();
221         state.setCredentials(AuthScope.ANY, creds);
222         this.client.setState(state);
223         this.client.getParams().setAuthenticationPreemptive(true);
224 
225         this.server.setHttpService(new PreemptiveNTLMAuthService());
226 
227         GetMethod httpget = new GetMethod("/test/");
228         try {
229             this.client.executeMethod(httpget);
230         } finally {
231             httpget.releaseConnection();
232         }
233         assertNotNull(httpget.getStatusLine());
234         assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
235     }
236     
237     
238 }