1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.testing.sync;
28
29 import java.io.IOException;
30 import java.util.function.Consumer;
31
32 import org.apache.hc.client5.http.auth.CredentialsProvider;
33 import org.apache.hc.client5.http.auth.NTCredentials;
34 import org.apache.hc.client5.http.auth.StandardAuthScheme;
35 import org.apache.hc.client5.http.classic.methods.HttpGet;
36 import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
37 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
38 import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
39 import org.apache.hc.client5.http.protocol.HttpClientContext;
40 import org.apache.hc.client5.testing.sync.extension.TestClientResources;
41 import org.apache.hc.core5.http.ClassicHttpRequest;
42 import org.apache.hc.core5.http.ClassicHttpResponse;
43 import org.apache.hc.core5.http.HttpException;
44 import org.apache.hc.core5.http.HttpHeaders;
45 import org.apache.hc.core5.http.HttpHost;
46 import org.apache.hc.core5.http.HttpStatus;
47 import org.apache.hc.core5.http.URIScheme;
48 import org.apache.hc.core5.http.io.HttpRequestHandler;
49 import org.apache.hc.core5.http.io.entity.EntityUtils;
50 import org.apache.hc.core5.http.protocol.HttpContext;
51 import org.apache.hc.core5.testing.classic.ClassicTestServer;
52 import org.apache.hc.core5.util.Timeout;
53 import org.junit.jupiter.api.Assertions;
54 import org.junit.jupiter.api.Test;
55 import org.junit.jupiter.api.extension.RegisterExtension;
56
57
58
59
60 public class TestClientAuthenticationFakeNTLM {
61
62 public static final Timeout TIMEOUT = Timeout.ofMinutes(1);
63
64 @RegisterExtension
65 private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT);
66
67 public ClassicTestServer startServer() throws IOException {
68 return testResources.startServer(null, null, null);
69 }
70
71 public CloseableHttpClient startClient(final Consumer<HttpClientBuilder> clientCustomizer) throws Exception {
72 return testResources.startClient(clientCustomizer);
73 }
74
75 public CloseableHttpClient startClient() throws Exception {
76 return testResources.startClient(builder -> {});
77 }
78
79 public HttpHost targetHost() {
80 return testResources.targetHost();
81 }
82
83 static class NtlmResponseHandler implements HttpRequestHandler {
84
85 @Override
86 public void handle(
87 final ClassicHttpRequest request,
88 final ClassicHttpResponse response,
89 final HttpContext context) throws HttpException, IOException {
90 response.setCode(HttpStatus.SC_UNAUTHORIZED);
91 response.setHeader("Connection", "Keep-Alive");
92 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.NTLM);
93 }
94 }
95
96 @Test
97 public void testNTLMAuthenticationFailure() throws Exception {
98 final ClassicTestServer server = startServer();
99 server.registerHandler("*", new NtlmResponseHandler());
100 final HttpHost target = targetHost();
101
102 final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
103 .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
104 .build();
105
106 final CloseableHttpClient client = startClient(builder -> builder
107 .setDefaultCredentialsProvider(credsProvider)
108 );
109
110 final HttpContext context = HttpClientContext.create();
111 final HttpGet httpget = new HttpGet("/");
112
113 client.execute(target, httpget, context, response -> {
114 EntityUtils.consume(response.getEntity());
115 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
116 return null;
117 });
118 }
119
120 static class NtlmType2MessageResponseHandler implements HttpRequestHandler {
121
122 private final String authenticateHeaderValue;
123
124 public NtlmType2MessageResponseHandler(final String type2Message) {
125 this.authenticateHeaderValue = StandardAuthScheme.NTLM + " " + type2Message;
126 }
127
128 @Override
129 public void handle(
130 final ClassicHttpRequest request,
131 final ClassicHttpResponse response,
132 final HttpContext context) throws HttpException, IOException {
133 response.setCode(HttpStatus.SC_UNAUTHORIZED);
134 response.setHeader("Connection", "Keep-Alive");
135 if (!request.containsHeader(HttpHeaders.AUTHORIZATION)) {
136 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.NTLM);
137 } else {
138 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, authenticateHeaderValue);
139 }
140 }
141 }
142
143 @Test
144 public void testNTLMv1Type2Message() throws Exception {
145 final ClassicTestServer server = startServer();
146 server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" +
147 "AADAAMADgAAAAzggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" +
148 "AGUAcgB2AGUAcgA="));
149 final HttpHost target = targetHost();
150
151 final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
152 .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
153 .build();
154
155 final CloseableHttpClient client = startClient(builder -> builder
156 .setDefaultCredentialsProvider(credsProvider)
157 );
158
159 final HttpContext context = HttpClientContext.create();
160 final HttpGet httpget = new HttpGet("/");
161
162 client.execute(target, httpget, context, response -> {
163 EntityUtils.consume(response.getEntity());
164 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
165 return null;
166 });
167 }
168
169 @Test
170 public void testNTLMv2Type2Message() throws Exception {
171 final ClassicTestServer server = startServer();
172 server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" +
173 "AADAAMADgAAAAzgoriASNFZ4mrze8AAAAAAAAAACQAJABEAAAABgBwFwAAAA9T" +
174 "AGUAcgB2AGUAcgACAAwARABvAG0AYQBpAG4AAQAMAFMAZQByAHYAZQByAAAAAAA="));
175 final HttpHost target = targetHost();
176
177 final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
178 .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
179 .build();
180
181 final CloseableHttpClient client = startClient(builder -> builder
182 .setDefaultCredentialsProvider(credsProvider)
183 );
184
185 final HttpContext context = HttpClientContext.create();
186 final HttpGet httpget = new HttpGet("/");
187
188 client.execute(target, httpget, context, response -> {
189 EntityUtils.consume(response.getEntity());
190 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
191 return null;
192 });
193 }
194
195 static class NtlmType2MessageOnlyResponseHandler implements HttpRequestHandler {
196
197 private final String authenticateHeaderValue;
198
199 public NtlmType2MessageOnlyResponseHandler(final String type2Message) {
200 this.authenticateHeaderValue = StandardAuthScheme.NTLM + " " + type2Message;
201 }
202
203 @Override
204 public void handle(
205 final ClassicHttpRequest request,
206 final ClassicHttpResponse response,
207 final HttpContext context) throws HttpException, IOException {
208 response.setCode(HttpStatus.SC_UNAUTHORIZED);
209 response.setHeader("Connection", "Keep-Alive");
210 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, authenticateHeaderValue);
211 }
212 }
213
214 @Test
215 public void testNTLMType2MessageOnlyAuthenticationFailure() throws Exception {
216 final ClassicTestServer server = startServer();
217 server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" +
218 "AADAAMADgAAAAzggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" +
219 "AGUAcgB2AGUAcgA="));
220 final HttpHost target = targetHost();
221
222 final CloseableHttpClient client = startClient();
223
224 final HttpClientContext context = HttpClientContext.create();
225 context.setCredentialsProvider(CredentialsProviderBuilder.create()
226 .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
227 .build());
228 final HttpGet httpget = new HttpGet("/");
229
230 client.execute(target, httpget, context, response -> {
231 EntityUtils.consume(response.getEntity());
232 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
233 return null;
234 });
235 }
236
237 @Test
238 public void testNTLMType2NonUnicodeMessageOnlyAuthenticationFailure() throws Exception {
239 final ClassicTestServer server = startServer();
240 server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" +
241 "AABgAGADgAAAAyggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" +
242 "ZXJ2ZXI="));
243 final HttpHost target = targetHost();
244
245
246 final CloseableHttpClient client = startClient();
247
248 final HttpClientContext context = HttpClientContext.create();
249 context.setCredentialsProvider(CredentialsProviderBuilder.create()
250 .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
251 .build());
252 final HttpGet httpget = new HttpGet("/");
253
254 client.execute(target, httpget, context, response -> {
255 EntityUtils.consume(response.getEntity());
256 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
257 return null;
258 });
259 }
260
261 }