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/ServiceCreds.java
41161 views
1
/*
2
* Copyright (c) 2012, 2013, 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 javax.security.auth.kerberos.KerberosTicket;
29
import javax.security.auth.kerberos.KerberosKey;
30
import javax.security.auth.kerberos.KerberosPrincipal;
31
import javax.security.auth.kerberos.KeyTab;
32
import javax.security.auth.Subject;
33
34
import sun.security.krb5.Credentials;
35
import sun.security.krb5.EncryptionKey;
36
import sun.security.krb5.KrbException;
37
import java.io.IOException;
38
import java.util.ArrayList;
39
import java.util.List;
40
import java.util.Set;
41
import sun.security.krb5.*;
42
import sun.security.krb5.internal.Krb5;
43
44
/**
45
* Credentials of a kerberos acceptor. A KerberosPrincipal object (kp) is
46
* the principal. It can be specified as the serverPrincipal argument
47
* in the getInstance() method, or uses only KerberosPrincipal in the subject.
48
* Otherwise, the creds object is unbound and kp is null.
49
*
50
* The class also encapsulates various secrets, which can be:
51
*
52
* 1. Some KerberosKeys (generated from password)
53
* 2. Some KeyTabs (for a typical service based on keytabs)
54
* 3. A TGT (for S4U2proxy extension or user2user)
55
*
56
* Note that some secrets can coexist. For example, a user2user service
57
* can use its keytab (or keys) if the client can successfully obtain a
58
* normal service ticket, or it can use the TGT (actually, the session key
59
* of the TGT) if the client can only acquire a service ticket
60
* of ENC-TKT-IN-SKEY style.
61
*
62
* @since 1.8
63
*/
64
public final class ServiceCreds {
65
// The principal, or null if unbound
66
private KerberosPrincipal kp;
67
68
// All principals in the subject's princ set
69
private Set<KerberosPrincipal> allPrincs;
70
71
// All private credentials that can be used
72
private List<KeyTab> ktabs;
73
private List<KerberosKey> kk;
74
private KerberosTicket tgt;
75
76
private boolean destroyed;
77
78
private ServiceCreds() {
79
// Make sure this class cannot be instantiated externally.
80
}
81
82
/**
83
* Creates a ServiceCreds object based on info in a Subject for
84
* a given principal name (if specified).
85
* @return the object, or null if there is no private creds for it
86
*/
87
public static ServiceCreds getInstance(
88
Subject subj, String serverPrincipal) {
89
90
ServiceCreds sc = new ServiceCreds();
91
92
sc.allPrincs =
93
subj.getPrincipals(KerberosPrincipal.class);
94
95
// Compatibility. A key implies its own principal
96
for (KerberosKey key: SubjectComber.findMany(
97
subj, serverPrincipal, null, KerberosKey.class)) {
98
sc.allPrincs.add(key.getPrincipal());
99
}
100
101
if (serverPrincipal != null) { // A named principal
102
sc.kp = new KerberosPrincipal(serverPrincipal);
103
} else {
104
// For compatibility reason, we set the name of default principal
105
// to the "only possible" name it can take, which means there is
106
// only one KerberosPrincipal and there is no unbound keytabs
107
if (sc.allPrincs.size() == 1) {
108
boolean hasUnbound = false;
109
for (KeyTab ktab: SubjectComber.findMany(
110
subj, null, null, KeyTab.class)) {
111
if (!ktab.isBound()) {
112
hasUnbound = true;
113
break;
114
}
115
}
116
if (!hasUnbound) {
117
sc.kp = sc.allPrincs.iterator().next();
118
serverPrincipal = sc.kp.getName();
119
}
120
}
121
}
122
123
sc.ktabs = SubjectComber.findMany(
124
subj, serverPrincipal, null, KeyTab.class);
125
sc.kk = SubjectComber.findMany(
126
subj, serverPrincipal, null, KerberosKey.class);
127
sc.tgt = SubjectComber.find(
128
subj, null, serverPrincipal, KerberosTicket.class);
129
if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) {
130
return null;
131
}
132
133
sc.destroyed = false;
134
135
return sc;
136
}
137
138
// can be null
139
public String getName() {
140
if (destroyed) {
141
throw new IllegalStateException("This object is destroyed");
142
}
143
return kp == null ? null : kp.getName();
144
}
145
146
/**
147
* Gets keys for "someone". Used in 2 cases:
148
* 1. By TLS because it needs to get keys before client comes in.
149
* 2. As a fallback in getEKeys() below.
150
* This method can still return an empty array.
151
*/
152
public KerberosKey[] getKKeys() {
153
if (destroyed) {
154
throw new IllegalStateException("This object is destroyed");
155
}
156
KerberosPrincipal one = kp; // named principal
157
if (one == null && !allPrincs.isEmpty()) { // or, a known principal
158
one = allPrincs.iterator().next();
159
}
160
if (one == null) { // Or, some random one
161
for (KeyTab ktab: ktabs) {
162
// Must be unbound keytab, otherwise, allPrincs is not empty
163
PrincipalName pn =
164
Krb5Util.snapshotFromJavaxKeyTab(ktab).getOneName();
165
if (pn != null) {
166
one = new KerberosPrincipal(pn.getName());
167
break;
168
}
169
}
170
}
171
if (one != null) {
172
return getKKeys(one);
173
} else {
174
return new KerberosKey[0];
175
}
176
}
177
178
/**
179
* Get kkeys for a principal,
180
* @param princ the target name initiator requests. Not null.
181
* @return keys for the princ, never null, might be empty
182
*/
183
public KerberosKey[] getKKeys(KerberosPrincipal princ) {
184
if (destroyed) {
185
throw new IllegalStateException("This object is destroyed");
186
}
187
ArrayList<KerberosKey> keys = new ArrayList<>();
188
if (kp != null && !princ.equals(kp)) { // named principal
189
return new KerberosKey[0];
190
}
191
for (KerberosKey k: kk) {
192
if (k.getPrincipal().equals(princ)) {
193
keys.add(k);
194
}
195
}
196
for (KeyTab ktab: ktabs) {
197
if (ktab.getPrincipal() == null && ktab.isBound()) {
198
// legacy bound keytab. although we don't know who
199
// the bound principal is, it must be in allPrincs
200
if (!allPrincs.contains(princ)) {
201
continue; // skip this legacy bound keytab
202
}
203
}
204
for (KerberosKey k: ktab.getKeys(princ)) {
205
keys.add(k);
206
}
207
}
208
return keys.toArray(new KerberosKey[keys.size()]);
209
}
210
211
/**
212
* Gets EKeys for a principal.
213
* @param princ the target name initiator requests. Not null.
214
* @return keys for the princ, never null, might be empty
215
*/
216
public EncryptionKey[] getEKeys(PrincipalName princ) {
217
if (destroyed) {
218
throw new IllegalStateException("This object is destroyed");
219
}
220
KerberosKey[] kkeys = getKKeys(new KerberosPrincipal(princ.getName()));
221
if (kkeys.length == 0) {
222
// Fallback: old JDK does not perform real name checking. If the
223
// acceptor has host.sun.com but initiator requests for host,
224
// as long as their keys match (i.e. keys for one can decrypt
225
// the other's service ticket), the authentication is OK.
226
// There are real customers depending on this to use different
227
// names for a single service.
228
kkeys = getKKeys();
229
}
230
EncryptionKey[] ekeys = new EncryptionKey[kkeys.length];
231
for (int i=0; i<ekeys.length; i++) {
232
ekeys[i] = new EncryptionKey(
233
kkeys[i].getEncoded(), kkeys[i].getKeyType(),
234
kkeys[i].getVersionNumber());
235
}
236
return ekeys;
237
}
238
239
public Credentials getInitCred() {
240
if (destroyed) {
241
throw new IllegalStateException("This object is destroyed");
242
}
243
if (tgt == null) {
244
return null;
245
}
246
try {
247
return Krb5Util.ticketToCreds(tgt);
248
} catch (KrbException | IOException e) {
249
return null;
250
}
251
}
252
253
public void destroy() {
254
// Do not wipe out real keys because they are references to the
255
// priv creds in subject. Just make it useless.
256
destroyed = true;
257
kp = null;
258
ktabs.clear();
259
kk.clear();
260
tgt = null;
261
}
262
}
263
264