Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java
38922 views
1
/*
2
* Copyright (c) 2000, 2013, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.jgss.krb5;
27
28
import org.ietf.jgss.*;
29
import javax.security.auth.kerberos.DelegationPermission;
30
import java.io.IOException;
31
import java.net.InetAddress;
32
import java.net.Inet4Address;
33
import java.net.Inet6Address;
34
import java.security.MessageDigest;
35
import java.security.NoSuchAlgorithmException;
36
import java.util.Arrays;
37
import sun.security.krb5.*;
38
import sun.security.krb5.internal.Krb5;
39
40
abstract class InitialToken extends Krb5Token {
41
42
private static final int CHECKSUM_TYPE = 0x8003;
43
44
private static final int CHECKSUM_LENGTH_SIZE = 4;
45
private static final int CHECKSUM_BINDINGS_SIZE = 16;
46
private static final int CHECKSUM_FLAGS_SIZE = 4;
47
private static final int CHECKSUM_DELEG_OPT_SIZE = 2;
48
private static final int CHECKSUM_DELEG_LGTH_SIZE = 2;
49
50
private static final int CHECKSUM_DELEG_FLAG = 1;
51
private static final int CHECKSUM_MUTUAL_FLAG = 2;
52
private static final int CHECKSUM_REPLAY_FLAG = 4;
53
private static final int CHECKSUM_SEQUENCE_FLAG = 8;
54
private static final int CHECKSUM_CONF_FLAG = 16;
55
private static final int CHECKSUM_INTEG_FLAG = 32;
56
57
private final byte[] CHECKSUM_FIRST_BYTES =
58
{(byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00};
59
60
private static final int CHANNEL_BINDING_AF_INET = 2;
61
private static final int CHANNEL_BINDING_AF_INET6 = 24;
62
private static final int CHANNEL_BINDING_AF_NULL_ADDR = 255;
63
64
private static final int Inet4_ADDRSZ = 4;
65
private static final int Inet6_ADDRSZ = 16;
66
67
protected class OverloadedChecksum {
68
69
private byte[] checksumBytes = null;
70
private Credentials delegCreds = null;
71
private int flags = 0;
72
73
/**
74
* Called on the initiator side when creating the
75
* InitSecContextToken.
76
*/
77
public OverloadedChecksum(Krb5Context context,
78
Credentials tgt,
79
Credentials serviceTicket)
80
throws KrbException, IOException, GSSException {
81
82
byte[] krbCredMessage = null;
83
int pos = 0;
84
int size = CHECKSUM_LENGTH_SIZE + CHECKSUM_BINDINGS_SIZE +
85
CHECKSUM_FLAGS_SIZE;
86
87
if (!tgt.isForwardable()) {
88
context.setCredDelegState(false);
89
context.setDelegPolicyState(false);
90
} else if (context.getCredDelegState()) {
91
if (context.getDelegPolicyState()) {
92
if (!serviceTicket.checkDelegate()) {
93
// delegation not permitted by server policy, mark it
94
context.setDelegPolicyState(false);
95
}
96
}
97
} else if (context.getDelegPolicyState()) {
98
if (serviceTicket.checkDelegate()) {
99
context.setCredDelegState(true);
100
} else {
101
context.setDelegPolicyState(false);
102
}
103
}
104
105
if (context.getCredDelegState()) {
106
KrbCred krbCred = null;
107
CipherHelper cipherHelper =
108
context.getCipherHelper(serviceTicket.getSessionKey());
109
if (useNullKey(cipherHelper)) {
110
krbCred = new KrbCred(tgt, serviceTicket,
111
EncryptionKey.NULL_KEY);
112
} else {
113
krbCred = new KrbCred(tgt, serviceTicket,
114
serviceTicket.getSessionKey());
115
}
116
krbCredMessage = krbCred.getMessage();
117
size += CHECKSUM_DELEG_OPT_SIZE +
118
CHECKSUM_DELEG_LGTH_SIZE +
119
krbCredMessage.length;
120
}
121
122
checksumBytes = new byte[size];
123
124
checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[0];
125
checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[1];
126
checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[2];
127
checksumBytes[pos++] = CHECKSUM_FIRST_BYTES[3];
128
129
ChannelBinding localBindings = context.getChannelBinding();
130
if (localBindings != null) {
131
byte[] localBindingsBytes =
132
computeChannelBinding(context.getChannelBinding());
133
System.arraycopy(localBindingsBytes, 0,
134
checksumBytes, pos, localBindingsBytes.length);
135
// System.out.println("ChannelBinding hash: "
136
// + getHexBytes(localBindingsBytes));
137
}
138
139
pos += CHECKSUM_BINDINGS_SIZE;
140
141
if (context.getCredDelegState())
142
flags |= CHECKSUM_DELEG_FLAG;
143
if (context.getMutualAuthState())
144
flags |= CHECKSUM_MUTUAL_FLAG;
145
if (context.getReplayDetState())
146
flags |= CHECKSUM_REPLAY_FLAG;
147
if (context.getSequenceDetState())
148
flags |= CHECKSUM_SEQUENCE_FLAG;
149
if (context.getIntegState())
150
flags |= CHECKSUM_INTEG_FLAG;
151
if (context.getConfState())
152
flags |= CHECKSUM_CONF_FLAG;
153
154
byte[] temp = new byte[4];
155
writeLittleEndian(flags, temp);
156
checksumBytes[pos++] = temp[0];
157
checksumBytes[pos++] = temp[1];
158
checksumBytes[pos++] = temp[2];
159
checksumBytes[pos++] = temp[3];
160
161
if (context.getCredDelegState()) {
162
163
PrincipalName delegateTo =
164
serviceTicket.getServer();
165
// Cannot use '\"' instead of "\"" in constructor because
166
// it is interpreted as suggested length!
167
StringBuffer buf = new StringBuffer("\"");
168
buf.append(delegateTo.getName()).append('\"');
169
String realm = delegateTo.getRealmAsString();
170
buf.append(" \"krbtgt/").append(realm).append('@');
171
buf.append(realm).append('\"');
172
SecurityManager sm = System.getSecurityManager();
173
if (sm != null) {
174
DelegationPermission perm =
175
new DelegationPermission(buf.toString());
176
sm.checkPermission(perm);
177
}
178
179
180
/*
181
* Write 1 in little endian but in two bytes
182
* for DlgOpt
183
*/
184
185
checksumBytes[pos++] = (byte)0x01;
186
checksumBytes[pos++] = (byte)0x00;
187
188
/*
189
* Write the length of the delegated credential in little
190
* endian but in two bytes for Dlgth
191
*/
192
193
if (krbCredMessage.length > 0x0000ffff)
194
throw new GSSException(GSSException.FAILURE, -1,
195
"Incorrect message length");
196
197
writeLittleEndian(krbCredMessage.length, temp);
198
checksumBytes[pos++] = temp[0];
199
checksumBytes[pos++] = temp[1];
200
System.arraycopy(krbCredMessage, 0,
201
checksumBytes, pos, krbCredMessage.length);
202
}
203
204
}
205
206
/**
207
* Called on the acceptor side when reading an InitSecContextToken.
208
*/
209
// XXX Passing in Checksum is not required. byte[] can
210
// be passed in if this checksum type denotes a
211
// raw_checksum. In that case, make Checksum class krb5
212
// internal.
213
public OverloadedChecksum(Krb5Context context, Checksum checksum,
214
EncryptionKey key, EncryptionKey subKey)
215
throws GSSException, KrbException, IOException {
216
217
int pos = 0;
218
219
if (checksum == null) {
220
GSSException ge = new GSSException(GSSException.FAILURE, -1,
221
"No cksum in AP_REQ's authenticator");
222
ge.initCause(new KrbException(Krb5.KRB_AP_ERR_INAPP_CKSUM));
223
throw ge;
224
}
225
checksumBytes = checksum.getBytes();
226
227
if ((checksumBytes[0] != CHECKSUM_FIRST_BYTES[0]) ||
228
(checksumBytes[1] != CHECKSUM_FIRST_BYTES[1]) ||
229
(checksumBytes[2] != CHECKSUM_FIRST_BYTES[2]) ||
230
(checksumBytes[3] != CHECKSUM_FIRST_BYTES[3])) {
231
throw new GSSException(GSSException.FAILURE, -1,
232
"Incorrect checksum");
233
}
234
235
ChannelBinding localBindings = context.getChannelBinding();
236
237
// Ignore remote channel binding info when not requested at
238
// local side (RFC 4121 4.1.1.2: the acceptor MAY ignore...).
239
//
240
// All major krb5 implementors implement this "MAY",
241
// and some applications depend on it as a workaround
242
// for not having a way to negotiate the use of channel
243
// binding -- the initiator application always uses CB
244
// and hopes the acceptor will ignore the CB if the
245
// acceptor doesn't support CB.
246
if (localBindings != null) {
247
byte[] remoteBindingBytes = new byte[CHECKSUM_BINDINGS_SIZE];
248
System.arraycopy(checksumBytes, 4, remoteBindingBytes, 0,
249
CHECKSUM_BINDINGS_SIZE);
250
251
byte[] noBindings = new byte[CHECKSUM_BINDINGS_SIZE];
252
if (!Arrays.equals(noBindings, remoteBindingBytes)) {
253
byte[] localBindingsBytes =
254
computeChannelBinding(localBindings);
255
if (!Arrays.equals(localBindingsBytes,
256
remoteBindingBytes)) {
257
throw new GSSException(GSSException.BAD_BINDINGS, -1,
258
"Bytes mismatch!");
259
}
260
} else {
261
throw new GSSException(GSSException.BAD_BINDINGS, -1,
262
"Token missing ChannelBinding!");
263
}
264
}
265
266
flags = readLittleEndian(checksumBytes, 20, 4);
267
268
if ((flags & CHECKSUM_DELEG_FLAG) > 0) {
269
270
/*
271
* XXX
272
* if ((checksumBytes[24] != (byte)0x01) &&
273
* (checksumBytes[25] != (byte)0x00))
274
*/
275
276
int credLen = readLittleEndian(checksumBytes, 26, 2);
277
byte[] credBytes = new byte[credLen];
278
System.arraycopy(checksumBytes, 28, credBytes, 0, credLen);
279
280
KrbCred cred;
281
try {
282
cred = new KrbCred(credBytes, key);
283
} catch (KrbException ke) {
284
if (subKey != null) {
285
cred = new KrbCred(credBytes, subKey);
286
} else {
287
throw ke;
288
}
289
}
290
delegCreds = cred.getDelegatedCreds()[0];
291
}
292
}
293
294
// check if KRB-CRED message should use NULL_KEY for encryption
295
private boolean useNullKey(CipherHelper ch) {
296
boolean flag = true;
297
// for "newer" etypes and RC4-HMAC do not use NULL KEY
298
if ((ch.getProto() == 1) || ch.isArcFour()) {
299
flag = false;
300
}
301
return flag;
302
}
303
304
public Checksum getChecksum() throws KrbException {
305
return new Checksum(checksumBytes, CHECKSUM_TYPE);
306
}
307
308
public Credentials getDelegatedCreds() {
309
return delegCreds;
310
}
311
312
// Only called by acceptor
313
public void setContextFlags(Krb5Context context) {
314
// default for cred delegation is false
315
if ((flags & CHECKSUM_DELEG_FLAG) > 0)
316
context.setCredDelegState(true);
317
// default for the following are true
318
if ((flags & CHECKSUM_MUTUAL_FLAG) == 0) {
319
context.setMutualAuthState(false);
320
}
321
if ((flags & CHECKSUM_REPLAY_FLAG) == 0) {
322
context.setReplayDetState(false);
323
}
324
if ((flags & CHECKSUM_SEQUENCE_FLAG) == 0) {
325
context.setSequenceDetState(false);
326
}
327
if ((flags & CHECKSUM_CONF_FLAG) == 0) {
328
context.setConfState(false);
329
}
330
if ((flags & CHECKSUM_INTEG_FLAG) == 0) {
331
context.setIntegState(false);
332
}
333
}
334
}
335
336
private int getAddrType(InetAddress addr) {
337
int addressType = CHANNEL_BINDING_AF_NULL_ADDR;
338
339
if (addr instanceof Inet4Address)
340
addressType = CHANNEL_BINDING_AF_INET;
341
else if (addr instanceof Inet6Address)
342
addressType = CHANNEL_BINDING_AF_INET6;
343
return (addressType);
344
}
345
346
private byte[] getAddrBytes(InetAddress addr) throws GSSException {
347
int addressType = getAddrType(addr);
348
byte[] addressBytes = addr.getAddress();
349
if (addressBytes != null) {
350
switch (addressType) {
351
case CHANNEL_BINDING_AF_INET:
352
if (addressBytes.length != Inet4_ADDRSZ) {
353
throw new GSSException(GSSException.FAILURE, -1,
354
"Incorrect AF-INET address length in ChannelBinding.");
355
}
356
return (addressBytes);
357
case CHANNEL_BINDING_AF_INET6:
358
if (addressBytes.length != Inet6_ADDRSZ) {
359
throw new GSSException(GSSException.FAILURE, -1,
360
"Incorrect AF-INET6 address length in ChannelBinding.");
361
}
362
return (addressBytes);
363
default:
364
throw new GSSException(GSSException.FAILURE, -1,
365
"Cannot handle non AF-INET addresses in ChannelBinding.");
366
}
367
}
368
return null;
369
}
370
371
private byte[] computeChannelBinding(ChannelBinding channelBinding)
372
throws GSSException {
373
374
InetAddress initiatorAddress = channelBinding.getInitiatorAddress();
375
InetAddress acceptorAddress = channelBinding.getAcceptorAddress();
376
int size = 5*4;
377
378
int initiatorAddressType = getAddrType(initiatorAddress);
379
int acceptorAddressType = getAddrType(acceptorAddress);
380
381
byte[] initiatorAddressBytes = null;
382
if (initiatorAddress != null) {
383
initiatorAddressBytes = getAddrBytes(initiatorAddress);
384
size += initiatorAddressBytes.length;
385
}
386
387
byte[] acceptorAddressBytes = null;
388
if (acceptorAddress != null) {
389
acceptorAddressBytes = getAddrBytes(acceptorAddress);
390
size += acceptorAddressBytes.length;
391
}
392
393
byte[] appDataBytes = channelBinding.getApplicationData();
394
if (appDataBytes != null) {
395
size += appDataBytes.length;
396
}
397
398
byte[] data = new byte[size];
399
400
int pos = 0;
401
402
writeLittleEndian(initiatorAddressType, data, pos);
403
pos += 4;
404
405
if (initiatorAddressBytes != null) {
406
writeLittleEndian(initiatorAddressBytes.length, data, pos);
407
pos += 4;
408
System.arraycopy(initiatorAddressBytes, 0,
409
data, pos, initiatorAddressBytes.length);
410
pos += initiatorAddressBytes.length;
411
} else {
412
// Write length 0
413
pos += 4;
414
}
415
416
writeLittleEndian(acceptorAddressType, data, pos);
417
pos += 4;
418
419
if (acceptorAddressBytes != null) {
420
writeLittleEndian(acceptorAddressBytes.length, data, pos);
421
pos += 4;
422
System.arraycopy(acceptorAddressBytes, 0,
423
data, pos, acceptorAddressBytes.length);
424
pos += acceptorAddressBytes.length;
425
} else {
426
// Write length 0
427
pos += 4;
428
}
429
430
if (appDataBytes != null) {
431
writeLittleEndian(appDataBytes.length, data, pos);
432
pos += 4;
433
System.arraycopy(appDataBytes, 0, data, pos,
434
appDataBytes.length);
435
pos += appDataBytes.length;
436
} else {
437
// Write 0
438
pos += 4;
439
}
440
441
try {
442
MessageDigest md5 = MessageDigest.getInstance("MD5");
443
return md5.digest(data);
444
} catch (NoSuchAlgorithmException e) {
445
throw new GSSException(GSSException.FAILURE, -1,
446
"Could not get MD5 Message Digest - "
447
+ e.getMessage());
448
}
449
}
450
451
public abstract byte[] encode() throws IOException;
452
453
}
454
455