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/Realm.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.Krb5;
35
import sun.security.util.*;
36
import java.io.IOException;
37
import java.util.*;
38
39
import sun.security.krb5.internal.util.KerberosString;
40
41
/**
42
* Implements the ASN.1 Realm type.
43
*
44
* {@code Realm ::= GeneralString}
45
*
46
* This class is immutable.
47
*/
48
public class Realm implements Cloneable {
49
50
public static final boolean AUTODEDUCEREALM =
51
java.security.AccessController.doPrivileged(
52
new sun.security.action.GetBooleanAction(
53
"sun.security.krb5.autodeducerealm"));
54
55
private final String realm; // not null nor empty
56
57
public Realm(String name) throws RealmException {
58
realm = parseRealm(name);
59
}
60
61
public static Realm getDefault() throws RealmException {
62
try {
63
return new Realm(Config.getInstance().getDefaultRealm());
64
} catch (RealmException re) {
65
throw re;
66
} catch (KrbException ke) {
67
throw new RealmException(ke);
68
}
69
}
70
71
// Immutable class, no need to clone
72
public Object clone() {
73
return this;
74
}
75
76
public boolean equals(Object obj) {
77
if (this == obj) {
78
return true;
79
}
80
81
if (!(obj instanceof Realm)) {
82
return false;
83
}
84
85
Realm that = (Realm)obj;
86
return this.realm.equals(that.realm);
87
}
88
89
public int hashCode() {
90
return realm.hashCode();
91
}
92
93
/**
94
* Constructs a Realm object.
95
* @param encoding a Der-encoded data.
96
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
97
* @exception IOException if an I/O error occurs while reading encoded data.
98
* @exception RealmException if an error occurs while parsing a Realm object.
99
*/
100
public Realm(DerValue encoding)
101
throws Asn1Exception, RealmException, IOException {
102
if (encoding == null) {
103
throw new IllegalArgumentException("encoding can not be null");
104
}
105
realm = new KerberosString(encoding).toString();
106
if (realm == null || realm.length() == 0)
107
throw new RealmException(Krb5.REALM_NULL);
108
if (!isValidRealmString(realm))
109
throw new RealmException(Krb5.REALM_ILLCHAR);
110
}
111
112
public String toString() {
113
return realm;
114
}
115
116
// Extract realm from a string like dummy@REALM
117
public static String parseRealmAtSeparator(String name)
118
throws RealmException {
119
if (name == null) {
120
throw new IllegalArgumentException
121
("null input name is not allowed");
122
}
123
String temp = new String(name);
124
String result = null;
125
int i = 0;
126
while (i < temp.length()) {
127
if (temp.charAt(i) == PrincipalName.NAME_REALM_SEPARATOR) {
128
if (i == 0 || temp.charAt(i - 1) != '\\') {
129
if (i + 1 < temp.length()) {
130
result = temp.substring(i + 1, temp.length());
131
} else {
132
throw new IllegalArgumentException
133
("empty realm part not allowed");
134
}
135
break;
136
}
137
}
138
i++;
139
}
140
if (result != null) {
141
if (result.length() == 0)
142
throw new RealmException(Krb5.REALM_NULL);
143
if (!isValidRealmString(result))
144
throw new RealmException(Krb5.REALM_ILLCHAR);
145
}
146
return result;
147
}
148
149
public static String parseRealmComponent(String name) {
150
if (name == null) {
151
throw new IllegalArgumentException
152
("null input name is not allowed");
153
}
154
String temp = new String(name);
155
String result = null;
156
int i = 0;
157
while (i < temp.length()) {
158
if (temp.charAt(i) == PrincipalName.REALM_COMPONENT_SEPARATOR) {
159
if (i == 0 || temp.charAt(i - 1) != '\\') {
160
if (i + 1 < temp.length())
161
result = temp.substring(i + 1, temp.length());
162
break;
163
}
164
}
165
i++;
166
}
167
return result;
168
}
169
170
protected static String parseRealm(String name) throws RealmException {
171
String result = parseRealmAtSeparator(name);
172
if (result == null)
173
result = name;
174
if (result == null || result.length() == 0)
175
throw new RealmException(Krb5.REALM_NULL);
176
if (!isValidRealmString(result))
177
throw new RealmException(Krb5.REALM_ILLCHAR);
178
return result;
179
}
180
181
// This is protected because the definition of a realm
182
// string is fixed
183
protected static boolean isValidRealmString(String name) {
184
if (name == null)
185
return false;
186
if (name.length() == 0)
187
return false;
188
for (int i = 0; i < name.length(); i++) {
189
if (name.charAt(i) == '/' ||
190
name.charAt(i) == '\0') {
191
return false;
192
}
193
}
194
return true;
195
}
196
197
/**
198
* Encodes a Realm object.
199
* @return the byte array of encoded KrbCredInfo object.
200
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
201
* @exception IOException if an I/O error occurs while reading encoded data.
202
*
203
*/
204
public byte[] asn1Encode() throws Asn1Exception, IOException {
205
DerOutputStream out = new DerOutputStream();
206
out.putDerValue(new KerberosString(this.realm).toDerValue());
207
return out.toByteArray();
208
}
209
210
211
/**
212
* Parse (unmarshal) a realm from a DER input stream. This form
213
* parsing might be used when expanding a value which is part of
214
* a constructed sequence and uses explicitly tagged type.
215
*
216
* @exception Asn1Exception on error.
217
* @param data the Der input stream value, which contains one or more marshaled value.
218
* @param explicitTag tag number.
219
* @param optional indicate if this data field is optional
220
* @return an instance of Realm.
221
*
222
*/
223
public static Realm parse(DerInputStream data, byte explicitTag, boolean optional)
224
throws Asn1Exception, IOException, RealmException {
225
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) {
226
return null;
227
}
228
DerValue der = data.getDerValue();
229
if (explicitTag != (der.getTag() & (byte)0x1F)) {
230
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
231
} else {
232
DerValue subDer = der.getData().getDerValue();
233
return new Realm(subDer);
234
}
235
}
236
237
/**
238
* Returns an array of realms that may be traversed to obtain
239
* a TGT from the initiating realm cRealm to the target realm
240
* sRealm.
241
* <br>
242
* This method would read [capaths] to create a path, or generate a
243
* hierarchical path if [capaths] does not contain a sub-stanza for cRealm
244
* or the sub-stanza does not contain a tag for sRealm.
245
* <br>
246
* The returned list would never be null, and it always contains
247
* cRealm as the head entry. sRealm is not included as the tail.
248
*
249
* @param cRealm the initiating realm, not null
250
* @param sRealm the target realm, not null, not equals to cRealm
251
* @return array of realms including at least cRealm as the first
252
* element
253
*/
254
public static String[] getRealmsList(String cRealm, String sRealm) {
255
try {
256
// Try [capaths]
257
return parseCapaths(cRealm, sRealm);
258
} catch (KrbException ke) {
259
// Now assume the realms are organized hierarchically.
260
return parseHierarchy(cRealm, sRealm);
261
}
262
}
263
264
/**
265
* Parses the [capaths] stanza of the configuration file for a
266
* list of realms to traverse to obtain credentials from the
267
* initiating realm cRealm to the target realm sRealm.
268
*
269
* For a given client realm C there is a tag C in [capaths] whose
270
* subtag S has a value which is a (possibly partial) path from C
271
* to S. When the path is partial, it contains only the tail of the
272
* full path. Values of other subtags will be used to build the full
273
* path. The value "." means a direct path from C to S. If realm S
274
* does not appear as a subtag, there is no path defined here.
275
*
276
* The implementation ignores all values which equals to C or S, or
277
* a "." in multiple values, or any duplicated realm names.
278
*
279
* When a path value has more than two realms, they can be specified
280
* with multiple key-value pairs each having a single value, but the
281
* order must not change.
282
*
283
* For example:
284
*
285
* [capaths]
286
* TIVOLI.COM = {
287
* IBM.COM = IBM_LDAPCENTRAL.COM MOONLITE.ORG
288
* IBM_LDAPCENTRAL.COM = LDAPCENTRAL.NET
289
* LDAPCENTRAL.NET = .
290
* }
291
*
292
* TIVOLI.COM has a direct path to LDAPCENTRAL.NET, which has a direct
293
* path to IBM_LDAPCENTRAL.COM. It also has a partial path to IBM.COM
294
* being "IBM_LDAPCENTRAL.COM MOONLITE.ORG". Merging these info together,
295
* a full path from TIVOLI.COM to IBM.COM will be
296
*
297
* TIVOLI.COM -> LDAPCENTRAL.NET -> IBM_LDAPCENTRAL.COM
298
* -> IBM_LDAPCENTRAL.COM -> MOONLITE.ORG
299
*
300
* Please note the sRealm IBM.COM does not appear in the path.
301
*
302
* @param cRealm the initiating realm
303
* @param sRealm the target realm, not the same as cRealm
304
* @returns array of realms including at least cRealm as the first
305
* element
306
* @throws KrbException if the config does not contain a sub-stanza
307
* for cRealm in [capaths] or the sub-stanza does not contain
308
* sRealm as a tag
309
*/
310
private static String[] parseCapaths(String cRealm, String sRealm)
311
throws KrbException {
312
313
// This line could throw a KrbException
314
Config cfg = Config.getInstance();
315
316
if (!cfg.exists("capaths", cRealm, sRealm)) {
317
throw new KrbException("No conf");
318
}
319
320
LinkedList<String> path = new LinkedList<>();
321
322
String head = sRealm;
323
while (true) {
324
String value = cfg.getAll("capaths", cRealm, head);
325
if (value == null) {
326
break;
327
}
328
String[] more = value.split("\\s+");
329
boolean changed = false;
330
for (int i=more.length-1; i>=0; i--) {
331
if (path.contains(more[i])
332
|| more[i].equals(".")
333
|| more[i].equals(cRealm)
334
|| more[i].equals(sRealm)
335
|| more[i].equals(head)) {
336
// Ignore invalid values
337
continue;
338
}
339
changed = true;
340
path.addFirst(more[i]);
341
}
342
if (!changed) break;
343
head = path.getFirst();
344
}
345
path.addFirst(cRealm);
346
return path.toArray(new String[path.size()]);
347
}
348
349
/**
350
* Build a list of realm that can be traversed
351
* to obtain credentials from the initiating realm cRealm
352
* for a service in the target realm sRealm.
353
* @param cRealm the initiating realm
354
* @param sRealm the target realm, not the same as cRealm
355
* @return array of realms including cRealm as the first element
356
*/
357
private static String[] parseHierarchy(String cRealm, String sRealm) {
358
359
String[] cComponents = cRealm.split("\\.");
360
String[] sComponents = sRealm.split("\\.");
361
362
int cPos = cComponents.length;
363
int sPos = sComponents.length;
364
365
boolean hasCommon = false;
366
for (sPos--, cPos--; sPos >=0 && cPos >= 0 &&
367
sComponents[sPos].equals(cComponents[cPos]);
368
sPos--, cPos--) {
369
hasCommon = true;
370
}
371
372
// For those with common components:
373
// length pos
374
// SITES1.SALES.EXAMPLE.COM 4 1
375
// EVERYWHERE.EXAMPLE.COM 3 0
376
377
// For those without common components:
378
// length pos
379
// DEVEL.EXAMPLE.COM 3 2
380
// PROD.EXAMPLE.ORG 3 2
381
382
LinkedList<String> path = new LinkedList<>();
383
384
// Un-common ones for client side
385
for (int i=0; i<=cPos; i++) {
386
path.addLast(subStringFrom(cComponents, i));
387
}
388
389
// Common one
390
if (hasCommon) {
391
path.addLast(subStringFrom(cComponents, cPos+1));
392
}
393
394
// Un-common ones for server side
395
for (int i=sPos; i>=0; i--) {
396
path.addLast(subStringFrom(sComponents, i));
397
}
398
399
// Remove sRealm from path. Note that it might be added at last loop
400
// or as a common component, if sRealm is a parent of cRealm
401
path.removeLast();
402
403
return path.toArray(new String[path.size()]);
404
}
405
406
/**
407
* Creates a realm name using components from the given position.
408
* For example, subStringFrom({"A", "B", "C"}, 1) is "B.C".
409
*/
410
private static String subStringFrom(String[] components, int from) {
411
StringBuilder sb = new StringBuilder();
412
for (int i=from; i<components.length; i++) {
413
if (sb.length() != 0) sb.append('.');
414
sb.append(components[i]);
415
}
416
return sb.toString();
417
}
418
}
419
420