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