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