Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyTab.java
41161 views
1
/*
2
* Copyright (c) 2011, 2021, 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 javax.security.auth.kerberos;
27
28
import java.io.File;
29
import java.security.AccessControlException;
30
import java.util.Objects;
31
import sun.security.krb5.EncryptionKey;
32
import sun.security.krb5.KerberosSecrets;
33
import sun.security.krb5.PrincipalName;
34
import sun.security.krb5.RealmException;
35
36
/**
37
* This class encapsulates a keytab file.
38
* <p>
39
* A Kerberos JAAS login module that obtains long term secret keys from a
40
* keytab file should use this class. The login module will store
41
* an instance of this class in the private credential set of a
42
* {@link javax.security.auth.Subject Subject} during the commit phase of the
43
* authentication process.
44
* <p>
45
* If a {@code KeyTab} object is obtained from {@link #getUnboundInstance()}
46
* or {@link #getUnboundInstance(java.io.File)}, it is unbound and thus can be
47
* used by any service principal. Otherwise, if it's obtained from
48
* {@link #getInstance(KerberosPrincipal)} or
49
* {@link #getInstance(KerberosPrincipal, java.io.File)}, it is bound to the
50
* specific service principal and can only be used by it.
51
* <p>
52
* Please note the constructors {@link #getInstance()} and
53
* {@link #getInstance(java.io.File)} were created when there was no support
54
* for unbound keytabs. These methods should not be used anymore. An object
55
* created with either of these methods are considered to be bound to an
56
* unknown principal, which means, its {@link #isBound()} returns true and
57
* {@link #getPrincipal()} returns null.
58
* <p>
59
* It might be necessary for the application to be granted a
60
* {@link javax.security.auth.PrivateCredentialPermission
61
* PrivateCredentialPermission} if it needs to access the {@code KeyTab}
62
* instance from a {@code Subject}. This permission is not needed when the
63
* application depends on the default JGSS Kerberos mechanism to access the
64
* {@code KeyTab}. In that case, however, the application will need an appropriate
65
* {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
66
* <p>
67
* The keytab file format is described at
68
* <a href="http://www.ioplex.com/utilities/keytab.txt">
69
* http://www.ioplex.com/utilities/keytab.txt</a>.
70
*
71
* @since 1.7
72
*/
73
public final class KeyTab {
74
75
/*
76
* Impl notes:
77
*
78
* This class is only a name, a permanent link to the keytab source
79
* (can be missing). Itself has no content. In order to read content,
80
* take a snapshot and read from it.
81
*
82
* The snapshot is of type sun.security.krb5.internal.ktab.KeyTab, which
83
* contains the content of the keytab file when the snapshot is taken.
84
* Itself has no refresh function and mostly an immutable class (except
85
* for the create/add/save methods only used by the ktab command).
86
*/
87
88
// Source, null if using the default one. Note that the default name
89
// is maintained in snapshot, this field is never "resolved".
90
private final File file;
91
92
// Bound user: normally from the "principal" value in a JAAS krb5
93
// login conf. Will be null if it's "*".
94
private final KerberosPrincipal princ;
95
96
private final boolean bound;
97
98
// Set up JavaxSecurityAuthKerberosAccess in KerberosSecrets
99
static {
100
KerberosSecrets.setJavaxSecurityAuthKerberosAccess(
101
new JavaxSecurityAuthKerberosAccessImpl());
102
}
103
104
private KeyTab(KerberosPrincipal princ, File file, boolean bound) {
105
this.princ = princ;
106
this.file = file;
107
this.bound = bound;
108
}
109
110
/**
111
* Returns a {@code KeyTab} instance from a {@code File} object
112
* that is bound to an unknown service principal.
113
* <p>
114
* The result of this method is never null. This method only associates
115
* the returned {@code KeyTab} object with the file and does not read it.
116
* <p>
117
* Developers should call {@link #getInstance(KerberosPrincipal,File)}
118
* when the bound service principal is known.
119
* @param file the keytab {@code File} object, must not be null
120
* @return the keytab instance
121
* @throws NullPointerException if the {@code file} argument is null
122
*/
123
public static KeyTab getInstance(File file) {
124
if (file == null) {
125
throw new NullPointerException("file must be non null");
126
}
127
return new KeyTab(null, file, true);
128
}
129
130
/**
131
* Returns an unbound {@code KeyTab} instance from a {@code File}
132
* object.
133
* <p>
134
* The result of this method is never null. This method only associates
135
* the returned {@code KeyTab} object with the file and does not read it.
136
* @param file the keytab {@code File} object, must not be null
137
* @return the keytab instance
138
* @throws NullPointerException if the file argument is null
139
* @since 1.8
140
*/
141
public static KeyTab getUnboundInstance(File file) {
142
if (file == null) {
143
throw new NullPointerException("file must be non null");
144
}
145
return new KeyTab(null, file, false);
146
}
147
148
/**
149
* Returns a {@code KeyTab} instance from a {@code File} object
150
* that is bound to the specified service principal.
151
* <p>
152
* The result of this method is never null. This method only associates
153
* the returned {@code KeyTab} object with the file and does not read it.
154
* @param princ the bound service principal, must not be null
155
* @param file the keytab {@code File} object, must not be null
156
* @return the keytab instance
157
* @throws NullPointerException if either of the arguments is null
158
* @since 1.8
159
*/
160
public static KeyTab getInstance(KerberosPrincipal princ, File file) {
161
if (princ == null) {
162
throw new NullPointerException("princ must be non null");
163
}
164
if (file == null) {
165
throw new NullPointerException("file must be non null");
166
}
167
return new KeyTab(princ, file, true);
168
}
169
170
/**
171
* Returns the default {@code KeyTab} instance that is bound
172
* to an unknown service principal.
173
* <p>
174
* The result of this method is never null. This method only associates
175
* the returned {@code KeyTab} object with the default keytab file and
176
* does not read it.
177
* <p>
178
* Developers should call {@link #getInstance(KerberosPrincipal)}
179
* when the bound service principal is known.
180
* @return the default keytab instance.
181
*/
182
public static KeyTab getInstance() {
183
return new KeyTab(null, null, true);
184
}
185
186
/**
187
* Returns the default unbound {@code KeyTab} instance.
188
* <p>
189
* The result of this method is never null. This method only associates
190
* the returned {@code KeyTab} object with the default keytab file and
191
* does not read it.
192
* @return the default keytab instance
193
* @since 1.8
194
*/
195
public static KeyTab getUnboundInstance() {
196
return new KeyTab(null, null, false);
197
}
198
199
/**
200
* Returns the default {@code KeyTab} instance that is bound
201
* to the specified service principal.
202
* <p>
203
* The result of this method is never null. This method only associates
204
* the returned {@code KeyTab} object with the default keytab file and
205
* does not read it.
206
* @param princ the bound service principal, must not be null
207
* @return the default keytab instance
208
* @throws NullPointerException if {@code princ} is null
209
* @since 1.8
210
*/
211
public static KeyTab getInstance(KerberosPrincipal princ) {
212
if (princ == null) {
213
throw new NullPointerException("princ must be non null");
214
}
215
return new KeyTab(princ, null, true);
216
}
217
218
// Takes a snapshot of the keytab content. This method is called by
219
// JavaxSecurityAuthKerberosAccessImpl so no more private
220
sun.security.krb5.internal.ktab.KeyTab takeSnapshot() {
221
try {
222
return sun.security.krb5.internal.ktab.KeyTab.getInstance(file);
223
} catch (@SuppressWarnings("removal") AccessControlException ace) {
224
if (file != null) {
225
// It's OK to show the name if caller specified it
226
throw ace;
227
} else {
228
@SuppressWarnings("removal")
229
AccessControlException ace2 = new AccessControlException(
230
"Access to default keytab denied (modified exception)");
231
ace2.setStackTrace(ace.getStackTrace());
232
throw ace2;
233
}
234
}
235
}
236
237
/**
238
* Returns fresh keys for the given Kerberos principal.
239
* <p>
240
* Implementation of this method should make sure the returned keys match
241
* the latest content of the keytab file. The result is a newly created
242
* copy that can be modified by the caller without modifying the keytab
243
* object. The caller should {@link KerberosKey#destroy() destroy} the
244
* result keys after they are used.
245
* <p>
246
* Please note that the keytab file can be created after the
247
* {@code KeyTab} object is instantiated and its content may change over
248
* time. Therefore, an application should call this method only when it
249
* needs to use the keys. Any previous result from an earlier invocation
250
* could potentially be expired.
251
* <p>
252
* If there is any error (say, I/O error or format error)
253
* during the reading process of the keytab file, a saved result should be
254
* returned. If there is no saved result (say, this is the first time this
255
* method is called, or, all previous read attempts failed), an empty array
256
* should be returned. This can make sure the result is not drastically
257
* changed during the (probably slow) update of the keytab file.
258
* <p>
259
* Each time this method is called and the reading of the file succeeds
260
* with no exception (say, I/O error or file format error),
261
* the result should be saved for {@code principal}. The implementation can
262
* also save keys for other principals having keys in the same keytab object
263
* if convenient.
264
* <p>
265
* Any unsupported key read from the keytab is ignored and not included
266
* in the result.
267
* <p>
268
* If this keytab is bound to a specific principal, calling this method on
269
* another principal will return an empty array.
270
*
271
* @param principal the Kerberos principal, must not be null.
272
* @return the keys (never null, may be empty)
273
* @throws NullPointerException if the {@code principal}
274
* argument is null
275
* @throws SecurityException if a security manager exists and the read
276
* access to the keytab file is not permitted
277
*/
278
public KerberosKey[] getKeys(KerberosPrincipal principal) {
279
try {
280
if (princ != null && !principal.equals(princ)) {
281
return new KerberosKey[0];
282
}
283
PrincipalName pn = new PrincipalName(principal.getName());
284
EncryptionKey[] keys = takeSnapshot().readServiceKeys(pn);
285
KerberosKey[] kks = new KerberosKey[keys.length];
286
for (int i=0; i<kks.length; i++) {
287
Integer tmp = keys[i].getKeyVersionNumber();
288
kks[i] = new KerberosKey(
289
principal,
290
keys[i].getBytes(),
291
keys[i].getEType(),
292
tmp == null ? 0 : tmp.intValue());
293
keys[i].destroy();
294
}
295
return kks;
296
} catch (RealmException re) {
297
return new KerberosKey[0];
298
}
299
}
300
301
EncryptionKey[] getEncryptionKeys(PrincipalName principal) {
302
return takeSnapshot().readServiceKeys(principal);
303
}
304
305
/**
306
* Checks if the keytab file exists. Implementation of this method
307
* should make sure that the result matches the latest status of the
308
* keytab file.
309
*
310
* @return true if the keytab file exists; false otherwise.
311
* @throws SecurityException if a security manager exists and the read
312
* access to the keytab file is not permitted
313
*/
314
public boolean exists() {
315
return !takeSnapshot().isMissing();
316
}
317
318
/**
319
* Returns an informative textual representation of this {@code KeyTab}.
320
*
321
* @return an informative textual representation of this {@code KeyTab}.
322
*/
323
public String toString() {
324
String s = (file == null) ? "Default keytab" : file.toString();
325
if (!bound) return s;
326
else if (princ == null) return s + " for someone";
327
else return s + " for " + princ;
328
}
329
330
/**
331
* Returns a hash code for this {@code KeyTab}.
332
*
333
* @return a hash code for this {@code KeyTab}.
334
*/
335
public int hashCode() {
336
return Objects.hash(file, princ, bound);
337
}
338
339
/**
340
* Compares the specified object with this {@code KeyTab} for equality.
341
* Returns true if the given object is also a
342
* {@code KeyTab} and the two
343
* {@code KeyTab} instances are equivalent.
344
*
345
* @param other the object to compare to
346
* @return true if the specified object is equal to this {@code KeyTab}
347
*/
348
public boolean equals(Object other) {
349
if (other == this)
350
return true;
351
352
if (! (other instanceof KeyTab)) {
353
return false;
354
}
355
356
KeyTab otherKtab = (KeyTab) other;
357
return Objects.equals(otherKtab.princ, princ) &&
358
Objects.equals(otherKtab.file, file) &&
359
bound == otherKtab.bound;
360
}
361
362
/**
363
* Returns the service principal this {@code KeyTab} object
364
* is bound to. Returns {@code null} if it's not bound.
365
* <p>
366
* Please note the deprecated constructors create a {@code KeyTab} object
367
* bound for some unknown principal. In this case, this method also returns
368
* null. User can call {@link #isBound()} to verify this case.
369
* @return the service principal
370
* @since 1.8
371
*/
372
public KerberosPrincipal getPrincipal() {
373
return princ;
374
}
375
376
/**
377
* Returns if the keytab is bound to a principal
378
* @return if the keytab is bound to a principal
379
* @since 1.8
380
*/
381
public boolean isBound() {
382
return bound;
383
}
384
}
385
386