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/javax/security/auth/kerberos/KeyTab.java
38918 views
1
/*
2
* Copyright (c) 2011, 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 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 KeyTab
62
* instance from a Subject. This permission is not needed when the
63
* application depends on the default JGSS Kerberos mechanism to access the
64
* 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
* <p>
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 (AccessControlException ace) {
224
if (file != null) {
225
// It's OK to show the name if caller specified it
226
throw ace;
227
} else {
228
AccessControlException ace2 = new AccessControlException(
229
"Access to default keytab denied (modified exception)");
230
ace2.setStackTrace(ace.getStackTrace());
231
throw ace2;
232
}
233
}
234
}
235
236
/**
237
* Returns fresh keys for the given Kerberos principal.
238
* <p>
239
* Implementation of this method should make sure the returned keys match
240
* the latest content of the keytab file. The result is a newly created
241
* copy that can be modified by the caller without modifying the keytab
242
* object. The caller should {@link KerberosKey#destroy() destroy} the
243
* result keys after they are used.
244
* <p>
245
* Please note that the keytab file can be created after the
246
* {@code KeyTab} object is instantiated and its content may change over
247
* time. Therefore, an application should call this method only when it
248
* needs to use the keys. Any previous result from an earlier invocation
249
* could potentially be expired.
250
* <p>
251
* If there is any error (say, I/O error or format error)
252
* during the reading process of the KeyTab file, a saved result should be
253
* returned. If there is no saved result (say, this is the first time this
254
* method is called, or, all previous read attempts failed), an empty array
255
* should be returned. This can make sure the result is not drastically
256
* changed during the (probably slow) update of the keytab file.
257
* <p>
258
* Each time this method is called and the reading of the file succeeds
259
* with no exception (say, I/O error or file format error),
260
* the result should be saved for {@code principal}. The implementation can
261
* also save keys for other principals having keys in the same keytab object
262
* if convenient.
263
* <p>
264
* Any unsupported key read from the keytab is ignored and not included
265
* in the result.
266
* <p>
267
* If this keytab is bound to a specific principal, calling this method on
268
* another principal will return an empty array.
269
*
270
* @param principal the Kerberos principal, must not be null.
271
* @return the keys (never null, may be empty)
272
* @throws NullPointerException if the {@code principal}
273
* argument is null
274
* @throws SecurityException if a security manager exists and the read
275
* access to the keytab file is not permitted
276
*/
277
public KerberosKey[] getKeys(KerberosPrincipal principal) {
278
try {
279
if (princ != null && !principal.equals(princ)) {
280
return new KerberosKey[0];
281
}
282
PrincipalName pn = new PrincipalName(principal.getName());
283
EncryptionKey[] keys = takeSnapshot().readServiceKeys(pn);
284
KerberosKey[] kks = new KerberosKey[keys.length];
285
for (int i=0; i<kks.length; i++) {
286
Integer tmp = keys[i].getKeyVersionNumber();
287
kks[i] = new KerberosKey(
288
principal,
289
keys[i].getBytes(),
290
keys[i].getEType(),
291
tmp == null ? 0 : tmp.intValue());
292
keys[i].destroy();
293
}
294
return kks;
295
} catch (RealmException re) {
296
return new KerberosKey[0];
297
}
298
}
299
300
EncryptionKey[] getEncryptionKeys(PrincipalName principal) {
301
return takeSnapshot().readServiceKeys(principal);
302
}
303
304
/**
305
* Checks if the keytab file exists. Implementation of this method
306
* should make sure that the result matches the latest status of the
307
* keytab file.
308
* <p>
309
* The caller can use the result to determine if it should fallback to
310
* another mechanism to read the keys.
311
* @return true if the keytab file exists; false otherwise.
312
* @throws SecurityException if a security manager exists and the read
313
* access to the keytab file is not permitted
314
*/
315
public boolean exists() {
316
return !takeSnapshot().isMissing();
317
}
318
319
public String toString() {
320
String s = (file == null) ? "Default keytab" : file.toString();
321
if (!bound) return s;
322
else if (princ == null) return s + " for someone";
323
else return s + " for " + princ;
324
}
325
326
/**
327
* Returns a hashcode for this KeyTab.
328
*
329
* @return a hashCode() for the {@code KeyTab}
330
*/
331
public int hashCode() {
332
return Objects.hash(file, princ, bound);
333
}
334
335
/**
336
* Compares the specified Object with this KeyTab for equality.
337
* Returns true if the given object is also a
338
* {@code KeyTab} and the two
339
* {@code KeyTab} instances are equivalent.
340
*
341
* @param other the Object to compare to
342
* @return true if the specified object is equal to this KeyTab
343
*/
344
public boolean equals(Object other) {
345
if (other == this)
346
return true;
347
348
if (! (other instanceof KeyTab)) {
349
return false;
350
}
351
352
KeyTab otherKtab = (KeyTab) other;
353
return Objects.equals(otherKtab.princ, princ) &&
354
Objects.equals(otherKtab.file, file) &&
355
bound == otherKtab.bound;
356
}
357
358
/**
359
* Returns the service principal this {@code KeyTab} object
360
* is bound to. Returns {@code null} if it's not bound.
361
* <p>
362
* Please note the deprecated constructors create a KeyTab object bound for
363
* some unknown principal. In this case, this method also returns null.
364
* User can call {@link #isBound()} to verify this case.
365
* @return the service principal
366
* @since 1.8
367
*/
368
public KerberosPrincipal getPrincipal() {
369
return princ;
370
}
371
372
/**
373
* Returns if the keytab is bound to a principal
374
* @return if the keytab is bound to a principal
375
* @since 1.8
376
*/
377
public boolean isBound() {
378
return bound;
379
}
380
}
381
382