Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/jdk/sun/security/krb5/auto/HttpsCB.java
66646 views
1
/*
2
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 8279842 8282293
27
* @modules java.base/sun.security.util
28
* java.security.jgss/sun.security.jgss
29
* java.security.jgss/sun.security.jgss.krb5
30
* java.security.jgss/sun.security.jgss.krb5.internal
31
* java.security.jgss/sun.security.krb5.internal:+open
32
* java.security.jgss/sun.security.krb5:+open
33
* java.security.jgss/sun.security.krb5.internal.ccache
34
* java.security.jgss/sun.security.krb5.internal.crypto
35
* java.security.jgss/sun.security.krb5.internal.ktab
36
* jdk.security.auth
37
* jdk.security.jgss
38
* jdk.httpserver
39
* @summary HTTPS Channel Binding support for Java GSS/Kerberos
40
* @library /test/lib
41
* @run main jdk.test.lib.FileInstaller TestHosts TestHosts
42
* @run main/othervm -Djdk.net.hosts.file=TestHosts
43
* -Djdk.https.negotiate.cbt=always HttpsCB true true
44
* @run main/othervm -Djdk.net.hosts.file=TestHosts
45
* -Djdk.https.negotiate.cbt=never HttpsCB false true
46
* @run main/othervm -Djdk.net.hosts.file=TestHosts
47
* -Djdk.https.negotiate.cbt=invalid HttpsCB false true
48
* @run main/othervm -Djdk.net.hosts.file=TestHosts
49
* HttpsCB false true
50
* @run main/othervm -Djdk.net.hosts.file=TestHosts
51
* -Djdk.https.negotiate.cbt=domain:other.com HttpsCB false true
52
* @run main/othervm -Djdk.net.hosts.file=TestHosts
53
* -Djdk.https.negotiate.cbt=domain:host.web.domain HttpsCB true true
54
* @run main/othervm -Djdk.net.hosts.file=TestHosts
55
* -Djdk.https.negotiate.cbt=domain:HOST.WEB.DOMAIN HttpsCB true true
56
* @run main/othervm -Djdk.net.hosts.file=TestHosts
57
* -Djdk.https.negotiate.cbt=domain:*.web.domain HttpsCB true true
58
* @run main/othervm -Djdk.net.hosts.file=TestHosts
59
* -Djdk.https.negotiate.cbt=domain:*.WEB.Domain HttpsCB true true
60
* @run main/othervm -Djdk.net.hosts.file=TestHosts
61
* -Djdk.https.negotiate.cbt=domain:*.Invalid,*.WEB.Domain HttpsCB true true
62
*/
63
64
import com.sun.net.httpserver.Headers;
65
import com.sun.net.httpserver.HttpExchange;
66
import com.sun.net.httpserver.HttpHandler;
67
import com.sun.net.httpserver.HttpServer;
68
import com.sun.net.httpserver.HttpPrincipal;
69
import com.sun.net.httpserver.HttpsConfigurator;
70
import com.sun.net.httpserver.HttpsExchange;
71
import com.sun.net.httpserver.HttpsServer;
72
import com.sun.security.auth.module.Krb5LoginModule;
73
import java.io.BufferedReader;
74
import java.io.File;
75
import java.io.FileOutputStream;
76
import java.io.IOException;
77
import java.io.InputStreamReader;
78
import java.net.HttpURLConnection;
79
import java.net.InetSocketAddress;
80
import java.net.PasswordAuthentication;
81
import java.net.Proxy;
82
import java.net.Socket;
83
import java.net.URL;
84
import java.security.cert.X509Certificate;
85
import java.security.PrivilegedExceptionAction;
86
import java.util.HashMap;
87
import java.util.Map;
88
import javax.net.ssl.HttpsURLConnection;
89
import javax.net.ssl.SSLContext;
90
import javax.net.ssl.SSLEngine;
91
import javax.net.ssl.TrustManager;
92
import javax.net.ssl.X509ExtendedTrustManager;
93
import javax.security.auth.Subject;
94
95
import jdk.test.lib.Asserts;
96
import jdk.test.lib.net.SimpleSSLContext;
97
import org.ietf.jgss.GSSContext;
98
import org.ietf.jgss.GSSCredential;
99
import org.ietf.jgss.GSSManager;
100
import sun.security.jgss.GSSUtil;
101
import sun.security.jgss.krb5.internal.TlsChannelBindingImpl;
102
import sun.security.krb5.Config;
103
import sun.security.util.TlsChannelBinding;
104
105
import java.util.Base64;
106
import java.util.concurrent.Callable;
107
108
public class HttpsCB {
109
110
final static String REALM_WEB = "WEB.DOMAIN";
111
final static String KRB5_CONF = "web.conf";
112
final static String KRB5_TAB = "web.ktab";
113
114
final static String WEB_USER = "web";
115
final static char[] WEB_PASS = "webby".toCharArray();
116
final static String WEB_HOST = "host.web.domain";
117
final static String CONTENT = "Hello, World!";
118
119
static int webPort;
120
static URL cbtURL;
121
static URL normalURL;
122
123
public static void main(String[] args)
124
throws Exception {
125
126
boolean expectCBT = Boolean.parseBoolean(args[0]);
127
boolean expectNoCBT = Boolean.parseBoolean(args[1]);
128
129
System.setProperty("sun.security.krb5.debug", "true");
130
131
KDC kdcw = KDC.create(REALM_WEB);
132
kdcw.addPrincipal(WEB_USER, WEB_PASS);
133
kdcw.addPrincipalRandKey("krbtgt/" + REALM_WEB);
134
kdcw.addPrincipalRandKey("HTTP/" + WEB_HOST);
135
136
KDC.saveConfig(KRB5_CONF, kdcw,
137
"default_keytab_name = " + KRB5_TAB,
138
"[domain_realm]",
139
"",
140
".web.domain="+REALM_WEB);
141
142
System.setProperty("java.security.krb5.conf", KRB5_CONF);
143
Config.refresh();
144
KDC.writeMultiKtab(KRB5_TAB, kdcw);
145
146
// Write a customized JAAS conf file, so that any kinit cache
147
// will be ignored.
148
System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
149
File f = new File(OneKDC.JAAS_CONF);
150
FileOutputStream fos = new FileOutputStream(f);
151
fos.write((
152
"com.sun.security.jgss.krb5.initiate {\n" +
153
" com.sun.security.auth.module.Krb5LoginModule required;\n};\n"
154
).getBytes());
155
fos.close();
156
157
HttpServer h1 = httpd("Negotiate",
158
"HTTP/" + WEB_HOST + "@" + REALM_WEB, KRB5_TAB);
159
webPort = h1.getAddress().getPort();
160
161
cbtURL = new URL("https://" + WEB_HOST +":" + webPort + "/cbt");
162
normalURL = new URL("https://" + WEB_HOST +":" + webPort + "/normal");
163
164
java.net.Authenticator.setDefault(new java.net.Authenticator() {
165
public PasswordAuthentication getPasswordAuthentication () {
166
return new PasswordAuthentication(
167
WEB_USER+"@"+REALM_WEB, WEB_PASS);
168
}
169
});
170
171
// Client-side SSLContext needs to ignore hostname mismatch
172
// and untrusted certificate.
173
SSLContext sc = SSLContext.getInstance("SSL");
174
sc.init(null, new TrustManager[] {
175
new X509ExtendedTrustManager() {
176
public X509Certificate[] getAcceptedIssuers() {
177
return null;
178
}
179
public void checkClientTrusted(X509Certificate[] chain,
180
String authType, Socket socket) { }
181
public void checkServerTrusted(X509Certificate[] chain,
182
String authType, Socket socket) { }
183
public void checkClientTrusted(X509Certificate[] chain,
184
String authType, SSLEngine engine) { }
185
public void checkServerTrusted(X509Certificate[] chain,
186
String authType, SSLEngine engine) { }
187
public void checkClientTrusted(X509Certificate[] certs,
188
String authType) { }
189
public void checkServerTrusted(X509Certificate[] certs,
190
String authType) { }
191
}
192
}, null);
193
194
Asserts.assertEQ(visit(sc, cbtURL), expectCBT);
195
Asserts.assertEQ(visit(sc, normalURL), expectNoCBT);
196
}
197
198
static boolean visit(SSLContext sc, URL url) {
199
try {
200
HttpsURLConnection conn = (HttpsURLConnection)
201
url.openConnection(Proxy.NO_PROXY);
202
conn.setSSLSocketFactory(sc.getSocketFactory());
203
BufferedReader reader;
204
reader = new BufferedReader(new InputStreamReader(
205
conn.getInputStream()));
206
return reader.readLine().equals(CONTENT);
207
} catch (IOException e) {
208
e.printStackTrace(System.out);
209
return false;
210
}
211
}
212
213
static HttpServer httpd(String scheme, String principal, String ktab)
214
throws Exception {
215
MyHttpHandler h = new MyHttpHandler();
216
HttpsServer server = HttpsServer.create(new InetSocketAddress(0), 0);
217
server.setHttpsConfigurator(
218
new HttpsConfigurator(new SimpleSSLContext().get()));
219
server.createContext("/", h).setAuthenticator(
220
new MyServerAuthenticator(scheme, principal, ktab));
221
server.start();
222
return server;
223
}
224
225
static class MyHttpHandler implements HttpHandler {
226
public void handle(HttpExchange t) throws IOException {
227
t.sendResponseHeaders(200, 0);
228
t.getResponseBody().write(CONTENT.getBytes());
229
t.close();
230
}
231
}
232
233
static class MyServerAuthenticator
234
extends com.sun.net.httpserver.Authenticator {
235
Subject s = new Subject();
236
GSSManager m;
237
GSSCredential cred;
238
String scheme = null;
239
String reqHdr = "WWW-Authenticate";
240
String respHdr = "Authorization";
241
int err = HttpURLConnection.HTTP_UNAUTHORIZED;
242
243
public MyServerAuthenticator(String scheme,
244
String principal, String ktab) throws Exception {
245
246
this.scheme = scheme;
247
Krb5LoginModule krb5 = new Krb5LoginModule();
248
Map<String, String> map = new HashMap<>();
249
Map<String, Object> shared = new HashMap<>();
250
251
map.put("storeKey", "true");
252
map.put("isInitiator", "false");
253
map.put("useKeyTab", "true");
254
map.put("keyTab", ktab);
255
map.put("principal", principal);
256
krb5.initialize(s, null, shared, map);
257
krb5.login();
258
krb5.commit();
259
m = GSSManager.getInstance();
260
cred = Subject.doAs(s, new PrivilegedExceptionAction<GSSCredential>() {
261
@Override
262
public GSSCredential run() throws Exception {
263
System.err.println("Creating GSSCredential");
264
return m.createCredential(
265
null,
266
GSSCredential.INDEFINITE_LIFETIME,
267
MyServerAuthenticator.this.scheme
268
.equalsIgnoreCase("Negotiate") ?
269
GSSUtil.GSS_SPNEGO_MECH_OID :
270
GSSUtil.GSS_KRB5_MECH_OID,
271
GSSCredential.ACCEPT_ONLY);
272
}
273
});
274
}
275
276
@Override
277
public Result authenticate(HttpExchange exch) {
278
// The GSContext is stored in an HttpContext attribute named
279
// "GSSContext" and is created at the first request.
280
GSSContext c = null;
281
String auth = exch.getRequestHeaders().getFirst(respHdr);
282
try {
283
c = (GSSContext)exch.getHttpContext()
284
.getAttributes().get("GSSContext");
285
if (auth == null) { // First request
286
Headers map = exch.getResponseHeaders();
287
map.set (reqHdr, scheme); // Challenge!
288
c = Subject.doAs(s, new PrivilegedExceptionAction<GSSContext>() {
289
@Override
290
public GSSContext run() throws Exception {
291
return m.createContext(cred);
292
}
293
});
294
// CBT is required for cbtURL
295
if (exch instanceof HttpsExchange sexch
296
&& exch.getRequestURI().toString().equals("/cbt")) {
297
TlsChannelBinding b = TlsChannelBinding.create(
298
(X509Certificate) sexch.getSSLSession()
299
.getLocalCertificates()[0]);
300
c.setChannelBinding(
301
new TlsChannelBindingImpl(b.getData()));
302
}
303
exch.getHttpContext().getAttributes().put("GSSContext", c);
304
return new com.sun.net.httpserver.Authenticator.Retry(err);
305
} else { // Later requests
306
byte[] token = Base64.getMimeDecoder()
307
.decode(auth.split(" ")[1]);
308
token = c.acceptSecContext(token, 0, token.length);
309
Headers map = exch.getResponseHeaders();
310
map.set (reqHdr, scheme + " " + Base64.getMimeEncoder()
311
.encodeToString(token).replaceAll("\\s", ""));
312
if (c.isEstablished()) {
313
return new com.sun.net.httpserver.Authenticator.Success(
314
new HttpPrincipal(c.getSrcName().toString(), ""));
315
} else {
316
return new com.sun.net.httpserver.Authenticator.Retry(err);
317
}
318
}
319
} catch (Exception e) {
320
throw new RuntimeException(e);
321
}
322
}
323
}
324
}
325
326