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/krb5/KrbApReq.java
38830 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 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 REP - " +
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
byte[] hash;
305
try {
306
hash = MessageDigest.getInstance("MD5")
307
.digest(apReqMessg.authenticator.cipher);
308
} catch (NoSuchAlgorithmException ex) {
309
throw new AssertionError("Impossible");
310
}
311
312
char[] h = new char[hash.length * 2];
313
for (int i=0; i<hash.length; i++) {
314
h[2*i] = hexConst[(hash[i]&0xff)>>4];
315
h[2*i+1] = hexConst[hash[i]&0xf];
316
}
317
AuthTimeWithHash time = new AuthTimeWithHash(
318
authenticator.cname.toString(),
319
apReqMessg.ticket.sname.toString(),
320
authenticator.ctime.getSeconds(),
321
authenticator.cusec,
322
new String(h));
323
rcache.checkAndStore(KerberosTime.now(), time);
324
325
if (initiator != null) {
326
// sender host address
327
HostAddress sender = new HostAddress(initiator);
328
if (enc_ticketPart.caddr != null
329
&& !enc_ticketPart.caddr.inList(sender)) {
330
if (DEBUG) {
331
System.out.println(">>> KrbApReq: initiator is "
332
+ sender.getInetAddress()
333
+ ", but caddr is "
334
+ Arrays.toString(
335
enc_ticketPart.caddr.getInetAddresses()));
336
}
337
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
338
}
339
}
340
341
// XXX check for repeated authenticator
342
// if found
343
// throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
344
// else
345
// save authenticator to check for later
346
347
KerberosTime now = KerberosTime.now();
348
349
if ((enc_ticketPart.starttime != null &&
350
enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) ||
351
enc_ticketPart.flags.get(Krb5.TKT_OPTS_INVALID))
352
throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_NYV);
353
354
// if the current time is later than end time by more
355
// than the allowable clock skew, throws ticket expired exception.
356
if (enc_ticketPart.endtime != null &&
357
now.greaterThanWRTClockSkew(enc_ticketPart.endtime)) {
358
throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_EXPIRED);
359
}
360
361
creds = new Credentials(
362
apReqMessg.ticket,
363
authenticator.cname,
364
null,
365
apReqMessg.ticket.sname,
366
null,
367
enc_ticketPart.key,
368
enc_ticketPart.flags,
369
enc_ticketPart.authtime,
370
enc_ticketPart.starttime,
371
enc_ticketPart.endtime,
372
enc_ticketPart.renewTill,
373
enc_ticketPart.caddr,
374
enc_ticketPart.authorizationData);
375
if (DEBUG) {
376
System.out.println(">>> KrbApReq: authenticate succeed.");
377
}
378
}
379
380
/**
381
* Returns the credentials that are contained in the ticket that
382
* is part of this this AP-REP.
383
*/
384
public Credentials getCreds() {
385
return creds;
386
}
387
388
KerberosTime getCtime() {
389
if (ctime != null)
390
return ctime;
391
return authenticator.ctime;
392
}
393
394
int cusec() {
395
return cusec;
396
}
397
398
APOptions getAPOptions() throws KrbException, IOException {
399
if (apReqMessg == null)
400
decode();
401
if (apReqMessg != null)
402
return apReqMessg.apOptions;
403
return null;
404
}
405
406
/**
407
* Returns true if mutual authentication is required and hence an
408
* AP-REP will need to be generated.
409
* @throws KrbException
410
* @throws IOException
411
*/
412
public boolean getMutualAuthRequired() throws KrbException, IOException {
413
if (apReqMessg == null)
414
decode();
415
if (apReqMessg != null)
416
return apReqMessg.apOptions.get(Krb5.AP_OPTS_MUTUAL_REQUIRED);
417
return false;
418
}
419
420
boolean useSessionKey() throws KrbException, IOException {
421
if (apReqMessg == null)
422
decode();
423
if (apReqMessg != null)
424
return apReqMessg.apOptions.get(Krb5.AP_OPTS_USE_SESSION_KEY);
425
return false;
426
}
427
428
/**
429
* Returns the optional subkey stored in the Authenticator for
430
* this message. Returns null if none is stored.
431
*/
432
public EncryptionKey getSubKey() {
433
// XXX Can authenticator be null
434
return authenticator.getSubKey();
435
}
436
437
/**
438
* Returns the optional sequence number stored in the
439
* Authenticator for this message. Returns null if none is
440
* stored.
441
*/
442
public Integer getSeqNumber() {
443
// XXX Can authenticator be null
444
return authenticator.getSeqNumber();
445
}
446
447
/**
448
* Returns the optional Checksum stored in the
449
* Authenticator for this message. Returns null if none is
450
* stored.
451
*/
452
public Checksum getChecksum() {
453
return authenticator.getChecksum();
454
}
455
456
/**
457
* Returns the ASN.1 encoding that should be sent to the peer.
458
*/
459
public byte[] getMessage() {
460
return obuf;
461
}
462
463
/**
464
* Returns the principal name of the client that generated this
465
* message.
466
*/
467
public PrincipalName getClient() {
468
return creds.getClient();
469
}
470
471
private void createMessage(APOptions apOptions,
472
Ticket ticket,
473
EncryptionKey key,
474
PrincipalName cname,
475
Checksum cksum,
476
KerberosTime ctime,
477
EncryptionKey subKey,
478
SeqNumber seqNumber,
479
AuthorizationData authorizationData,
480
int usage)
481
throws Asn1Exception, IOException,
482
KdcErrException, KrbCryptoException {
483
484
Integer seqno = null;
485
486
if (seqNumber != null)
487
seqno = new Integer(seqNumber.current());
488
489
authenticator =
490
new Authenticator(cname,
491
cksum,
492
ctime.getMicroSeconds(),
493
ctime,
494
subKey,
495
seqno,
496
authorizationData);
497
498
byte[] temp = authenticator.asn1Encode();
499
500
EncryptedData encAuthenticator =
501
new EncryptedData(key, temp, usage);
502
503
apReqMessg =
504
new APReq(apOptions, ticket, encAuthenticator);
505
}
506
507
// Check that key is one of the permitted types
508
private static void checkPermittedEType(int target) throws KrbException {
509
int[] etypes = EType.getDefaults("permitted_enctypes");
510
if (!EType.isSupported(target, etypes)) {
511
throw new KrbException(EType.toString(target) +
512
" encryption type not in permitted_enctypes list");
513
}
514
}
515
}
516
517