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/jgss/GSSCredentialImpl.java
38830 views
1
/*
2
* Copyright (c) 2000, 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;
27
28
import org.ietf.jgss.*;
29
import sun.security.jgss.spi.*;
30
import java.util.*;
31
import com.sun.security.jgss.*;
32
import sun.security.jgss.spnego.SpNegoCredElement;
33
34
public class GSSCredentialImpl implements ExtendedGSSCredential {
35
36
private GSSManagerImpl gssManager = null;
37
private boolean destroyed = false;
38
39
/*
40
* We store all elements in a hashtable, using <oid, usage> as the
41
* key. This makes it easy to locate the specific kind of credential we
42
* need. The implementation needs to be optimized for the case where
43
* there is just one element (tempCred).
44
*/
45
private Hashtable<SearchKey, GSSCredentialSpi> hashtable = null;
46
47
// XXX Optimization for single mech usage
48
private GSSCredentialSpi tempCred = null;
49
50
GSSCredentialImpl(GSSManagerImpl gssManager, int usage)
51
throws GSSException {
52
this(gssManager, null, GSSCredential.DEFAULT_LIFETIME,
53
(Oid[]) null, usage);
54
}
55
56
GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,
57
int lifetime, Oid mech, int usage)
58
throws GSSException {
59
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;
60
61
init(gssManager);
62
add(name, lifetime, lifetime, mech, usage);
63
}
64
65
GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,
66
int lifetime, Oid mechs[], int usage)
67
throws GSSException {
68
init(gssManager);
69
boolean defaultList = false;
70
if (mechs == null) {
71
mechs = gssManager.getMechs();
72
defaultList = true;
73
}
74
75
for (int i = 0; i < mechs.length; i++) {
76
try {
77
add(name, lifetime, lifetime, mechs[i], usage);
78
} catch (GSSException e) {
79
if (defaultList) {
80
// Try the next mechanism
81
GSSUtil.debug("Ignore " + e + " while acquring cred for "
82
+ mechs[i]);
83
//e.printStackTrace();
84
} else throw e; // else try the next mechanism
85
}
86
}
87
if ((hashtable.size() == 0) || (usage != getUsage()))
88
throw new GSSException(GSSException.NO_CRED);
89
}
90
91
// Wrap a mech cred into a GSS cred
92
public GSSCredentialImpl(GSSManagerImpl gssManager,
93
GSSCredentialSpi mechElement) throws GSSException {
94
95
init(gssManager);
96
int usage = GSSCredential.ACCEPT_ONLY;
97
if (mechElement.isInitiatorCredential()) {
98
if (mechElement.isAcceptorCredential()) {
99
usage = GSSCredential.INITIATE_AND_ACCEPT;
100
} else {
101
usage = GSSCredential.INITIATE_ONLY;
102
}
103
}
104
SearchKey key = new SearchKey(mechElement.getMechanism(),
105
usage);
106
tempCred = mechElement;
107
hashtable.put(key, tempCred);
108
// More mechs that can use this cred, say, SPNEGO
109
if (!GSSUtil.isSpNegoMech(mechElement.getMechanism())) {
110
key = new SearchKey(GSSUtil.GSS_SPNEGO_MECH_OID, usage);
111
hashtable.put(key, new SpNegoCredElement(mechElement));
112
}
113
}
114
115
void init(GSSManagerImpl gssManager) {
116
this.gssManager = gssManager;
117
hashtable = new Hashtable<SearchKey, GSSCredentialSpi>(
118
gssManager.getMechs().length);
119
}
120
121
public void dispose() throws GSSException {
122
if (!destroyed) {
123
GSSCredentialSpi element;
124
Enumeration<GSSCredentialSpi> values = hashtable.elements();
125
while (values.hasMoreElements()) {
126
element = values.nextElement();
127
element.dispose();
128
}
129
destroyed = true;
130
}
131
}
132
133
public GSSCredential impersonate(GSSName name) throws GSSException {
134
if (destroyed) {
135
throw new IllegalStateException("This credential is " +
136
"no longer valid");
137
}
138
Oid mech = tempCred.getMechanism();
139
GSSNameSpi nameElement = (name == null ? null :
140
((GSSNameImpl)name).getElement(mech));
141
GSSCredentialSpi cred = tempCred.impersonate(nameElement);
142
return (cred == null ?
143
null : new GSSCredentialImpl(gssManager, cred));
144
}
145
146
public GSSName getName() throws GSSException {
147
if (destroyed) {
148
throw new IllegalStateException("This credential is " +
149
"no longer valid");
150
}
151
return GSSNameImpl.wrapElement(gssManager, tempCred.getName());
152
}
153
154
public GSSName getName(Oid mech) throws GSSException {
155
156
if (destroyed) {
157
throw new IllegalStateException("This credential is " +
158
"no longer valid");
159
}
160
161
SearchKey key = null;
162
GSSCredentialSpi element = null;
163
164
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;
165
166
key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);
167
element = hashtable.get(key);
168
169
if (element == null) {
170
key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);
171
element = hashtable.get(key);
172
}
173
174
if (element == null) {
175
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
176
element = hashtable.get(key);
177
}
178
179
if (element == null) {
180
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
181
}
182
183
return GSSNameImpl.wrapElement(gssManager, element.getName());
184
185
}
186
187
/**
188
* Returns the remaining lifetime of this credential. The remaining
189
* lifetime is defined as the minimum lifetime, either for initiate or
190
* for accept, across all elements contained in it. Not terribly
191
* useful, but required by GSS-API.
192
*/
193
public int getRemainingLifetime() throws GSSException {
194
195
if (destroyed) {
196
throw new IllegalStateException("This credential is " +
197
"no longer valid");
198
}
199
200
SearchKey tempKey;
201
GSSCredentialSpi tempCred;
202
int tempLife = 0, tempInitLife = 0, tempAcceptLife = 0;
203
int min = INDEFINITE_LIFETIME;
204
205
for (Enumeration<SearchKey> e = hashtable.keys();
206
e.hasMoreElements(); ) {
207
tempKey = e.nextElement();
208
tempCred = hashtable.get(tempKey);
209
if (tempKey.getUsage() == INITIATE_ONLY)
210
tempLife = tempCred.getInitLifetime();
211
else if (tempKey.getUsage() == ACCEPT_ONLY)
212
tempLife = tempCred.getAcceptLifetime();
213
else {
214
tempInitLife = tempCred.getInitLifetime();
215
tempAcceptLife = tempCred.getAcceptLifetime();
216
tempLife = (tempInitLife < tempAcceptLife ?
217
tempInitLife:
218
tempAcceptLife);
219
}
220
if (min > tempLife)
221
min = tempLife;
222
}
223
224
return min;
225
}
226
227
public int getRemainingInitLifetime(Oid mech) throws GSSException {
228
229
if (destroyed) {
230
throw new IllegalStateException("This credential is " +
231
"no longer valid");
232
}
233
234
GSSCredentialSpi element = null;
235
SearchKey key = null;
236
boolean found = false;
237
int max = 0;
238
239
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;
240
241
key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);
242
element = hashtable.get(key);
243
244
if (element != null) {
245
found = true;
246
if (max < element.getInitLifetime())
247
max = element.getInitLifetime();
248
}
249
250
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
251
element = hashtable.get(key);
252
253
if (element != null) {
254
found = true;
255
if (max < element.getInitLifetime())
256
max = element.getInitLifetime();
257
}
258
259
if (!found) {
260
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
261
}
262
263
return max;
264
265
}
266
267
public int getRemainingAcceptLifetime(Oid mech) throws GSSException {
268
269
if (destroyed) {
270
throw new IllegalStateException("This credential is " +
271
"no longer valid");
272
}
273
274
GSSCredentialSpi element = null;
275
SearchKey key = null;
276
boolean found = false;
277
int max = 0;
278
279
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;
280
281
key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);
282
element = hashtable.get(key);
283
284
if (element != null) {
285
found = true;
286
if (max < element.getAcceptLifetime())
287
max = element.getAcceptLifetime();
288
}
289
290
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
291
element = hashtable.get(key);
292
293
if (element != null) {
294
found = true;
295
if (max < element.getAcceptLifetime())
296
max = element.getAcceptLifetime();
297
}
298
299
if (!found) {
300
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
301
}
302
303
return max;
304
305
}
306
307
/**
308
* Returns the usage mode for this credential. Returns
309
* INITIATE_AND_ACCEPT if any one element contained in it supports
310
* INITIATE_AND_ACCEPT or if two different elements exist where one
311
* support INITIATE_ONLY and the other supports ACCEPT_ONLY.
312
*/
313
public int getUsage() throws GSSException {
314
315
if (destroyed) {
316
throw new IllegalStateException("This credential is " +
317
"no longer valid");
318
}
319
320
SearchKey tempKey;
321
boolean initiate = false;
322
boolean accept = false;
323
324
for (Enumeration<SearchKey> e = hashtable.keys();
325
e.hasMoreElements(); ) {
326
tempKey = e.nextElement();
327
if (tempKey.getUsage() == INITIATE_ONLY)
328
initiate = true;
329
else if (tempKey.getUsage() == ACCEPT_ONLY)
330
accept = true;
331
else
332
return INITIATE_AND_ACCEPT;
333
}
334
if (initiate) {
335
if (accept)
336
return INITIATE_AND_ACCEPT;
337
else
338
return INITIATE_ONLY;
339
} else
340
return ACCEPT_ONLY;
341
}
342
343
public int getUsage(Oid mech) throws GSSException {
344
345
if (destroyed) {
346
throw new IllegalStateException("This credential is " +
347
"no longer valid");
348
}
349
350
GSSCredentialSpi element = null;
351
SearchKey key = null;
352
boolean initiate = false;
353
boolean accept = false;
354
355
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;
356
357
key = new SearchKey(mech, GSSCredential.INITIATE_ONLY);
358
element = hashtable.get(key);
359
360
if (element != null) {
361
initiate = true;
362
}
363
364
key = new SearchKey(mech, GSSCredential.ACCEPT_ONLY);
365
element = hashtable.get(key);
366
367
if (element != null) {
368
accept = true;
369
}
370
371
key = new SearchKey(mech, GSSCredential.INITIATE_AND_ACCEPT);
372
element = hashtable.get(key);
373
374
if (element != null) {
375
initiate = true;
376
accept = true;
377
}
378
379
if (initiate && accept)
380
return GSSCredential.INITIATE_AND_ACCEPT;
381
else if (initiate)
382
return GSSCredential.INITIATE_ONLY;
383
else if (accept)
384
return GSSCredential.ACCEPT_ONLY;
385
else {
386
throw new GSSExceptionImpl(GSSException.BAD_MECH, mech);
387
}
388
}
389
390
public Oid[] getMechs() throws GSSException {
391
392
if (destroyed) {
393
throw new IllegalStateException("This credential is " +
394
"no longer valid");
395
}
396
Vector<Oid> result = new Vector<Oid>(hashtable.size());
397
398
for (Enumeration<SearchKey> e = hashtable.keys();
399
e.hasMoreElements(); ) {
400
SearchKey tempKey = e.nextElement();
401
result.addElement(tempKey.getMech());
402
}
403
return result.toArray(new Oid[0]);
404
}
405
406
public void add(GSSName name, int initLifetime, int acceptLifetime,
407
Oid mech, int usage) throws GSSException {
408
409
if (destroyed) {
410
throw new IllegalStateException("This credential is " +
411
"no longer valid");
412
}
413
if (mech == null) mech = ProviderList.DEFAULT_MECH_OID;
414
415
SearchKey key = new SearchKey(mech, usage);
416
if (hashtable.containsKey(key)) {
417
throw new GSSExceptionImpl(GSSException.DUPLICATE_ELEMENT,
418
"Duplicate element found: " +
419
getElementStr(mech, usage));
420
}
421
422
// XXX If not instance of GSSNameImpl then throw exception
423
// Application mixing GSS implementations
424
GSSNameSpi nameElement = (name == null ? null :
425
((GSSNameImpl)name).getElement(mech));
426
427
tempCred = gssManager.getCredentialElement(nameElement,
428
initLifetime,
429
acceptLifetime,
430
mech,
431
usage);
432
/*
433
* Not all mechanisms support the concept of one credential element
434
* that can be used for both initiating and accepting a context. In
435
* the event that an application requests usage INITIATE_AND_ACCEPT
436
* for a credential from such a mechanism, the GSS framework will
437
* need to obtain two different credential elements from the
438
* mechanism, one that will have usage INITIATE_ONLY and another
439
* that will have usage ACCEPT_ONLY. The mechanism will help the
440
* GSS-API realize this by returning a credential element with
441
* usage INITIATE_ONLY or ACCEPT_ONLY prompting it to make another
442
* call to getCredentialElement, this time with the other usage
443
* mode.
444
*/
445
446
if (tempCred != null) {
447
if (usage == GSSCredential.INITIATE_AND_ACCEPT &&
448
(!tempCred.isAcceptorCredential() ||
449
!tempCred.isInitiatorCredential())) {
450
451
int currentUsage;
452
int desiredUsage;
453
454
if (!tempCred.isInitiatorCredential()) {
455
currentUsage = GSSCredential.ACCEPT_ONLY;
456
desiredUsage = GSSCredential.INITIATE_ONLY;
457
} else {
458
currentUsage = GSSCredential.INITIATE_ONLY;
459
desiredUsage = GSSCredential.ACCEPT_ONLY;
460
}
461
462
key = new SearchKey(mech, currentUsage);
463
hashtable.put(key, tempCred);
464
465
tempCred = gssManager.getCredentialElement(nameElement,
466
initLifetime,
467
acceptLifetime,
468
mech,
469
desiredUsage);
470
471
key = new SearchKey(mech, desiredUsage);
472
hashtable.put(key, tempCred);
473
} else {
474
hashtable.put(key, tempCred);
475
}
476
}
477
}
478
479
public boolean equals(Object another) {
480
481
if (destroyed) {
482
throw new IllegalStateException("This credential is " +
483
"no longer valid");
484
}
485
486
if (this == another) {
487
return true;
488
}
489
490
if (!(another instanceof GSSCredentialImpl)) {
491
return false;
492
}
493
494
// NOTE: The specification does not define the criteria to compare
495
// credentials.
496
/*
497
* XXX
498
* The RFC says: "Tests if this GSSCredential refers to the same
499
* entity as the supplied object. The two credentials must be
500
* acquired over the same mechanisms and must refer to the same
501
* principal. Returns "true" if the two GSSCredentials refer to
502
* the same entity; "false" otherwise."
503
*
504
* Well, when do two credentials refer to the same principal? Do
505
* they need to have one GSSName in common for the different
506
* GSSName's that the credential elements return? Or do all
507
* GSSName's have to be in common when the names are exported with
508
* their respective mechanisms for the credential elements?
509
*/
510
return false;
511
512
}
513
514
/**
515
* Returns a hashcode value for this GSSCredential.
516
*
517
* @return a hashCode value
518
*/
519
public int hashCode() {
520
521
if (destroyed) {
522
throw new IllegalStateException("This credential is " +
523
"no longer valid");
524
}
525
526
// NOTE: The specification does not define the criteria to compare
527
// credentials.
528
/*
529
* XXX
530
* Decide on a criteria for equals first then do this.
531
*/
532
return 1;
533
}
534
535
/**
536
* Returns the specified mechanism's credential-element.
537
*
538
* @param mechOid the oid for mechanism to retrieve
539
* @param initiate boolean indicating if the function is
540
* to throw exception or return null when element is not
541
* found.
542
* @return mechanism credential object
543
* @exception GSSException of invalid mechanism
544
*/
545
public GSSCredentialSpi getElement(Oid mechOid, boolean initiate)
546
throws GSSException {
547
548
if (destroyed) {
549
throw new IllegalStateException("This credential is " +
550
"no longer valid");
551
}
552
553
SearchKey key;
554
GSSCredentialSpi element;
555
556
if (mechOid == null) {
557
/*
558
* First see if the default mechanism satisfies the
559
* desired usage.
560
*/
561
mechOid = ProviderList.DEFAULT_MECH_OID;
562
key = new SearchKey(mechOid,
563
initiate? INITIATE_ONLY : ACCEPT_ONLY);
564
element = hashtable.get(key);
565
if (element == null) {
566
key = new SearchKey(mechOid, INITIATE_AND_ACCEPT);
567
element = hashtable.get(key);
568
if (element == null) {
569
/*
570
* Now just return any element that satisfies the
571
* desired usage.
572
*/
573
Object[] elements = hashtable.entrySet().toArray();
574
for (int i = 0; i < elements.length; i++) {
575
element = (GSSCredentialSpi)
576
((Map.Entry)elements[i]).getValue();
577
if (element.isInitiatorCredential() == initiate)
578
break;
579
} // for loop
580
}
581
}
582
} else {
583
584
if (initiate)
585
key = new SearchKey(mechOid, INITIATE_ONLY);
586
else
587
key = new SearchKey(mechOid, ACCEPT_ONLY);
588
589
element = hashtable.get(key);
590
591
if (element == null) {
592
key = new SearchKey(mechOid, INITIATE_AND_ACCEPT);
593
element = hashtable.get(key);
594
}
595
}
596
597
if (element == null)
598
throw new GSSExceptionImpl(GSSException.NO_CRED,
599
"No credential found for: " +
600
getElementStr(mechOid,
601
initiate? INITIATE_ONLY : ACCEPT_ONLY));
602
return element;
603
}
604
605
Set<GSSCredentialSpi> getElements() {
606
HashSet<GSSCredentialSpi> retVal =
607
new HashSet<GSSCredentialSpi>(hashtable.size());
608
Enumeration<GSSCredentialSpi> values = hashtable.elements();
609
while (values.hasMoreElements()) {
610
GSSCredentialSpi o = values.nextElement();
611
retVal.add(o);
612
}
613
return retVal;
614
}
615
616
private static String getElementStr(Oid mechOid, int usage) {
617
String displayString = mechOid.toString();
618
if (usage == GSSCredential.INITIATE_ONLY) {
619
displayString =
620
displayString.concat(" usage: Initiate");
621
} else if (usage == GSSCredential.ACCEPT_ONLY) {
622
displayString =
623
displayString.concat(" usage: Accept");
624
} else {
625
displayString =
626
displayString.concat(" usage: Initiate and Accept");
627
}
628
return displayString;
629
}
630
631
public String toString() {
632
633
if (destroyed) {
634
throw new IllegalStateException("This credential is " +
635
"no longer valid");
636
}
637
638
GSSCredentialSpi element = null;
639
StringBuffer buffer = new StringBuffer("[GSSCredential: ");
640
Object[] elements = hashtable.entrySet().toArray();
641
for (int i = 0; i < elements.length; i++) {
642
try {
643
buffer.append('\n');
644
element = (GSSCredentialSpi)
645
((Map.Entry)elements[i]).getValue();
646
buffer.append(element.getName());
647
buffer.append(' ');
648
buffer.append(element.getMechanism());
649
buffer.append(element.isInitiatorCredential() ?
650
" Initiate" : "");
651
buffer.append(element.isAcceptorCredential() ?
652
" Accept" : "");
653
buffer.append(" [");
654
buffer.append(element.getClass());
655
buffer.append(']');
656
} catch (GSSException e) {
657
// skip to next element
658
}
659
}
660
buffer.append(']');
661
return buffer.toString();
662
}
663
664
static class SearchKey {
665
private Oid mechOid = null;
666
private int usage = GSSCredential.INITIATE_AND_ACCEPT;
667
public SearchKey(Oid mechOid, int usage) {
668
669
this.mechOid = mechOid;
670
this.usage = usage;
671
}
672
public Oid getMech() {
673
return mechOid;
674
}
675
public int getUsage() {
676
return usage;
677
}
678
public boolean equals(Object other) {
679
if (! (other instanceof SearchKey))
680
return false;
681
SearchKey that = (SearchKey) other;
682
return ((this.mechOid.equals(that.mechOid)) &&
683
(this.usage == that.usage));
684
}
685
public int hashCode() {
686
return mechOid.hashCode();
687
}
688
}
689
690
}
691
692