Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java
67745 views
1
/*
2
* Copyright (c) 2019, 2021, Red Hat, Inc.
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.krb5.internal;
27
28
import java.util.Arrays;
29
import java.util.Date;
30
import java.util.HashMap;
31
import java.util.Iterator;
32
import java.util.LinkedList;
33
import java.util.List;
34
import java.util.Map;
35
import java.util.Map.Entry;
36
import java.util.Objects;
37
38
import sun.security.krb5.Credentials;
39
import sun.security.krb5.PrincipalName;
40
41
/*
42
* ReferralsCache class implements a cache scheme for referral TGTs as
43
* described in RFC 6806 - 10. Caching Information. The goal is to optimize
44
* resources (such as network traffic) when a client requests credentials for a
45
* service principal to a given KDC. If a referral TGT was previously received,
46
* cached information is used instead of issuing a new query. Once a referral
47
* TGT expires, the corresponding referral entry in the cache is removed.
48
*/
49
final class ReferralsCache {
50
51
private static Map<ReferralCacheKey, Map<String, ReferralCacheEntry>>
52
referralsMap = new HashMap<>();
53
54
private static final class ReferralCacheKey {
55
private PrincipalName cname;
56
private PrincipalName sname;
57
private PrincipalName user; // S4U2Self only
58
private byte[] userSvcTicketEnc; // S4U2Proxy only
59
ReferralCacheKey (PrincipalName cname, PrincipalName sname,
60
PrincipalName user, Ticket userSvcTicket) {
61
this.cname = cname;
62
this.sname = sname;
63
this.user = user;
64
if (userSvcTicket != null && userSvcTicket.encPart != null) {
65
byte[] userSvcTicketEnc = userSvcTicket.encPart.getBytes();
66
if (userSvcTicketEnc.length > 0) {
67
this.userSvcTicketEnc = userSvcTicketEnc;
68
}
69
}
70
}
71
public boolean equals(Object other) {
72
if (!(other instanceof ReferralCacheKey))
73
return false;
74
ReferralCacheKey that = (ReferralCacheKey)other;
75
return cname.equals(that.cname) &&
76
sname.equals(that.sname) &&
77
Objects.equals(user, that.user) &&
78
Arrays.equals(userSvcTicketEnc, that.userSvcTicketEnc);
79
}
80
public int hashCode() {
81
return cname.hashCode() + sname.hashCode() +
82
Objects.hashCode(user) +
83
Arrays.hashCode(userSvcTicketEnc);
84
}
85
}
86
87
static final class ReferralCacheEntry {
88
private final Credentials creds;
89
private final String toRealm;
90
ReferralCacheEntry(Credentials creds, String toRealm) {
91
this.creds = creds;
92
this.toRealm = toRealm;
93
}
94
Credentials getCreds() {
95
return creds;
96
}
97
String getToRealm() {
98
return toRealm;
99
}
100
}
101
102
/*
103
* Add a new referral entry to the cache, including: client principal,
104
* service principal, user principal (S4U2Self only), client service
105
* ticket (S4U2Proxy only), source KDC realm, destination KDC realm and
106
* referral TGT.
107
*
108
* If a loop is generated when adding the new referral, the first hop is
109
* automatically removed. For example, let's assume that adding a
110
* REALM-3.COM -> REALM-1.COM referral generates the following loop:
111
* REALM-1.COM -> REALM-2.COM -> REALM-3.COM -> REALM-1.COM. Then,
112
* REALM-1.COM -> REALM-2.COM referral entry is removed from the cache.
113
*/
114
static synchronized void put(PrincipalName cname, PrincipalName service,
115
PrincipalName user, Ticket[] userSvcTickets, String fromRealm,
116
String toRealm, Credentials creds) {
117
Ticket userSvcTicket = (userSvcTickets != null ?
118
userSvcTickets[0] : null);
119
ReferralCacheKey k = new ReferralCacheKey(cname, service,
120
user, userSvcTicket);
121
pruneExpired(k);
122
if (creds.getEndTime().before(new Date())) {
123
return;
124
}
125
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
126
if (entries == null) {
127
entries = new HashMap<String, ReferralCacheEntry>();
128
referralsMap.put(k, entries);
129
}
130
entries.remove(fromRealm);
131
ReferralCacheEntry newEntry = new ReferralCacheEntry(creds, toRealm);
132
entries.put(fromRealm, newEntry);
133
134
// Remove loops within the cache
135
ReferralCacheEntry current = newEntry;
136
List<ReferralCacheEntry> seen = new LinkedList<>();
137
while (current != null) {
138
if (seen.contains(current)) {
139
// Loop found. Remove the first referral to cut the loop.
140
entries.remove(newEntry.getToRealm());
141
break;
142
}
143
seen.add(current);
144
current = entries.get(current.getToRealm());
145
}
146
}
147
148
/*
149
* Obtain a referral entry from the cache given a client principal,
150
* a service principal, a user principal (S4U2Self only), a client
151
* service ticket (S4U2Proxy only) and a source KDC realm.
152
*/
153
static synchronized ReferralCacheEntry get(PrincipalName cname,
154
PrincipalName service, PrincipalName user,
155
Ticket[] userSvcTickets, String fromRealm) {
156
Ticket userSvcTicket = (userSvcTickets != null ?
157
userSvcTickets[0] : null);
158
ReferralCacheKey k = new ReferralCacheKey(cname, service,
159
user, userSvcTicket);
160
pruneExpired(k);
161
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
162
if (entries != null) {
163
ReferralCacheEntry toRef = entries.get(fromRealm);
164
if (toRef != null) {
165
return toRef;
166
}
167
}
168
return null;
169
}
170
171
/*
172
* Remove referral entries from the cache when referral TGTs expire.
173
*/
174
private static void pruneExpired(ReferralCacheKey k) {
175
Date now = new Date();
176
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
177
if (entries != null) {
178
Iterator<Entry<String, ReferralCacheEntry>> it = entries.entrySet().iterator();
179
while (it.hasNext()) {
180
Entry<String, ReferralCacheEntry> mapEntry = it.next();
181
if (mapEntry.getValue().getCreds().getEndTime().before(now)) {
182
it.remove();
183
}
184
}
185
}
186
}
187
}
188
189