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/krb5/KrbApReq.java
41159 views
1
/*
2
* Copyright (c) 2000, 2019, 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
/*
27
*
28
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
29
* Copyright 1997 The Open Group Research Institute. All rights reserved.
30
*/
31
32
package sun.security.krb5;
33
34
import sun.security.krb5.internal.*;
35
import sun.security.krb5.internal.crypto.*;
36
import sun.security.jgss.krb5.Krb5AcceptCredential;
37
import java.net.InetAddress;
38
import sun.security.util.*;
39
import java.io.IOException;
40
import java.util.Arrays;
41
import java.security.MessageDigest;
42
import java.security.NoSuchAlgorithmException;
43
import sun.security.krb5.internal.rcache.AuthTimeWithHash;
44
45
/**
46
* This class encapsulates a KRB-AP-REQ that a client sends to a
47
* server for authentication.
48
*/
49
public class KrbApReq {
50
51
private byte[] obuf;
52
private KerberosTime ctime;
53
private int cusec;
54
private Authenticator authenticator;
55
private Credentials creds;
56
private APReq apReqMessg;
57
58
// Used by acceptor side
59
private static ReplayCache rcache = ReplayCache.getInstance();
60
private static boolean DEBUG = Krb5.DEBUG;
61
private static final char[] hexConst = "0123456789ABCDEF".toCharArray();
62
63
/**
64
* Constructs an AP-REQ message to send to the peer.
65
* @param tgsCred the <code>Credentials</code> to be used to construct the
66
* AP Request protocol message.
67
* @param mutualRequired Whether mutual authentication is required
68
* @param useSubkey Whether the subkey is to be used to protect this
69
* specific application session. If this is not set then the
70
* session key from the ticket will be used.
71
* @throws KrbException for any Kerberos protocol specific error
72
* @throws IOException for any IO related errors
73
* (e.g. socket operations)
74
*/
75
/*
76
// Not Used
77
public KrbApReq(Credentials tgsCred,
78
boolean mutualRequired,
79
boolean useSubKey,
80
boolean useSeqNumber) throws Asn1Exception,
81
KrbCryptoException, KrbException, IOException {
82
83
this(tgsCred, mutualRequired, useSubKey, useSeqNumber, null);
84
}
85
*/
86
87
/**
88
* Constructs an AP-REQ message to send to the peer.
89
* @param tgsCred the <code>Credentials</code> to be used to construct the
90
* AP Request protocol message.
91
* @param mutualRequired Whether mutual authentication is required
92
* @param useSubKey Whether the subkey is to be used to protect this
93
* specific application session. If this is not set then the
94
* session key from the ticket will be used.
95
* @param cksum checksum of the application data that accompanies
96
* the KRB_AP_REQ.
97
* @throws KrbException for any Kerberos protocol specific error
98
* @throws IOException for any IO related errors
99
* (e.g. socket operations)
100
*/
101
// Used in InitSecContextToken
102
public KrbApReq(Credentials tgsCred,
103
boolean mutualRequired,
104
boolean useSubKey,
105
boolean useSeqNumber,
106
Checksum cksum) throws Asn1Exception,
107
KrbCryptoException, KrbException, IOException {
108
109
APOptions apOptions = (mutualRequired?
110
new APOptions(Krb5.AP_OPTS_MUTUAL_REQUIRED):
111
new APOptions());
112
if (DEBUG)
113
System.out.println(">>> KrbApReq: APOptions are " + apOptions);
114
115
EncryptionKey subKey = (useSubKey?
116
new EncryptionKey(tgsCred.getSessionKey()):
117
null);
118
119
SeqNumber seqNum = new LocalSeqNumber();
120
121
init(apOptions,
122
tgsCred,
123
cksum,
124
subKey,
125
seqNum,
126
null, // AuthorizationData authzData
127
KeyUsage.KU_AP_REQ_AUTHENTICATOR);
128
129
}
130
131
/**
132
* Constructs an AP-REQ message from the bytes received from the
133
* peer.
134
* @param message The message received from the peer
135
* @param cred <code>KrbAcceptCredential</code> containing keys to decrypt
136
* the message; key selected will depend on etype used to encrypt data
137
* @throws KrbException for any Kerberos protocol specific error
138
* @throws IOException for any IO related errors
139
* (e.g. socket operations)
140
*/
141
// Used in InitSecContextToken (for AP_REQ and not TGS REQ)
142
public KrbApReq(byte[] message,
143
Krb5AcceptCredential cred,
144
InetAddress initiator)
145
throws KrbException, IOException {
146
obuf = message;
147
if (apReqMessg == null)
148
decode();
149
authenticate(cred, initiator);
150
}
151
152
/**
153
* Constructs an AP-REQ message from the bytes received from the
154
* peer.
155
* @param value The <code>DerValue</code> that contains the
156
* DER enoded AP-REQ protocol message
157
* @param keys <code>EncrtyptionKey</code>s to decrypt the message;
158
*
159
* @throws KrbException for any Kerberos protocol specific error
160
* @throws IOException for any IO related errors
161
* (e.g. socket operations)
162
*/
163
/*
164
public KrbApReq(DerValue value, EncryptionKey[] key, InetAddress initiator)
165
throws KrbException, IOException {
166
obuf = value.toByteArray();
167
if (apReqMessg == null)
168
decode(value);
169
authenticate(keys, initiator);
170
}
171
172
KrbApReq(APOptions options,
173
Credentials tgs_creds,
174
Checksum cksum,
175
EncryptionKey subKey,
176
SeqNumber seqNumber,
177
AuthorizationData authorizationData)
178
throws KrbException, IOException {
179
init(options, tgs_creds, cksum, subKey, seqNumber, authorizationData);
180
}
181
*/
182
183
/** used by KrbTgsReq **/
184
KrbApReq(APOptions apOptions,
185
Ticket ticket,
186
EncryptionKey key,
187
PrincipalName cname,
188
Checksum cksum,
189
KerberosTime ctime,
190
EncryptionKey subKey,
191
SeqNumber seqNumber,
192
AuthorizationData authorizationData)
193
throws Asn1Exception, IOException,
194
KdcErrException, KrbCryptoException {
195
196
init(apOptions, ticket, key, cname,
197
cksum, ctime, subKey, seqNumber, authorizationData,
198
KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR);
199
200
}
201
202
private void init(APOptions options,
203
Credentials tgs_creds,
204
Checksum cksum,
205
EncryptionKey subKey,
206
SeqNumber seqNumber,
207
AuthorizationData authorizationData,
208
int usage)
209
throws KrbException, IOException {
210
211
ctime = KerberosTime.now();
212
init(options,
213
tgs_creds.ticket,
214
tgs_creds.key,
215
tgs_creds.client,
216
cksum,
217
ctime,
218
subKey,
219
seqNumber,
220
authorizationData,
221
usage);
222
}
223
224
private void init(APOptions apOptions,
225
Ticket ticket,
226
EncryptionKey key,
227
PrincipalName cname,
228
Checksum cksum,
229
KerberosTime ctime,
230
EncryptionKey subKey,
231
SeqNumber seqNumber,
232
AuthorizationData authorizationData,
233
int usage)
234
throws Asn1Exception, IOException,
235
KdcErrException, KrbCryptoException {
236
237
createMessage(apOptions, ticket, key, cname,
238
cksum, ctime, subKey, seqNumber, authorizationData,
239
usage);
240
obuf = apReqMessg.asn1Encode();
241
}
242
243
244
void decode() throws KrbException, IOException {
245
DerValue encoding = new DerValue(obuf);
246
decode(encoding);
247
}
248
249
void decode(DerValue encoding) throws KrbException, IOException {
250
apReqMessg = null;
251
try {
252
apReqMessg = new APReq(encoding);
253
} catch (Asn1Exception e) {
254
apReqMessg = null;
255
KRBError err = new KRBError(encoding);
256
String errStr = err.getErrorString();
257
String eText;
258
if (errStr.charAt(errStr.length() - 1) == 0)
259
eText = errStr.substring(0, errStr.length() - 1);
260
else
261
eText = errStr;
262
KrbException ke = new KrbException(err.getErrorCode(), eText);
263
ke.initCause(e);
264
throw ke;
265
}
266
}
267
268
private void authenticate(Krb5AcceptCredential cred, InetAddress initiator)
269
throws KrbException, IOException {
270
int encPartKeyType = apReqMessg.ticket.encPart.getEType();
271
Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
272
EncryptionKey[] keys = cred.getKrb5EncryptionKeys(apReqMessg.ticket.sname);
273
EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);
274
275
if (dkey == null) {
276
throw new KrbException(Krb5.API_INVALID_ARG,
277
"Cannot find key of appropriate type to decrypt AP-REQ - " +
278
EType.toString(encPartKeyType));
279
}
280
281
byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey,
282
KeyUsage.KU_TICKET);
283
byte[] temp = apReqMessg.ticket.encPart.reset(bytes);
284
EncTicketPart enc_ticketPart = new EncTicketPart(temp);
285
286
checkPermittedEType(enc_ticketPart.key.getEType());
287
288
byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key,
289
KeyUsage.KU_AP_REQ_AUTHENTICATOR);
290
byte[] temp2 = apReqMessg.authenticator.reset(bytes2);
291
authenticator = new Authenticator(temp2);
292
ctime = authenticator.ctime;
293
cusec = authenticator.cusec;
294
authenticator.ctime =
295
authenticator.ctime.withMicroSeconds(authenticator.cusec);
296
297
if (!authenticator.cname.equals(enc_ticketPart.cname)) {
298
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);
299
}
300
301
if (!authenticator.ctime.inClockSkew())
302
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
303
304
String alg = AuthTimeWithHash.DEFAULT_HASH_ALG;
305
byte[] hash;
306
try {
307
hash = MessageDigest.getInstance(AuthTimeWithHash.realAlg(alg))
308
.digest(apReqMessg.authenticator.cipher);
309
} catch (NoSuchAlgorithmException ex) {
310
throw new AssertionError("Impossible " + alg);
311
}
312
313
char[] h = new char[hash.length * 2];
314
for (int i=0; i<hash.length; i++) {
315
h[2*i] = hexConst[(hash[i]&0xff)>>4];
316
h[2*i+1] = hexConst[hash[i]&0xf];
317
}
318
AuthTimeWithHash time = new AuthTimeWithHash(
319
authenticator.cname.toString(),
320
apReqMessg.ticket.sname.toString(),
321
authenticator.ctime.getSeconds(),
322
authenticator.cusec,
323
alg,
324
new String(h));
325
rcache.checkAndStore(KerberosTime.now(), time);
326
327
if (initiator != null) {
328
// sender host address
329
HostAddress sender = new HostAddress(initiator);
330
if (enc_ticketPart.caddr != null
331
&& !enc_ticketPart.caddr.inList(sender)) {
332
if (DEBUG) {
333
System.out.println(">>> KrbApReq: initiator is "
334
+ sender.getInetAddress()
335
+ ", but caddr is "
336
+ Arrays.toString(
337
enc_ticketPart.caddr.getInetAddresses()));
338
}
339
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
340
}
341
}
342
343
// XXX check for repeated authenticator
344
// if found
345
// throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
346
// else
347
// save authenticator to check for later
348
349
KerberosTime now = KerberosTime.now();
350
351
if ((enc_ticketPart.starttime != null &&
352
enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) ||
353
enc_ticketPart.flags.get(Krb5.TKT_OPTS_INVALID))
354
throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_NYV);
355
356
// if the current time is later than end time by more
357
// than the allowable clock skew, throws ticket expired exception.
358
if (enc_ticketPart.endtime != null &&
359
now.greaterThanWRTClockSkew(enc_ticketPart.endtime)) {
360
throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_EXPIRED);
361
}
362
363
creds = new Credentials(
364
apReqMessg.ticket,
365
authenticator.cname,
366
null,
367
apReqMessg.ticket.sname,
368
null,
369
enc_ticketPart.key,
370
enc_ticketPart.flags,
371
enc_ticketPart.authtime,
372
enc_ticketPart.starttime,
373
enc_ticketPart.endtime,
374
enc_ticketPart.renewTill,
375
enc_ticketPart.caddr,
376
enc_ticketPart.authorizationData);
377
if (DEBUG) {
378
System.out.println(">>> KrbApReq: authenticate succeed.");
379
}
380
}
381
382
/**
383
* Returns the credentials that are contained in the ticket that
384
* is part of this AP-REQ.
385
*/
386
public Credentials getCreds() {
387
return creds;
388
}
389
390
KerberosTime getCtime() {
391
if (ctime != null)
392
return ctime;
393
return authenticator.ctime;
394
}
395
396
int cusec() {
397
return cusec;
398
}
399
400
APOptions getAPOptions() throws KrbException, IOException {
401
if (apReqMessg == null)
402
decode();
403
if (apReqMessg != null)
404
return apReqMessg.apOptions;
405
return null;
406
}
407
408
/**
409
* Returns true if mutual authentication is required and hence an
410
* AP-REP will need to be generated.
411
* @throws KrbException
412
* @throws IOException
413
*/
414
public boolean getMutualAuthRequired() throws KrbException, IOException {
415
if (apReqMessg == null)
416
decode();
417
if (apReqMessg != null)
418
return apReqMessg.apOptions.get(Krb5.AP_OPTS_MUTUAL_REQUIRED);
419
return false;
420
}
421
422
boolean useSessionKey() throws KrbException, IOException {
423
if (apReqMessg == null)
424
decode();
425
if (apReqMessg != null)
426
return apReqMessg.apOptions.get(Krb5.AP_OPTS_USE_SESSION_KEY);
427
return false;
428
}
429
430
/**
431
* Returns the optional subkey stored in the Authenticator for
432
* this message. Returns null if none is stored.
433
*/
434
public EncryptionKey getSubKey() {
435
// XXX Can authenticator be null
436
return authenticator.getSubKey();
437
}
438
439
/**
440
* Returns the optional sequence number stored in the
441
* Authenticator for this message. Returns null if none is
442
* stored.
443
*/
444
public Integer getSeqNumber() {
445
// XXX Can authenticator be null
446
return authenticator.getSeqNumber();
447
}
448
449
/**
450
* Returns the optional Checksum stored in the
451
* Authenticator for this message. Returns null if none is
452
* stored.
453
*/
454
public Checksum getChecksum() {
455
return authenticator.getChecksum();
456
}
457
458
/**
459
* Returns the ASN.1 encoding that should be sent to the peer.
460
*/
461
public byte[] getMessage() {
462
return obuf;
463
}
464
465
/**
466
* Returns the principal name of the client that generated this
467
* message.
468
*/
469
public PrincipalName getClient() {
470
return creds.getClient();
471
}
472
473
private void createMessage(APOptions apOptions,
474
Ticket ticket,
475
EncryptionKey key,
476
PrincipalName cname,
477
Checksum cksum,
478
KerberosTime ctime,
479
EncryptionKey subKey,
480
SeqNumber seqNumber,
481
AuthorizationData authorizationData,
482
int usage)
483
throws Asn1Exception, IOException,
484
KdcErrException, KrbCryptoException {
485
486
Integer seqno = null;
487
488
if (seqNumber != null)
489
seqno = seqNumber.current();
490
491
authenticator =
492
new Authenticator(cname,
493
cksum,
494
ctime.getMicroSeconds(),
495
ctime,
496
subKey,
497
seqno,
498
authorizationData);
499
500
byte[] temp = authenticator.asn1Encode();
501
502
EncryptedData encAuthenticator =
503
new EncryptedData(key, temp, usage);
504
505
apReqMessg =
506
new APReq(apOptions, ticket, encAuthenticator);
507
}
508
509
// Check that key is one of the permitted types
510
private static void checkPermittedEType(int target) throws KrbException {
511
int[] etypes = EType.getDefaults("permitted_enctypes");
512
if (!EType.isSupported(target, etypes)) {
513
throw new KrbException(EType.toString(target) +
514
" encryption type not in permitted_enctypes list");
515
}
516
}
517
}
518
519