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