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/internal/ReferralsCache.java
41161 views
1
/*
2
* Copyright (c) 2019, 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.Date;
29
import java.util.HashMap;
30
import java.util.LinkedList;
31
import java.util.List;
32
import java.util.Map;
33
import java.util.Map.Entry;
34
35
import sun.security.krb5.Credentials;
36
import sun.security.krb5.PrincipalName;
37
38
/*
39
* ReferralsCache class implements a cache scheme for referral TGTs as
40
* described in RFC 6806 - 10. Caching Information. The goal is to optimize
41
* resources (such as network traffic) when a client requests credentials for a
42
* service principal to a given KDC. If a referral TGT was previously received,
43
* cached information is used instead of issuing a new query. Once a referral
44
* TGT expires, the corresponding referral entry in the cache is removed.
45
*/
46
final class ReferralsCache {
47
48
private static Map<ReferralCacheKey, Map<String, ReferralCacheEntry>>
49
referralsMap = new HashMap<>();
50
51
private static final class ReferralCacheKey {
52
private PrincipalName cname;
53
private PrincipalName sname;
54
ReferralCacheKey (PrincipalName cname, PrincipalName sname) {
55
this.cname = cname;
56
this.sname = sname;
57
}
58
public boolean equals(Object other) {
59
if (!(other instanceof ReferralCacheKey))
60
return false;
61
ReferralCacheKey that = (ReferralCacheKey)other;
62
return cname.equals(that.cname) &&
63
sname.equals(that.sname);
64
}
65
public int hashCode() {
66
return cname.hashCode() + sname.hashCode();
67
}
68
}
69
70
static final class ReferralCacheEntry {
71
private final Credentials creds;
72
private final String toRealm;
73
ReferralCacheEntry(Credentials creds, String toRealm) {
74
this.creds = creds;
75
this.toRealm = toRealm;
76
}
77
Credentials getCreds() {
78
return creds;
79
}
80
String getToRealm() {
81
return toRealm;
82
}
83
}
84
85
/*
86
* Add a new referral entry to the cache, including: client principal,
87
* service principal, source KDC realm, destination KDC realm and
88
* referral TGT.
89
*
90
* If a loop is generated when adding the new referral, the first hop is
91
* automatically removed. For example, let's assume that adding a
92
* REALM-3.COM -> REALM-1.COM referral generates the following loop:
93
* REALM-1.COM -> REALM-2.COM -> REALM-3.COM -> REALM-1.COM. Then,
94
* REALM-1.COM -> REALM-2.COM referral entry is removed from the cache.
95
*/
96
static synchronized void put(PrincipalName cname, PrincipalName service,
97
String fromRealm, String toRealm, Credentials creds) {
98
ReferralCacheKey k = new ReferralCacheKey(cname, service);
99
pruneExpired(k);
100
if (creds.getEndTime().before(new Date())) {
101
return;
102
}
103
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
104
if (entries == null) {
105
entries = new HashMap<String, ReferralCacheEntry>();
106
referralsMap.put(k, entries);
107
}
108
entries.remove(fromRealm);
109
ReferralCacheEntry newEntry = new ReferralCacheEntry(creds, toRealm);
110
entries.put(fromRealm, newEntry);
111
112
// Remove loops within the cache
113
ReferralCacheEntry current = newEntry;
114
List<ReferralCacheEntry> seen = new LinkedList<>();
115
while (current != null) {
116
if (seen.contains(current)) {
117
// Loop found. Remove the first referral to cut the loop.
118
entries.remove(newEntry.getToRealm());
119
break;
120
}
121
seen.add(current);
122
current = entries.get(current.getToRealm());
123
}
124
}
125
126
/*
127
* Obtain a referral entry from the cache given a client principal,
128
* service principal and a source KDC realm.
129
*/
130
static synchronized ReferralCacheEntry get(PrincipalName cname,
131
PrincipalName service, String fromRealm) {
132
ReferralCacheKey k = new ReferralCacheKey(cname, service);
133
pruneExpired(k);
134
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
135
if (entries != null) {
136
ReferralCacheEntry toRef = entries.get(fromRealm);
137
if (toRef != null) {
138
return toRef;
139
}
140
}
141
return null;
142
}
143
144
/*
145
* Remove referral entries from the cache when referral TGTs expire.
146
*/
147
private static void pruneExpired(ReferralCacheKey k) {
148
Date now = new Date();
149
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
150
if (entries != null) {
151
for (Entry<String, ReferralCacheEntry> mapEntry :
152
entries.entrySet()) {
153
if (mapEntry.getValue().getCreds().getEndTime().before(now)) {
154
entries.remove(mapEntry.getKey());
155
}
156
}
157
}
158
}
159
}
160
161