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/spnego/SpNegoContext.java
38922 views
1
/*
2
* Copyright (c) 2005, 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.spnego;
27
28
import com.sun.security.jgss.ExtendedGSSContext;
29
import com.sun.security.jgss.InquireType;
30
import java.io.*;
31
import java.security.Provider;
32
import org.ietf.jgss.*;
33
import sun.security.jgss.*;
34
import sun.security.jgss.spi.*;
35
import sun.security.util.*;
36
37
/**
38
* Implements the mechanism specific context class for SPNEGO
39
* GSS-API mechanism
40
*
41
* @author Seema Malkani
42
* @since 1.6
43
*/
44
public class SpNegoContext implements GSSContextSpi {
45
46
/*
47
* The different states that this context can be in.
48
*/
49
private static final int STATE_NEW = 1;
50
private static final int STATE_IN_PROCESS = 2;
51
private static final int STATE_DONE = 3;
52
private static final int STATE_DELETED = 4;
53
54
private int state = STATE_NEW;
55
56
/*
57
* Optional features that the application can set and their default
58
* values.
59
*/
60
private boolean credDelegState = false;
61
private boolean mutualAuthState = true;
62
private boolean replayDetState = true;
63
private boolean sequenceDetState = true;
64
private boolean confState = true;
65
private boolean integState = true;
66
private boolean delegPolicyState = false;
67
68
private GSSNameSpi peerName = null;
69
private GSSNameSpi myName = null;
70
private SpNegoCredElement myCred = null;
71
72
private GSSContext mechContext = null;
73
private byte[] DER_mechTypes = null;
74
75
private int lifetime;
76
private ChannelBinding channelBinding;
77
private boolean initiator;
78
79
// the underlying negotiated mechanism
80
private Oid internal_mech = null;
81
82
// the SpNegoMechFactory that creates this context
83
final private SpNegoMechFactory factory;
84
85
// debug property
86
static final boolean DEBUG =
87
java.security.AccessController.doPrivileged(
88
new sun.security.action.GetBooleanAction
89
("sun.security.spnego.debug")).booleanValue();
90
91
/**
92
* Constructor for SpNegoContext to be called on the context initiator's
93
* side.
94
*/
95
public SpNegoContext(SpNegoMechFactory factory, GSSNameSpi peerName,
96
GSSCredentialSpi myCred,
97
int lifetime) throws GSSException {
98
99
if (peerName == null)
100
throw new IllegalArgumentException("Cannot have null peer name");
101
if ((myCred != null) && !(myCred instanceof SpNegoCredElement)) {
102
throw new IllegalArgumentException("Wrong cred element type");
103
}
104
this.peerName = peerName;
105
this.myCred = (SpNegoCredElement) myCred;
106
this.lifetime = lifetime;
107
this.initiator = true;
108
this.factory = factory;
109
}
110
111
/**
112
* Constructor for SpNegoContext to be called on the context acceptor's
113
* side.
114
*/
115
public SpNegoContext(SpNegoMechFactory factory, GSSCredentialSpi myCred)
116
throws GSSException {
117
if ((myCred != null) && !(myCred instanceof SpNegoCredElement)) {
118
throw new IllegalArgumentException("Wrong cred element type");
119
}
120
this.myCred = (SpNegoCredElement) myCred;
121
this.initiator = false;
122
this.factory = factory;
123
}
124
125
/**
126
* Constructor for SpNegoContext to import a previously exported context.
127
*/
128
public SpNegoContext(SpNegoMechFactory factory, byte [] interProcessToken)
129
throws GSSException {
130
throw new GSSException(GSSException.UNAVAILABLE,
131
-1, "GSS Import Context not available");
132
}
133
134
/**
135
* Requests that confidentiality be available.
136
*/
137
public final void requestConf(boolean value) throws GSSException {
138
if (state == STATE_NEW && isInitiator())
139
confState = value;
140
}
141
142
/**
143
* Is confidentiality available?
144
*/
145
public final boolean getConfState() {
146
return confState;
147
}
148
149
/**
150
* Requests that integrity be available.
151
*/
152
public final void requestInteg(boolean value) throws GSSException {
153
if (state == STATE_NEW && isInitiator())
154
integState = value;
155
}
156
157
/**
158
* Requests that deleg policy be respected.
159
*/
160
public final void requestDelegPolicy(boolean value) throws GSSException {
161
if (state == STATE_NEW && isInitiator())
162
delegPolicyState = value;
163
}
164
165
/**
166
* Is integrity available?
167
*/
168
public final boolean getIntegState() {
169
return integState;
170
}
171
172
/**
173
* Is deleg policy respected?
174
*/
175
public final boolean getDelegPolicyState() {
176
if (isInitiator() && mechContext != null &&
177
mechContext instanceof ExtendedGSSContext &&
178
(state == STATE_IN_PROCESS || state == STATE_DONE)) {
179
return ((ExtendedGSSContext)mechContext).getDelegPolicyState();
180
} else {
181
return delegPolicyState;
182
}
183
}
184
185
/**
186
* Requests that credential delegation be done during context
187
* establishment.
188
*/
189
public final void requestCredDeleg(boolean value) throws GSSException {
190
if (state == STATE_NEW && isInitiator())
191
credDelegState = value;
192
}
193
194
/**
195
* Is credential delegation enabled?
196
*/
197
public final boolean getCredDelegState() {
198
if (isInitiator() && mechContext != null &&
199
(state == STATE_IN_PROCESS || state == STATE_DONE)) {
200
return mechContext.getCredDelegState();
201
} else {
202
return credDelegState;
203
}
204
}
205
206
/**
207
* Requests that mutual authentication be done during context
208
* establishment. Since this is fromm the client's perspective, it
209
* essentially requests that the server be authenticated.
210
*/
211
public final void requestMutualAuth(boolean value) throws GSSException {
212
if (state == STATE_NEW && isInitiator()) {
213
mutualAuthState = value;
214
}
215
}
216
217
/**
218
* Is mutual authentication enabled? Since this is from the client's
219
* perspective, it essentially meas that the server is being
220
* authenticated.
221
*/
222
public final boolean getMutualAuthState() {
223
return mutualAuthState;
224
}
225
226
/**
227
* Returns the mechanism oid.
228
*
229
* @return the Oid of this context
230
*/
231
public final Oid getMech() {
232
if (isEstablished()) {
233
return getNegotiatedMech();
234
}
235
return (SpNegoMechFactory.GSS_SPNEGO_MECH_OID);
236
}
237
238
public final Oid getNegotiatedMech() {
239
return (internal_mech);
240
}
241
242
public final Provider getProvider() {
243
return SpNegoMechFactory.PROVIDER;
244
}
245
246
public final void dispose() throws GSSException {
247
mechContext = null;
248
state = STATE_DELETED;
249
}
250
251
/**
252
* Tests if this is the initiator side of the context.
253
*
254
* @return boolean indicating if this is initiator (true)
255
* or target (false)
256
*/
257
public final boolean isInitiator() {
258
return initiator;
259
}
260
261
/**
262
* Tests if the context can be used for per-message service.
263
* Context may allow the calls to the per-message service
264
* functions before being fully established.
265
*
266
* @return boolean indicating if per-message methods can
267
* be called.
268
*/
269
public final boolean isProtReady() {
270
return (state == STATE_DONE);
271
}
272
273
/**
274
* Initiator context establishment call. This method may be
275
* required to be called several times. A CONTINUE_NEEDED return
276
* call indicates that more calls are needed after the next token
277
* is received from the peer.
278
*
279
* @param is contains the token received from the peer. On the
280
* first call it will be ignored.
281
* @return any token required to be sent to the peer
282
* It is responsibility of the caller to send the token
283
* to its peer for processing.
284
* @exception GSSException
285
*/
286
public final byte[] initSecContext(InputStream is, int mechTokenSize)
287
throws GSSException {
288
289
byte[] retVal = null;
290
NegTokenInit initToken = null;
291
byte[] mechToken = null;
292
int errorCode = GSSException.FAILURE;
293
294
if (DEBUG) {
295
System.out.println("Entered SpNego.initSecContext with " +
296
"state=" + printState(state));
297
}
298
if (!isInitiator()) {
299
throw new GSSException(GSSException.FAILURE, -1,
300
"initSecContext on an acceptor GSSContext");
301
}
302
303
try {
304
if (state == STATE_NEW) {
305
state = STATE_IN_PROCESS;
306
307
errorCode = GSSException.NO_CRED;
308
309
// determine available mech set
310
Oid[] mechList = getAvailableMechs();
311
DER_mechTypes = getEncodedMechs(mechList);
312
313
// pull out first mechanism
314
internal_mech = mechList[0];
315
316
// get the token for first mechanism
317
mechToken = GSS_initSecContext(null);
318
319
errorCode = GSSException.DEFECTIVE_TOKEN;
320
// generate SPNEGO token
321
initToken = new NegTokenInit(DER_mechTypes, getContextFlags(),
322
mechToken, null);
323
if (DEBUG) {
324
System.out.println("SpNegoContext.initSecContext: " +
325
"sending token of type = " +
326
SpNegoToken.getTokenName(initToken.getType()));
327
}
328
// get the encoded token
329
retVal = initToken.getEncoded();
330
331
} else if (state == STATE_IN_PROCESS) {
332
333
errorCode = GSSException.FAILURE;
334
if (is == null) {
335
throw new GSSException(errorCode, -1,
336
"No token received from peer!");
337
}
338
339
errorCode = GSSException.DEFECTIVE_TOKEN;
340
byte[] server_token = new byte[is.available()];
341
SpNegoToken.readFully(is, server_token);
342
if (DEBUG) {
343
System.out.println("SpNegoContext.initSecContext: " +
344
"process received token = " +
345
SpNegoToken.getHexBytes(server_token));
346
}
347
348
// read the SPNEGO token
349
// token will be validated when parsing
350
NegTokenTarg targToken = new NegTokenTarg(server_token);
351
352
if (DEBUG) {
353
System.out.println("SpNegoContext.initSecContext: " +
354
"received token of type = " +
355
SpNegoToken.getTokenName(targToken.getType()));
356
}
357
358
// pull out mechanism
359
internal_mech = targToken.getSupportedMech();
360
if (internal_mech == null) {
361
// return wth failure
362
throw new GSSException(errorCode, -1,
363
"supported mechanism from server is null");
364
}
365
366
// get the negotiated result
367
SpNegoToken.NegoResult negoResult = null;
368
int result = targToken.getNegotiatedResult();
369
switch (result) {
370
case 0:
371
negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;
372
state = STATE_DONE;
373
break;
374
case 1:
375
negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;
376
state = STATE_IN_PROCESS;
377
break;
378
case 2:
379
negoResult = SpNegoToken.NegoResult.REJECT;
380
state = STATE_DELETED;
381
break;
382
default:
383
state = STATE_DONE;
384
break;
385
}
386
387
errorCode = GSSException.BAD_MECH;
388
389
if (negoResult == SpNegoToken.NegoResult.REJECT) {
390
throw new GSSException(errorCode, -1,
391
internal_mech.toString());
392
}
393
394
errorCode = GSSException.DEFECTIVE_TOKEN;
395
396
if ((negoResult == SpNegoToken.NegoResult.ACCEPT_COMPLETE) ||
397
(negoResult == SpNegoToken.NegoResult.ACCEPT_INCOMPLETE)) {
398
399
// pull out the mechanism token
400
byte[] accept_token = targToken.getResponseToken();
401
if (accept_token == null) {
402
if (!isMechContextEstablished()) {
403
// return with failure
404
throw new GSSException(errorCode, -1,
405
"mechanism token from server is null");
406
}
407
} else {
408
mechToken = GSS_initSecContext(accept_token);
409
}
410
// verify MIC
411
if (!GSSUtil.useMSInterop()) {
412
byte[] micToken = targToken.getMechListMIC();
413
if (!verifyMechListMIC(DER_mechTypes, micToken)) {
414
throw new GSSException(errorCode, -1,
415
"verification of MIC on MechList Failed!");
416
}
417
}
418
if (isMechContextEstablished()) {
419
state = STATE_DONE;
420
retVal = mechToken;
421
if (DEBUG) {
422
System.out.println("SPNEGO Negotiated Mechanism = "
423
+ internal_mech + " " +
424
GSSUtil.getMechStr(internal_mech));
425
}
426
} else {
427
// generate SPNEGO token
428
initToken = new NegTokenInit(null, null,
429
mechToken, null);
430
if (DEBUG) {
431
System.out.println("SpNegoContext.initSecContext:" +
432
" continue sending token of type = " +
433
SpNegoToken.getTokenName(initToken.getType()));
434
}
435
// get the encoded token
436
retVal = initToken.getEncoded();
437
}
438
}
439
440
} else {
441
// XXX Use logging API
442
if (DEBUG) {
443
System.out.println(state);
444
}
445
}
446
if (DEBUG) {
447
if (retVal != null) {
448
System.out.println("SNegoContext.initSecContext: " +
449
"sending token = " + SpNegoToken.getHexBytes(retVal));
450
}
451
}
452
} catch (GSSException e) {
453
GSSException gssException =
454
new GSSException(errorCode, -1, e.getMessage());
455
gssException.initCause(e);
456
throw gssException;
457
} catch (IOException e) {
458
GSSException gssException =
459
new GSSException(GSSException.FAILURE, -1, e.getMessage());
460
gssException.initCause(e);
461
throw gssException;
462
}
463
464
return retVal;
465
}
466
467
468
/**
469
* Acceptor's context establishment call. This method may be
470
* required to be called several times. A CONTINUE_NEEDED return
471
* call indicates that more calls are needed after the next token
472
* is received from the peer.
473
*
474
* @param is contains the token received from the peer.
475
* @return any token required to be sent to the peer
476
* It is responsibility of the caller to send the token
477
* to its peer for processing.
478
* @exception GSSException
479
*/
480
public final byte[] acceptSecContext(InputStream is, int mechTokenSize)
481
throws GSSException {
482
483
byte[] retVal = null;
484
SpNegoToken.NegoResult negoResult;
485
boolean valid = true;
486
487
if (DEBUG) {
488
System.out.println("Entered SpNegoContext.acceptSecContext with " +
489
"state=" + printState(state));
490
}
491
492
if (isInitiator()) {
493
throw new GSSException(GSSException.FAILURE, -1,
494
"acceptSecContext on an initiator " +
495
"GSSContext");
496
}
497
try {
498
if (state == STATE_NEW) {
499
state = STATE_IN_PROCESS;
500
501
// read data
502
byte[] token = new byte[is.available()];
503
SpNegoToken.readFully(is, token);
504
if (DEBUG) {
505
System.out.println("SpNegoContext.acceptSecContext: " +
506
"receiving token = " +
507
SpNegoToken.getHexBytes(token));
508
}
509
510
// read the SPNEGO token
511
// token will be validated when parsing
512
NegTokenInit initToken = new NegTokenInit(token);
513
514
if (DEBUG) {
515
System.out.println("SpNegoContext.acceptSecContext: " +
516
"received token of type = " +
517
SpNegoToken.getTokenName(initToken.getType()));
518
}
519
520
Oid[] mechList = initToken.getMechTypeList();
521
DER_mechTypes = initToken.getMechTypes();
522
if (DER_mechTypes == null) {
523
valid = false;
524
}
525
526
/*
527
* Select the best match between the list of mechs
528
* that the initiator requested and the list that
529
* the acceptor will support.
530
*/
531
Oid[] supported_mechSet = getAvailableMechs();
532
Oid mech_wanted =
533
negotiate_mech_type(supported_mechSet, mechList);
534
if (mech_wanted == null) {
535
valid = false;
536
}
537
// save the desired mechanism
538
internal_mech = mech_wanted;
539
540
// get the token for mechanism
541
byte[] accept_token;
542
543
if (mechList[0].equals(mech_wanted) ||
544
(GSSUtil.isKerberosMech(mechList[0]) &&
545
GSSUtil.isKerberosMech(mech_wanted))) {
546
// get the mechanism token
547
if (DEBUG && !mech_wanted.equals(mechList[0])) {
548
System.out.println("SpNegoContext.acceptSecContext: " +
549
"negotiated mech adjusted to " + mechList[0]);
550
}
551
byte[] mechToken = initToken.getMechToken();
552
if (mechToken == null) {
553
throw new GSSException(GSSException.FAILURE, -1,
554
"mechToken is missing");
555
}
556
accept_token = GSS_acceptSecContext(mechToken);
557
mech_wanted = mechList[0];
558
} else {
559
accept_token = null;
560
}
561
562
// verify MIC
563
if (!GSSUtil.useMSInterop() && valid) {
564
valid = verifyMechListMIC(DER_mechTypes,
565
initToken.getMechListMIC());
566
}
567
568
// determine negotiated result status
569
if (valid) {
570
if (isMechContextEstablished()) {
571
negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;
572
state = STATE_DONE;
573
// now set the context flags for acceptor
574
setContextFlags();
575
// print the negotiated mech info
576
if (DEBUG) {
577
System.out.println("SPNEGO Negotiated Mechanism = "
578
+ internal_mech + " " +
579
GSSUtil.getMechStr(internal_mech));
580
}
581
} else {
582
negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;
583
state = STATE_IN_PROCESS;
584
}
585
} else {
586
negoResult = SpNegoToken.NegoResult.REJECT;
587
state = STATE_DONE;
588
}
589
590
if (DEBUG) {
591
System.out.println("SpNegoContext.acceptSecContext: " +
592
"mechanism wanted = " + mech_wanted);
593
System.out.println("SpNegoContext.acceptSecContext: " +
594
"negotiated result = " + negoResult);
595
}
596
597
// generate SPNEGO token
598
NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),
599
mech_wanted, accept_token, null);
600
if (DEBUG) {
601
System.out.println("SpNegoContext.acceptSecContext: " +
602
"sending token of type = " +
603
SpNegoToken.getTokenName(targToken.getType()));
604
}
605
// get the encoded token
606
retVal = targToken.getEncoded();
607
608
} else if (state == STATE_IN_PROCESS) {
609
// read data
610
byte[] token = new byte[is.available()];
611
SpNegoToken.readFully(is, token);
612
if (DEBUG) {
613
System.out.println("SpNegoContext.acceptSecContext: " +
614
"receiving token = " +
615
SpNegoToken.getHexBytes(token));
616
}
617
618
// read the SPNEGO token
619
// token will be validated when parsing
620
NegTokenTarg inputToken = new NegTokenTarg(token);
621
622
if (DEBUG) {
623
System.out.println("SpNegoContext.acceptSecContext: " +
624
"received token of type = " +
625
SpNegoToken.getTokenName(inputToken.getType()));
626
}
627
628
// read the token
629
byte[] client_token = inputToken.getResponseToken();
630
byte[] accept_token = GSS_acceptSecContext(client_token);
631
if (accept_token == null) {
632
valid = false;
633
}
634
635
// determine negotiated result status
636
if (valid) {
637
if (isMechContextEstablished()) {
638
negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;
639
state = STATE_DONE;
640
} else {
641
negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;
642
state = STATE_IN_PROCESS;
643
}
644
} else {
645
negoResult = SpNegoToken.NegoResult.REJECT;
646
state = STATE_DONE;
647
}
648
649
// generate SPNEGO token
650
NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),
651
null, accept_token, null);
652
if (DEBUG) {
653
System.out.println("SpNegoContext.acceptSecContext: " +
654
"sending token of type = " +
655
SpNegoToken.getTokenName(targToken.getType()));
656
}
657
// get the encoded token
658
retVal = targToken.getEncoded();
659
660
} else {
661
// XXX Use logging API
662
if (DEBUG) {
663
System.out.println("AcceptSecContext: state = " + state);
664
}
665
}
666
if (DEBUG) {
667
System.out.println("SpNegoContext.acceptSecContext: " +
668
"sending token = " + SpNegoToken.getHexBytes(retVal));
669
}
670
} catch (IOException e) {
671
GSSException gssException =
672
new GSSException(GSSException.FAILURE, -1, e.getMessage());
673
gssException.initCause(e);
674
throw gssException;
675
}
676
677
if (state == STATE_DONE) {
678
// now set the context flags for acceptor
679
setContextFlags();
680
}
681
return retVal;
682
}
683
684
/**
685
* obtain the available mechanisms
686
*/
687
private Oid[] getAvailableMechs() {
688
if (myCred != null) {
689
Oid[] mechs = new Oid[1];
690
mechs[0] = myCred.getInternalMech();
691
return mechs;
692
} else {
693
return factory.availableMechs;
694
}
695
}
696
697
/**
698
* get ther DER encoded MechList
699
*/
700
private byte[] getEncodedMechs(Oid[] mechSet)
701
throws IOException, GSSException {
702
703
DerOutputStream mech = new DerOutputStream();
704
for (int i = 0; i < mechSet.length; i++) {
705
byte[] mechType = mechSet[i].getDER();
706
mech.write(mechType);
707
}
708
// insert in SEQUENCE
709
DerOutputStream mechTypeList = new DerOutputStream();
710
mechTypeList.write(DerValue.tag_Sequence, mech);
711
byte[] encoded = mechTypeList.toByteArray();
712
return encoded;
713
}
714
715
/**
716
* get the context flags
717
*/
718
private BitArray getContextFlags() {
719
BitArray out = new BitArray(7);
720
721
if (getCredDelegState()) out.set(0, true);
722
if (getMutualAuthState()) out.set(1, true);
723
if (getReplayDetState()) out.set(2, true);
724
if (getSequenceDetState()) out.set(3, true);
725
if (getConfState()) out.set(5, true);
726
if (getIntegState()) out.set(6, true);
727
728
return out;
729
}
730
731
// Only called on acceptor side. On the initiator side, most flags
732
// are already set at request. For those that might get chanegd,
733
// state from mech below is used.
734
private void setContextFlags() {
735
736
if (mechContext != null) {
737
// default for cred delegation is false
738
if (mechContext.getCredDelegState()) {
739
credDelegState = true;
740
}
741
// default for the following are true
742
if (!mechContext.getMutualAuthState()) {
743
mutualAuthState = false;
744
}
745
if (!mechContext.getReplayDetState()) {
746
replayDetState = false;
747
}
748
if (!mechContext.getSequenceDetState()) {
749
sequenceDetState = false;
750
}
751
if (!mechContext.getIntegState()) {
752
integState = false;
753
}
754
if (!mechContext.getConfState()) {
755
confState = false;
756
}
757
}
758
}
759
760
/**
761
* generate MIC on mechList. Not used at the moment.
762
*/
763
/*private byte[] generateMechListMIC(byte[] mechTypes)
764
throws GSSException {
765
766
// sanity check the required input
767
if (mechTypes == null) {
768
if (DEBUG) {
769
System.out.println("SpNegoContext: no MIC token included");
770
}
771
return null;
772
}
773
774
// check if mechanism supports integrity
775
if (!mechContext.getIntegState()) {
776
if (DEBUG) {
777
System.out.println("SpNegoContext: no MIC token included" +
778
" - mechanism does not support integrity");
779
}
780
return null;
781
}
782
783
// compute MIC on DER encoded mechanism list
784
byte[] mic = null;
785
try {
786
MessageProp prop = new MessageProp(0, true);
787
mic = getMIC(mechTypes, 0, mechTypes.length, prop);
788
if (DEBUG) {
789
System.out.println("SpNegoContext: getMIC = " +
790
SpNegoToken.getHexBytes(mic));
791
}
792
} catch (GSSException e) {
793
mic = null;
794
if (DEBUG) {
795
System.out.println("SpNegoContext: no MIC token included" +
796
" - getMIC failed : " + e.getMessage());
797
}
798
}
799
return mic;
800
}*/
801
802
/**
803
* verify MIC on MechList
804
*/
805
private boolean verifyMechListMIC(byte[] mechTypes, byte[] token)
806
throws GSSException {
807
808
// sanity check the input
809
if (token == null) {
810
if (DEBUG) {
811
System.out.println("SpNegoContext: no MIC token validation");
812
}
813
return true;
814
}
815
816
// check if mechanism supports integrity
817
if (!mechContext.getIntegState()) {
818
if (DEBUG) {
819
System.out.println("SpNegoContext: no MIC token validation" +
820
" - mechanism does not support integrity");
821
}
822
return true;
823
}
824
825
// now verify the token
826
boolean valid = false;
827
try {
828
MessageProp prop = new MessageProp(0, true);
829
verifyMIC(token, 0, token.length, mechTypes,
830
0, mechTypes.length, prop);
831
valid = true;
832
} catch (GSSException e) {
833
valid = false;
834
if (DEBUG) {
835
System.out.println("SpNegoContext: MIC validation failed! " +
836
e.getMessage());
837
}
838
}
839
return valid;
840
}
841
842
/**
843
* call gss_init_sec_context for the corresponding underlying mechanism
844
*/
845
private byte[] GSS_initSecContext(byte[] token) throws GSSException {
846
byte[] tok = null;
847
848
if (mechContext == null) {
849
// initialize mech context
850
GSSName serverName =
851
factory.manager.createName(peerName.toString(),
852
peerName.getStringNameType(), internal_mech);
853
GSSCredential cred = null;
854
if (myCred != null) {
855
// create context with provided credential
856
cred = new GSSCredentialImpl(factory.manager,
857
myCred.getInternalCred());
858
}
859
mechContext =
860
factory.manager.createContext(serverName,
861
internal_mech, cred, GSSContext.DEFAULT_LIFETIME);
862
mechContext.requestConf(confState);
863
mechContext.requestInteg(integState);
864
mechContext.requestCredDeleg(credDelegState);
865
mechContext.requestMutualAuth(mutualAuthState);
866
mechContext.requestReplayDet(replayDetState);
867
mechContext.requestSequenceDet(sequenceDetState);
868
if (mechContext instanceof ExtendedGSSContext) {
869
((ExtendedGSSContext)mechContext).requestDelegPolicy(
870
delegPolicyState);
871
}
872
}
873
874
// pass token
875
if (token != null) {
876
tok = token;
877
} else {
878
tok = new byte[0];
879
}
880
881
// pass token to mechanism initSecContext
882
byte[] init_token = mechContext.initSecContext(tok, 0, tok.length);
883
884
return init_token;
885
}
886
887
/**
888
* call gss_accept_sec_context for the corresponding underlying mechanism
889
*/
890
private byte[] GSS_acceptSecContext(byte[] token) throws GSSException {
891
892
if (mechContext == null) {
893
// initialize mech context
894
GSSCredential cred = null;
895
if (myCred != null) {
896
// create context with provided credential
897
cred = new GSSCredentialImpl(factory.manager,
898
myCred.getInternalCred());
899
}
900
mechContext =
901
factory.manager.createContext(cred);
902
}
903
904
// pass token to mechanism acceptSecContext
905
byte[] accept_token =
906
mechContext.acceptSecContext(token, 0, token.length);
907
908
return accept_token;
909
}
910
911
/**
912
* This routine compares the recieved mechset to the mechset that
913
* this server can support. It looks sequentially through the mechset
914
* and the first one that matches what the server can support is
915
* chosen as the negotiated mechanism. If one is found, negResult
916
* is set to ACCEPT_COMPLETE, otherwise we return NULL and negResult
917
* is set to REJECT.
918
*/
919
private static Oid negotiate_mech_type(Oid[] supported_mechSet,
920
Oid[] mechSet) {
921
for (int i = 0; i < supported_mechSet.length; i++) {
922
for (int j = 0; j < mechSet.length; j++) {
923
if (mechSet[j].equals(supported_mechSet[i])) {
924
if (DEBUG) {
925
System.out.println("SpNegoContext: " +
926
"negotiated mechanism = " + mechSet[j]);
927
}
928
return (mechSet[j]);
929
}
930
}
931
}
932
return null;
933
}
934
935
public final boolean isEstablished() {
936
return (state == STATE_DONE);
937
}
938
939
public final boolean isMechContextEstablished() {
940
if (mechContext != null) {
941
return mechContext.isEstablished();
942
} else {
943
if (DEBUG) {
944
System.out.println("The underlying mechanism context has " +
945
"not been initialized");
946
}
947
return false;
948
}
949
}
950
951
public final byte [] export() throws GSSException {
952
throw new GSSException(GSSException.UNAVAILABLE, -1,
953
"GSS Export Context not available");
954
}
955
956
/**
957
* Sets the channel bindings to be used during context
958
* establishment.
959
*/
960
public final void setChannelBinding(ChannelBinding channelBinding)
961
throws GSSException {
962
this.channelBinding = channelBinding;
963
}
964
965
final ChannelBinding getChannelBinding() {
966
return channelBinding;
967
}
968
969
/*
970
* Anonymity is a little different in that after an application
971
* requests anonymity it will want to know whether the mechanism
972
* can support it or not, prior to sending any tokens across for
973
* context establishment. Since this is from the initiator's
974
* perspective, it essentially requests that the initiator be
975
* anonymous.
976
*/
977
public final void requestAnonymity(boolean value) throws GSSException {
978
// Ignore silently. Application will check back with
979
// getAnonymityState.
980
}
981
982
// RFC 2853 actually calls for this to be called after context
983
// establishment to get the right answer, but that is
984
// incorrect. The application may not want to send over any
985
// tokens if anonymity is not available.
986
public final boolean getAnonymityState() {
987
return false;
988
}
989
990
/**
991
* Requests the desired lifetime. Can only be used on the context
992
* initiator's side.
993
*/
994
public void requestLifetime(int lifetime) throws GSSException {
995
if (state == STATE_NEW && isInitiator())
996
this.lifetime = lifetime;
997
}
998
999
/**
1000
* The lifetime remaining for this context.
1001
*/
1002
public final int getLifetime() {
1003
if (mechContext != null) {
1004
return mechContext.getLifetime();
1005
} else {
1006
return GSSContext.INDEFINITE_LIFETIME;
1007
}
1008
}
1009
1010
public final boolean isTransferable() throws GSSException {
1011
return false;
1012
}
1013
1014
/**
1015
* Requests that sequence checking be done on the GSS wrap and MIC
1016
* tokens.
1017
*/
1018
public final void requestSequenceDet(boolean value) throws GSSException {
1019
if (state == STATE_NEW && isInitiator())
1020
sequenceDetState = value;
1021
}
1022
1023
/**
1024
* Is sequence checking enabled on the GSS Wrap and MIC tokens?
1025
* We enable sequence checking if replay detection is enabled.
1026
*/
1027
public final boolean getSequenceDetState() {
1028
return sequenceDetState || replayDetState;
1029
}
1030
1031
/**
1032
* Requests that replay detection be done on the GSS wrap and MIC
1033
* tokens.
1034
*/
1035
public final void requestReplayDet(boolean value) throws GSSException {
1036
if (state == STATE_NEW && isInitiator())
1037
replayDetState = value;
1038
}
1039
1040
/**
1041
* Is replay detection enabled on the GSS wrap and MIC tokens?
1042
* We enable replay detection if sequence checking is enabled.
1043
*/
1044
public final boolean getReplayDetState() {
1045
return replayDetState || sequenceDetState;
1046
}
1047
1048
public final GSSNameSpi getTargName() throws GSSException {
1049
// fill-in the GSSName
1050
// get the peer name for the mechanism
1051
if (mechContext != null) {
1052
GSSNameImpl targName = (GSSNameImpl)mechContext.getTargName();
1053
peerName = targName.getElement(internal_mech);
1054
return peerName;
1055
} else {
1056
if (DEBUG) {
1057
System.out.println("The underlying mechanism context has " +
1058
"not been initialized");
1059
}
1060
return null;
1061
}
1062
}
1063
1064
public final GSSNameSpi getSrcName() throws GSSException {
1065
// fill-in the GSSName
1066
// get the src name for the mechanism
1067
if (mechContext != null) {
1068
GSSNameImpl srcName = (GSSNameImpl)mechContext.getSrcName();
1069
myName = srcName.getElement(internal_mech);
1070
return myName;
1071
} else {
1072
if (DEBUG) {
1073
System.out.println("The underlying mechanism context has " +
1074
"not been initialized");
1075
}
1076
return null;
1077
}
1078
}
1079
1080
/**
1081
* Returns the delegated credential for the context. This
1082
* is an optional feature of contexts which not all
1083
* mechanisms will support. A context can be requested to
1084
* support credential delegation by using the <b>CRED_DELEG</b>.
1085
* This is only valid on the acceptor side of the context.
1086
* @return GSSCredentialSpi object for the delegated credential
1087
* @exception GSSException
1088
* @see GSSContext#getCredDelegState
1089
*/
1090
public final GSSCredentialSpi getDelegCred() throws GSSException {
1091
if (state != STATE_IN_PROCESS && state != STATE_DONE)
1092
throw new GSSException(GSSException.NO_CONTEXT);
1093
if (mechContext != null) {
1094
GSSCredentialImpl delegCred =
1095
(GSSCredentialImpl)mechContext.getDelegCred();
1096
if (delegCred == null) {
1097
return null;
1098
}
1099
// determine delegated cred element usage
1100
boolean initiate = false;
1101
if (delegCred.getUsage() == GSSCredential.INITIATE_ONLY) {
1102
initiate = true;
1103
}
1104
GSSCredentialSpi mechCred =
1105
delegCred.getElement(internal_mech, initiate);
1106
SpNegoCredElement cred = new SpNegoCredElement(mechCred);
1107
return cred.getInternalCred();
1108
} else {
1109
throw new GSSException(GSSException.NO_CONTEXT, -1,
1110
"getDelegCred called in invalid state!");
1111
}
1112
}
1113
1114
public final int getWrapSizeLimit(int qop, boolean confReq,
1115
int maxTokSize) throws GSSException {
1116
if (mechContext != null) {
1117
return mechContext.getWrapSizeLimit(qop, confReq, maxTokSize);
1118
} else {
1119
throw new GSSException(GSSException.NO_CONTEXT, -1,
1120
"getWrapSizeLimit called in invalid state!");
1121
}
1122
}
1123
1124
public final byte[] wrap(byte inBuf[], int offset, int len,
1125
MessageProp msgProp) throws GSSException {
1126
if (mechContext != null) {
1127
return mechContext.wrap(inBuf, offset, len, msgProp);
1128
} else {
1129
throw new GSSException(GSSException.NO_CONTEXT, -1,
1130
"Wrap called in invalid state!");
1131
}
1132
}
1133
1134
public final void wrap(InputStream is, OutputStream os,
1135
MessageProp msgProp) throws GSSException {
1136
if (mechContext != null) {
1137
mechContext.wrap(is, os, msgProp);
1138
} else {
1139
throw new GSSException(GSSException.NO_CONTEXT, -1,
1140
"Wrap called in invalid state!");
1141
}
1142
}
1143
1144
public final byte[] unwrap(byte inBuf[], int offset, int len,
1145
MessageProp msgProp)
1146
throws GSSException {
1147
if (mechContext != null) {
1148
return mechContext.unwrap(inBuf, offset, len, msgProp);
1149
} else {
1150
throw new GSSException(GSSException.NO_CONTEXT, -1,
1151
"UnWrap called in invalid state!");
1152
}
1153
}
1154
1155
public final void unwrap(InputStream is, OutputStream os,
1156
MessageProp msgProp) throws GSSException {
1157
if (mechContext != null) {
1158
mechContext.unwrap(is, os, msgProp);
1159
} else {
1160
throw new GSSException(GSSException.NO_CONTEXT, -1,
1161
"UnWrap called in invalid state!");
1162
}
1163
}
1164
1165
public final byte[] getMIC(byte []inMsg, int offset, int len,
1166
MessageProp msgProp)
1167
throws GSSException {
1168
if (mechContext != null) {
1169
return mechContext.getMIC(inMsg, offset, len, msgProp);
1170
} else {
1171
throw new GSSException(GSSException.NO_CONTEXT, -1,
1172
"getMIC called in invalid state!");
1173
}
1174
}
1175
1176
public final void getMIC(InputStream is, OutputStream os,
1177
MessageProp msgProp) throws GSSException {
1178
if (mechContext != null) {
1179
mechContext.getMIC(is, os, msgProp);
1180
} else {
1181
throw new GSSException(GSSException.NO_CONTEXT, -1,
1182
"getMIC called in invalid state!");
1183
}
1184
}
1185
1186
public final void verifyMIC(byte []inTok, int tokOffset, int tokLen,
1187
byte[] inMsg, int msgOffset, int msgLen,
1188
MessageProp msgProp)
1189
throws GSSException {
1190
if (mechContext != null) {
1191
mechContext.verifyMIC(inTok, tokOffset, tokLen, inMsg, msgOffset,
1192
msgLen, msgProp);
1193
} else {
1194
throw new GSSException(GSSException.NO_CONTEXT, -1,
1195
"verifyMIC called in invalid state!");
1196
}
1197
}
1198
1199
public final void verifyMIC(InputStream is, InputStream msgStr,
1200
MessageProp msgProp) throws GSSException {
1201
if (mechContext != null) {
1202
mechContext.verifyMIC(is, msgStr, msgProp);
1203
} else {
1204
throw new GSSException(GSSException.NO_CONTEXT, -1,
1205
"verifyMIC called in invalid state!");
1206
}
1207
}
1208
1209
private static String printState(int state) {
1210
switch (state) {
1211
case STATE_NEW:
1212
return ("STATE_NEW");
1213
case STATE_IN_PROCESS:
1214
return ("STATE_IN_PROCESS");
1215
case STATE_DONE:
1216
return ("STATE_DONE");
1217
case STATE_DELETED:
1218
return ("STATE_DELETED");
1219
default:
1220
return ("Unknown state " + state);
1221
}
1222
}
1223
1224
/**
1225
* Retrieve attribute of the context for {@code type}.
1226
*/
1227
public Object inquireSecContext(InquireType type)
1228
throws GSSException {
1229
if (mechContext == null) {
1230
throw new GSSException(GSSException.NO_CONTEXT, -1,
1231
"Underlying mech not established.");
1232
}
1233
if (mechContext instanceof ExtendedGSSContext) {
1234
return ((ExtendedGSSContext)mechContext).inquireSecContext(type);
1235
} else {
1236
throw new GSSException(GSSException.BAD_MECH, -1,
1237
"inquireSecContext not supported by underlying mech.");
1238
}
1239
}
1240
}
1241
1242
1243