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.security.Principal;
31
32 import org.apache.hc.client5.http.SystemDefaultDnsResolver;
33 import org.apache.hc.client5.http.auth.AuthScheme;
34 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
35 import org.apache.hc.client5.http.auth.AuthScope;
36 import org.apache.hc.client5.http.auth.Credentials;
37 import org.apache.hc.client5.http.auth.CredentialsProvider;
38 import org.apache.hc.client5.http.auth.KerberosConfig;
39 import org.apache.hc.client5.http.auth.StandardAuthScheme;
40 import org.apache.hc.client5.http.classic.methods.HttpGet;
41 import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
42 import org.apache.hc.client5.http.impl.auth.SPNegoScheme;
43 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
44 import org.apache.hc.client5.testing.sync.extension.TestClientResources;
45 import org.apache.hc.core5.http.ClassicHttpRequest;
46 import org.apache.hc.core5.http.ClassicHttpResponse;
47 import org.apache.hc.core5.http.HttpException;
48 import org.apache.hc.core5.http.HttpHost;
49 import org.apache.hc.core5.http.HttpStatus;
50 import org.apache.hc.core5.http.URIScheme;
51 import org.apache.hc.core5.http.config.Registry;
52 import org.apache.hc.core5.http.config.RegistryBuilder;
53 import org.apache.hc.core5.http.io.HttpRequestHandler;
54 import org.apache.hc.core5.http.io.entity.EntityUtils;
55 import org.apache.hc.core5.http.io.entity.StringEntity;
56 import org.apache.hc.core5.http.message.BasicHeader;
57 import org.apache.hc.core5.http.protocol.HttpContext;
58 import org.apache.hc.core5.testing.classic.ClassicTestServer;
59 import org.apache.hc.core5.util.Timeout;
60 import org.ietf.jgss.GSSContext;
61 import org.ietf.jgss.GSSManager;
62 import org.ietf.jgss.GSSName;
63 import org.junit.jupiter.api.Assertions;
64 import org.junit.jupiter.api.Test;
65 import org.junit.jupiter.api.extension.RegisterExtension;
66 import org.mockito.ArgumentMatchers;
67 import org.mockito.Mockito;
68
69
70
71
72 public class TestSPNegoScheme {
73
74 public static final Timeout TIMEOUT = Timeout.ofMinutes(1);
75
76 @RegisterExtension
77 private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT);
78
79
80
81
82 private static class PleaseNegotiateService implements HttpRequestHandler {
83
84 @Override
85 public void handle(
86 final ClassicHttpRequest request,
87 final ClassicHttpResponse response,
88 final HttpContext context) throws HttpException, IOException {
89 response.setCode(HttpStatus.SC_UNAUTHORIZED);
90 response.addHeader(new BasicHeader("WWW-Authenticate", StandardAuthScheme.SPNEGO + " blablabla"));
91 response.addHeader(new BasicHeader("Connection", "Keep-Alive"));
92 response.setEntity(new StringEntity("auth required "));
93 }
94 }
95
96
97
98
99
100
101 private static class NegotiateSchemeWithMockGssManager extends SPNegoScheme {
102
103 final GSSManager manager = Mockito.mock(GSSManager.class);
104 final GSSName name = Mockito.mock(GSSName.class);
105 final GSSContext context = Mockito.mock(GSSContext.class);
106
107 NegotiateSchemeWithMockGssManager() throws Exception {
108 super(KerberosConfig.DEFAULT, SystemDefaultDnsResolver.INSTANCE);
109 Mockito.when(context.initSecContext(
110 ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()))
111 .thenReturn("12345678".getBytes());
112 Mockito.when(manager.createName(
113 ArgumentMatchers.anyString(), ArgumentMatchers.any()))
114 .thenReturn(name);
115 Mockito.when(manager.createContext(
116 ArgumentMatchers.any(), ArgumentMatchers.any(),
117 ArgumentMatchers.any(), ArgumentMatchers.anyInt()))
118 .thenReturn(context);
119 }
120
121 @Override
122 protected GSSManager getManager() {
123 return manager;
124 }
125
126 }
127
128 private static class UseJaasCredentials implements Credentials {
129
130 @Override
131 public char[] getPassword() {
132 return null;
133 }
134
135 @Override
136 public Principal getUserPrincipal() {
137 return null;
138 }
139
140 }
141
142 private static class NegotiateSchemeFactoryWithMockGssManager implements AuthSchemeFactory {
143
144 NegotiateSchemeWithMockGssManager scheme;
145
146 NegotiateSchemeFactoryWithMockGssManager() throws Exception {
147 scheme = new NegotiateSchemeWithMockGssManager();
148 }
149
150 @Override
151 public AuthScheme create(final HttpContext context) {
152 return scheme;
153 }
154
155 }
156
157
158
159
160
161 @Test
162 public void testDontTryToAuthenticateEndlessly() throws Exception {
163 final ClassicTestServer server = testResources.startServer(null, null, null);
164 server.registerHandler("*", new PleaseNegotiateService());
165 final HttpHost target = testResources.targetHost();
166
167 final AuthSchemeFactory nsf = new NegotiateSchemeFactoryWithMockGssManager();
168 final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
169 .add(new AuthScope(null, null, -1, null, null), new UseJaasCredentials())
170 .build();
171
172 final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
173 .register(StandardAuthScheme.SPNEGO, nsf)
174 .build();
175
176 final CloseableHttpClient client = testResources.startClient(builder -> builder
177 .setDefaultAuthSchemeRegistry(authSchemeRegistry)
178 .setDefaultCredentialsProvider(credentialsProvider)
179 );
180
181 final String s = "/path";
182 final HttpGet httpget = new HttpGet(s);
183 client.execute(target, httpget, response -> {
184 EntityUtils.consume(response.getEntity());
185 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
186 return null;
187 });
188 }
189
190
191
192
193
194 @Test
195 public void testNoTokenGeneratedError() throws Exception {
196 final ClassicTestServer server = testResources.startServer(null, null, null);
197 server.registerHandler("*", new PleaseNegotiateService());
198 final HttpHost target = testResources.targetHost();
199
200 final AuthSchemeFactory nsf = new NegotiateSchemeFactoryWithMockGssManager();
201
202 final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
203 .add(new AuthScope(null, null, -1, null, null), new UseJaasCredentials())
204 .build();
205
206 final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
207 .register(StandardAuthScheme.SPNEGO, nsf)
208 .build();
209
210 final CloseableHttpClient client = testResources.startClient(builder -> builder
211 .setDefaultAuthSchemeRegistry(authSchemeRegistry)
212 .setDefaultCredentialsProvider(credentialsProvider)
213 );
214
215 final String s = "/path";
216 final HttpGet httpget = new HttpGet(s);
217 client.execute(target, httpget, response -> {
218 EntityUtils.consume(response.getEntity());
219 Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
220 return null;
221 });
222
223 }
224
225 }