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/spnego/SpNegoContext.java
41161 views
1
/*
2
* Copyright (c) 2005, 2018, 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 java.io.*;
29
import java.security.Provider;
30
import org.ietf.jgss.*;
31
import sun.security.action.GetBooleanAction;
32
import sun.security.jgss.*;
33
import sun.security.jgss.spi.*;
34
import sun.security.util.*;
35
36
/**
37
* Implements the mechanism specific context class for SPNEGO
38
* GSS-API mechanism
39
*
40
* @author Seema Malkani
41
* @since 1.6
42
*/
43
public class SpNegoContext implements GSSContextSpi {
44
45
/*
46
* The different states that this context can be in.
47
*/
48
private static final int STATE_NEW = 1;
49
private static final int STATE_IN_PROCESS = 2;
50
private static final int STATE_DONE = 3;
51
private static final int STATE_DELETED = 4;
52
53
private int state = STATE_NEW;
54
55
/*
56
* Optional features that the application can set and their default
57
* values.
58
*/
59
private boolean credDelegState = false;
60
private boolean mutualAuthState = true;
61
private boolean replayDetState = true;
62
private boolean sequenceDetState = true;
63
private boolean confState = true;
64
private boolean integState = true;
65
private boolean delegPolicyState = false;
66
67
private GSSNameSpi peerName = null;
68
private GSSNameSpi myName = null;
69
private SpNegoCredElement myCred = null;
70
71
private GSSContext mechContext = null;
72
private byte[] DER_mechTypes = null;
73
74
private int lifetime;
75
private ChannelBinding channelBinding;
76
private boolean initiator;
77
78
// the underlying negotiated mechanism
79
private Oid internal_mech = null;
80
81
// the SpNegoMechFactory that creates this context
82
private final SpNegoMechFactory factory;
83
84
// debug property
85
static final boolean DEBUG = GetBooleanAction
86
.privilegedGetProperty("sun.security.spnego.debug");
87
88
/**
89
* Constructor for SpNegoContext to be called on the context initiator's
90
* side.
91
*/
92
public SpNegoContext(SpNegoMechFactory factory, GSSNameSpi peerName,
93
GSSCredentialSpi myCred,
94
int lifetime) throws GSSException {
95
96
if (peerName == null)
97
throw new IllegalArgumentException("Cannot have null peer name");
98
if ((myCred != null) && !(myCred instanceof SpNegoCredElement)) {
99
throw new IllegalArgumentException("Wrong cred element type");
100
}
101
this.peerName = peerName;
102
this.myCred = (SpNegoCredElement) myCred;
103
this.lifetime = lifetime;
104
this.initiator = true;
105
this.factory = factory;
106
}
107
108
/**
109
* Constructor for SpNegoContext to be called on the context acceptor's
110
* side.
111
*/
112
public SpNegoContext(SpNegoMechFactory factory, GSSCredentialSpi myCred)
113
throws GSSException {
114
if ((myCred != null) && !(myCred instanceof SpNegoCredElement)) {
115
throw new IllegalArgumentException("Wrong cred element type");
116
}
117
this.myCred = (SpNegoCredElement) myCred;
118
this.initiator = false;
119
this.factory = factory;
120
}
121
122
/**
123
* Constructor for SpNegoContext to import a previously exported context.
124
*/
125
public SpNegoContext(SpNegoMechFactory factory, byte [] interProcessToken)
126
throws GSSException {
127
throw new GSSException(GSSException.UNAVAILABLE,
128
-1, "GSS Import Context not available");
129
}
130
131
/**
132
* Requests that confidentiality be available.
133
*/
134
public final void requestConf(boolean value) throws GSSException {
135
if (state == STATE_NEW && isInitiator())
136
confState = value;
137
}
138
139
/**
140
* Is confidentiality available?
141
*/
142
public final boolean getConfState() {
143
return confState;
144
}
145
146
/**
147
* Requests that integrity be available.
148
*/
149
public final void requestInteg(boolean value) throws GSSException {
150
if (state == STATE_NEW && isInitiator())
151
integState = value;
152
}
153
154
/**
155
* Requests that deleg policy be respected.
156
*/
157
public final void requestDelegPolicy(boolean value) throws GSSException {
158
if (state == STATE_NEW && isInitiator())
159
delegPolicyState = value;
160
}
161
162
/**
163
* Is integrity available?
164
*/
165
public final boolean getIntegState() {
166
return integState;
167
}
168
169
/**
170
* Is deleg policy respected?
171
*/
172
public final boolean getDelegPolicyState() {
173
if (isInitiator() && mechContext != null &&
174
mechContext instanceof GSSContextImpl &&
175
(state == STATE_IN_PROCESS || state == STATE_DONE)) {
176
return ((GSSContextImpl)mechContext).getDelegPolicyState();
177
} else {
178
return delegPolicyState;
179
}
180
}
181
182
/**
183
* Requests that credential delegation be done during context
184
* establishment.
185
*/
186
public final void requestCredDeleg(boolean value) throws GSSException {
187
if (state == STATE_NEW && isInitiator())
188
credDelegState = value;
189
}
190
191
/**
192
* Is credential delegation enabled?
193
*/
194
public final boolean getCredDelegState() {
195
if (isInitiator() && mechContext != null &&
196
(state == STATE_IN_PROCESS || state == STATE_DONE)) {
197
return mechContext.getCredDelegState();
198
} else {
199
return credDelegState;
200
}
201
}
202
203
/**
204
* Requests that mutual authentication be done during context
205
* establishment. Since this is fromm the client's perspective, it
206
* essentially requests that the server be authenticated.
207
*/
208
public final void requestMutualAuth(boolean value) throws GSSException {
209
if (state == STATE_NEW && isInitiator()) {
210
mutualAuthState = value;
211
}
212
}
213
214
/**
215
* Is mutual authentication enabled? Since this is from the client's
216
* perspective, it essentially meas that the server is being
217
* authenticated.
218
*/
219
public final boolean getMutualAuthState() {
220
return mutualAuthState;
221
}
222
223
/**
224
* Returns the mechanism oid.
225
*
226
* @return the Oid of this context
227
*/
228
public final Oid getMech() {
229
if (isEstablished()) {
230
return getNegotiatedMech();
231
}
232
return (SpNegoMechFactory.GSS_SPNEGO_MECH_OID);
233
}
234
235
public final Oid getNegotiatedMech() {
236
return (internal_mech);
237
}
238
239
public final Provider getProvider() {
240
return SpNegoMechFactory.PROVIDER;
241
}
242
243
public final void dispose() throws GSSException {
244
mechContext = null;
245
state = STATE_DELETED;
246
}
247
248
/**
249
* Tests if this is the initiator side of the context.
250
*
251
* @return boolean indicating if this is initiator (true)
252
* or target (false)
253
*/
254
public final boolean isInitiator() {
255
return initiator;
256
}
257
258
/**
259
* Tests if the context can be used for per-message service.
260
* Context may allow the calls to the per-message service
261
* functions before being fully established.
262
*
263
* @return boolean indicating if per-message methods can
264
* be called.
265
*/
266
public final boolean isProtReady() {
267
return (state == STATE_DONE);
268
}
269
270
/**
271
* Initiator context establishment call. This method may be
272
* required to be called several times. A CONTINUE_NEEDED return
273
* call indicates that more calls are needed after the next token
274
* is received from the peer.
275
*
276
* @param is contains the token received from the peer. On the
277
* first call it will be ignored.
278
* @return any token required to be sent to the peer
279
* It is responsibility of the caller to send the token
280
* to its peer for processing.
281
* @exception GSSException
282
*/
283
@Deprecated(since="11")
284
public final byte[] initSecContext(InputStream is, int mechTokenSize)
285
throws GSSException {
286
287
byte[] retVal = null;
288
NegTokenInit initToken = null;
289
byte[] mechToken = null;
290
int errorCode = GSSException.FAILURE;
291
292
if (DEBUG) {
293
System.out.println("Entered SpNego.initSecContext with " +
294
"state=" + printState(state));
295
}
296
if (!isInitiator()) {
297
throw new GSSException(GSSException.FAILURE, -1,
298
"initSecContext on an acceptor GSSContext");
299
}
300
301
try {
302
if (state == STATE_NEW) {
303
state = STATE_IN_PROCESS;
304
305
errorCode = GSSException.NO_CRED;
306
307
// determine available mech set
308
Oid[] mechList = getAvailableMechs();
309
DER_mechTypes = getEncodedMechs(mechList);
310
311
// pull out first mechanism
312
internal_mech = mechList[0];
313
314
// get the token for first mechanism
315
mechToken = GSS_initSecContext(null);
316
317
errorCode = GSSException.DEFECTIVE_TOKEN;
318
// generate SPNEGO token
319
initToken = new NegTokenInit(DER_mechTypes, getContextFlags(),
320
mechToken, null);
321
if (DEBUG) {
322
System.out.println("SpNegoContext.initSecContext: " +
323
"sending token of type = " +
324
SpNegoToken.getTokenName(initToken.getType()));
325
}
326
// get the encoded token
327
retVal = initToken.getEncoded();
328
329
} else if (state == STATE_IN_PROCESS) {
330
331
errorCode = GSSException.FAILURE;
332
if (is == null) {
333
throw new GSSException(errorCode, -1,
334
"No token received from peer!");
335
}
336
337
errorCode = GSSException.DEFECTIVE_TOKEN;
338
byte[] server_token = new byte[is.available()];
339
SpNegoToken.readFully(is, server_token);
340
if (DEBUG) {
341
System.out.println("SpNegoContext.initSecContext: " +
342
"process received token = " +
343
SpNegoToken.getHexBytes(server_token));
344
}
345
346
// read the SPNEGO token
347
// token will be validated when parsing
348
NegTokenTarg targToken = new NegTokenTarg(server_token);
349
350
if (DEBUG) {
351
System.out.println("SpNegoContext.initSecContext: " +
352
"received token of type = " +
353
SpNegoToken.getTokenName(targToken.getType()));
354
}
355
356
// pull out mechanism
357
internal_mech = targToken.getSupportedMech();
358
if (internal_mech == null) {
359
// return wth failure
360
throw new GSSException(errorCode, -1,
361
"supported mechanism from server is null");
362
}
363
364
// get the negotiated result
365
SpNegoToken.NegoResult negoResult = null;
366
int result = targToken.getNegotiatedResult();
367
switch (result) {
368
case 0:
369
negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;
370
state = STATE_DONE;
371
break;
372
case 1:
373
negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;
374
state = STATE_IN_PROCESS;
375
break;
376
case 2:
377
negoResult = SpNegoToken.NegoResult.REJECT;
378
state = STATE_DELETED;
379
break;
380
default:
381
state = STATE_DONE;
382
break;
383
}
384
385
errorCode = GSSException.BAD_MECH;
386
387
if (negoResult == SpNegoToken.NegoResult.REJECT) {
388
throw new GSSException(errorCode, -1,
389
internal_mech.toString());
390
}
391
392
errorCode = GSSException.DEFECTIVE_TOKEN;
393
394
if ((negoResult == SpNegoToken.NegoResult.ACCEPT_COMPLETE) ||
395
(negoResult == SpNegoToken.NegoResult.ACCEPT_INCOMPLETE)) {
396
397
// pull out the mechanism token
398
byte[] accept_token = targToken.getResponseToken();
399
if (accept_token == null) {
400
if (!isMechContextEstablished()) {
401
// return with failure
402
throw new GSSException(errorCode, -1,
403
"mechanism token from server is null");
404
}
405
} else {
406
mechToken = GSS_initSecContext(accept_token);
407
}
408
// verify MIC
409
if (!GSSUtil.useMSInterop()) {
410
byte[] micToken = targToken.getMechListMIC();
411
if (!verifyMechListMIC(DER_mechTypes, micToken)) {
412
throw new GSSException(errorCode, -1,
413
"verification of MIC on MechList Failed!");
414
}
415
}
416
if (isMechContextEstablished()) {
417
state = STATE_DONE;
418
retVal = mechToken;
419
if (DEBUG) {
420
System.out.println("SPNEGO Negotiated Mechanism = "
421
+ internal_mech + " " +
422
GSSUtil.getMechStr(internal_mech));
423
}
424
} else {
425
// generate SPNEGO token
426
initToken = new NegTokenInit(null, null,
427
mechToken, null);
428
if (DEBUG) {
429
System.out.println("SpNegoContext.initSecContext:" +
430
" continue sending token of type = " +
431
SpNegoToken.getTokenName(initToken.getType()));
432
}
433
// get the encoded token
434
retVal = initToken.getEncoded();
435
}
436
}
437
438
} else {
439
// XXX Use logging API
440
if (DEBUG) {
441
System.out.println(state);
442
}
443
}
444
if (DEBUG) {
445
if (retVal != null) {
446
System.out.println("SNegoContext.initSecContext: " +
447
"sending token = " + SpNegoToken.getHexBytes(retVal));
448
}
449
}
450
} catch (GSSException e) {
451
GSSException gssException =
452
new GSSException(errorCode, -1, e.getMessage());
453
gssException.initCause(e);
454
throw gssException;
455
} catch (IOException e) {
456
GSSException gssException =
457
new GSSException(GSSException.FAILURE, -1, e.getMessage());
458
gssException.initCause(e);
459
throw gssException;
460
}
461
462
return retVal;
463
}
464
465
466
/**
467
* Acceptor's context establishment call. This method may be
468
* required to be called several times. A CONTINUE_NEEDED return
469
* call indicates that more calls are needed after the next token
470
* is received from the peer.
471
*
472
* @param is contains the token received from the peer.
473
* @return any token required to be sent to the peer
474
* It is responsibility of the caller to send the token
475
* to its peer for processing.
476
* @exception GSSException
477
*/
478
@Deprecated(since="11")
479
public final byte[] acceptSecContext(InputStream is, int mechTokenSize)
480
throws GSSException {
481
482
byte[] retVal = null;
483
SpNegoToken.NegoResult negoResult;
484
boolean valid = true;
485
486
if (DEBUG) {
487
System.out.println("Entered SpNegoContext.acceptSecContext with " +
488
"state=" + printState(state));
489
}
490
491
if (isInitiator()) {
492
throw new GSSException(GSSException.FAILURE, -1,
493
"acceptSecContext on an initiator " +
494
"GSSContext");
495
}
496
try {
497
if (state == STATE_NEW) {
498
state = STATE_IN_PROCESS;
499
500
// read data
501
byte[] token = new byte[is.available()];
502
SpNegoToken.readFully(is, token);
503
if (DEBUG) {
504
System.out.println("SpNegoContext.acceptSecContext: " +
505
"receiving token = " +
506
SpNegoToken.getHexBytes(token));
507
}
508
509
// read the SPNEGO token
510
// token will be validated when parsing
511
NegTokenInit initToken = new NegTokenInit(token);
512
513
if (DEBUG) {
514
System.out.println("SpNegoContext.acceptSecContext: " +
515
"received token of type = " +
516
SpNegoToken.getTokenName(initToken.getType()));
517
}
518
519
Oid[] mechList = initToken.getMechTypeList();
520
DER_mechTypes = initToken.getMechTypes();
521
if (DER_mechTypes == null) {
522
valid = false;
523
}
524
525
/*
526
* Select the best match between the list of mechs
527
* that the initiator requested and the list that
528
* the acceptor will support.
529
*/
530
Oid[] supported_mechSet = getAvailableMechs();
531
Oid mech_wanted =
532
negotiate_mech_type(supported_mechSet, mechList);
533
if (mech_wanted == null) {
534
valid = false;
535
}
536
// save the desired mechanism
537
internal_mech = mech_wanted;
538
539
// get the token for mechanism
540
byte[] accept_token;
541
542
if (mechList[0].equals(mech_wanted) ||
543
(GSSUtil.isKerberosMech(mechList[0]) &&
544
GSSUtil.isKerberosMech(mech_wanted))) {
545
// get the mechanism token
546
if (DEBUG && !mech_wanted.equals(mechList[0])) {
547
System.out.println("SpNegoContext.acceptSecContext: " +
548
"negotiated mech adjusted to " + mechList[0]);
549
}
550
byte[] mechToken = initToken.getMechToken();
551
if (mechToken == null) {
552
throw new GSSException(GSSException.FAILURE, -1,
553
"mechToken is missing");
554
}
555
accept_token = GSS_acceptSecContext(mechToken);
556
mech_wanted = mechList[0];
557
} else {
558
accept_token = null;
559
}
560
561
// verify MIC
562
if (!GSSUtil.useMSInterop() && valid) {
563
valid = verifyMechListMIC(DER_mechTypes,
564
initToken.getMechListMIC());
565
}
566
567
// determine negotiated result status
568
if (valid) {
569
if (isMechContextEstablished()) {
570
negoResult = SpNegoToken.NegoResult.ACCEPT_COMPLETE;
571
state = STATE_DONE;
572
// now set the context flags for acceptor
573
setContextFlags();
574
// print the negotiated mech info
575
if (DEBUG) {
576
System.out.println("SPNEGO Negotiated Mechanism = "
577
+ internal_mech + " " +
578
GSSUtil.getMechStr(internal_mech));
579
}
580
} else {
581
negoResult = SpNegoToken.NegoResult.ACCEPT_INCOMPLETE;
582
state = STATE_IN_PROCESS;
583
}
584
} else {
585
negoResult = SpNegoToken.NegoResult.REJECT;
586
state = STATE_DELETED;
587
throw new GSSException(GSSException.FAILURE);
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_DELETED;
647
throw new GSSException(GSSException.FAILURE);
648
}
649
650
// generate SPNEGO token
651
NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),
652
null, accept_token, null);
653
if (DEBUG) {
654
System.out.println("SpNegoContext.acceptSecContext: " +
655
"sending token of type = " +
656
SpNegoToken.getTokenName(targToken.getType()));
657
}
658
// get the encoded token
659
retVal = targToken.getEncoded();
660
661
} else {
662
// XXX Use logging API
663
if (DEBUG) {
664
System.out.println("AcceptSecContext: state = " + state);
665
}
666
}
667
if (DEBUG) {
668
System.out.println("SpNegoContext.acceptSecContext: " +
669
"sending token = " + SpNegoToken.getHexBytes(retVal));
670
}
671
} catch (IOException e) {
672
GSSException gssException =
673
new GSSException(GSSException.FAILURE, -1, e.getMessage());
674
gssException.initCause(e);
675
throw gssException;
676
}
677
678
if (state == STATE_DONE) {
679
// now set the context flags for acceptor
680
setContextFlags();
681
}
682
return retVal;
683
}
684
685
/**
686
* obtain the available mechanisms
687
*/
688
private Oid[] getAvailableMechs() {
689
if (myCred != null) {
690
Oid[] mechs = new Oid[1];
691
mechs[0] = myCred.getInternalMech();
692
return mechs;
693
} else {
694
return factory.availableMechs;
695
}
696
}
697
698
/**
699
* get ther DER encoded MechList
700
*/
701
private byte[] getEncodedMechs(Oid[] mechSet)
702
throws IOException, GSSException {
703
704
DerOutputStream mech = new DerOutputStream();
705
for (int i = 0; i < mechSet.length; i++) {
706
byte[] mechType = mechSet[i].getDER();
707
mech.write(mechType);
708
}
709
// insert in SEQUENCE
710
DerOutputStream mechTypeList = new DerOutputStream();
711
mechTypeList.write(DerValue.tag_Sequence, mech);
712
byte[] encoded = mechTypeList.toByteArray();
713
return encoded;
714
}
715
716
/**
717
* get the context flags
718
*/
719
private BitArray getContextFlags() {
720
BitArray out = new BitArray(7);
721
722
if (getCredDelegState()) out.set(0, true);
723
if (getMutualAuthState()) out.set(1, true);
724
if (getReplayDetState()) out.set(2, true);
725
if (getSequenceDetState()) out.set(3, true);
726
if (getConfState()) out.set(5, true);
727
if (getIntegState()) out.set(6, true);
728
729
return out;
730
}
731
732
// Only called on acceptor side. On the initiator side, most flags
733
// are already set at request. For those that might get chanegd,
734
// state from mech below is used.
735
private void setContextFlags() {
736
737
if (mechContext != null) {
738
// default for cred delegation is false
739
if (mechContext.getCredDelegState()) {
740
credDelegState = true;
741
}
742
// default for the following are true
743
if (!mechContext.getMutualAuthState()) {
744
mutualAuthState = false;
745
}
746
if (!mechContext.getReplayDetState()) {
747
replayDetState = false;
748
}
749
if (!mechContext.getSequenceDetState()) {
750
sequenceDetState = false;
751
}
752
if (!mechContext.getIntegState()) {
753
integState = false;
754
}
755
if (!mechContext.getConfState()) {
756
confState = false;
757
}
758
}
759
}
760
761
/**
762
* generate MIC on mechList. Not used at the moment.
763
*/
764
/*private byte[] generateMechListMIC(byte[] mechTypes)
765
throws GSSException {
766
767
// sanity check the required input
768
if (mechTypes == null) {
769
if (DEBUG) {
770
System.out.println("SpNegoContext: no MIC token included");
771
}
772
return null;
773
}
774
775
// check if mechanism supports integrity
776
if (!mechContext.getIntegState()) {
777
if (DEBUG) {
778
System.out.println("SpNegoContext: no MIC token included" +
779
" - mechanism does not support integrity");
780
}
781
return null;
782
}
783
784
// compute MIC on DER encoded mechanism list
785
byte[] mic = null;
786
try {
787
MessageProp prop = new MessageProp(0, true);
788
mic = getMIC(mechTypes, 0, mechTypes.length, prop);
789
if (DEBUG) {
790
System.out.println("SpNegoContext: getMIC = " +
791
SpNegoToken.getHexBytes(mic));
792
}
793
} catch (GSSException e) {
794
mic = null;
795
if (DEBUG) {
796
System.out.println("SpNegoContext: no MIC token included" +
797
" - getMIC failed : " + e.getMessage());
798
}
799
}
800
return mic;
801
}*/
802
803
/**
804
* verify MIC on MechList
805
*/
806
private boolean verifyMechListMIC(byte[] mechTypes, byte[] token)
807
throws GSSException {
808
809
// sanity check the input
810
if (token == null) {
811
if (DEBUG) {
812
System.out.println("SpNegoContext: no MIC token validation");
813
}
814
return true;
815
}
816
817
// check if mechanism supports integrity
818
if (!mechContext.getIntegState()) {
819
if (DEBUG) {
820
System.out.println("SpNegoContext: no MIC token validation" +
821
" - mechanism does not support integrity");
822
}
823
return true;
824
}
825
826
// now verify the token
827
boolean valid = false;
828
try {
829
MessageProp prop = new MessageProp(0, true);
830
verifyMIC(token, 0, token.length, mechTypes,
831
0, mechTypes.length, prop);
832
valid = true;
833
} catch (GSSException e) {
834
valid = false;
835
if (DEBUG) {
836
System.out.println("SpNegoContext: MIC validation failed! " +
837
e.getMessage());
838
}
839
}
840
return valid;
841
}
842
843
/**
844
* call gss_init_sec_context for the corresponding underlying mechanism
845
*/
846
private byte[] GSS_initSecContext(byte[] token) throws GSSException {
847
byte[] tok = null;
848
849
if (mechContext == null) {
850
// initialize mech context
851
GSSName serverName =
852
factory.manager.createName(peerName.toString(),
853
peerName.getStringNameType(), internal_mech);
854
GSSCredential cred = null;
855
if (myCred != null) {
856
// create context with provided credential
857
cred = new GSSCredentialImpl(factory.manager,
858
myCred.getInternalCred());
859
}
860
mechContext =
861
factory.manager.createContext(serverName,
862
internal_mech, cred, GSSContext.DEFAULT_LIFETIME);
863
mechContext.requestConf(confState);
864
mechContext.requestInteg(integState);
865
mechContext.requestCredDeleg(credDelegState);
866
mechContext.requestMutualAuth(mutualAuthState);
867
mechContext.requestReplayDet(replayDetState);
868
mechContext.requestSequenceDet(sequenceDetState);
869
if (mechContext instanceof GSSContextImpl) {
870
((GSSContextImpl)mechContext).requestDelegPolicy(
871
delegPolicyState);
872
}
873
}
874
875
// pass token
876
if (token != null) {
877
tok = token;
878
} else {
879
tok = new byte[0];
880
}
881
882
// pass token to mechanism initSecContext
883
byte[] init_token = mechContext.initSecContext(tok, 0, tok.length);
884
885
return init_token;
886
}
887
888
/**
889
* call gss_accept_sec_context for the corresponding underlying mechanism
890
*/
891
private byte[] GSS_acceptSecContext(byte[] token) throws GSSException {
892
893
if (mechContext == null) {
894
// initialize mech context
895
GSSCredential cred = null;
896
if (myCred != null) {
897
// create context with provided credential
898
cred = new GSSCredentialImpl(factory.manager,
899
myCred.getInternalCred());
900
}
901
mechContext = 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
@Deprecated(since="11")
1135
public final void wrap(InputStream is, OutputStream os,
1136
MessageProp msgProp) throws GSSException {
1137
if (mechContext != null) {
1138
mechContext.wrap(is, os, msgProp);
1139
} else {
1140
throw new GSSException(GSSException.NO_CONTEXT, -1,
1141
"Wrap called in invalid state!");
1142
}
1143
}
1144
1145
public final byte[] unwrap(byte inBuf[], int offset, int len,
1146
MessageProp msgProp)
1147
throws GSSException {
1148
if (mechContext != null) {
1149
return mechContext.unwrap(inBuf, offset, len, msgProp);
1150
} else {
1151
throw new GSSException(GSSException.NO_CONTEXT, -1,
1152
"UnWrap called in invalid state!");
1153
}
1154
}
1155
1156
@Deprecated(since="11")
1157
public final void unwrap(InputStream is, OutputStream os,
1158
MessageProp msgProp) throws GSSException {
1159
if (mechContext != null) {
1160
mechContext.unwrap(is, os, msgProp);
1161
} else {
1162
throw new GSSException(GSSException.NO_CONTEXT, -1,
1163
"UnWrap called in invalid state!");
1164
}
1165
}
1166
1167
public final byte[] getMIC(byte []inMsg, int offset, int len,
1168
MessageProp msgProp)
1169
throws GSSException {
1170
if (mechContext != null) {
1171
return mechContext.getMIC(inMsg, offset, len, msgProp);
1172
} else {
1173
throw new GSSException(GSSException.NO_CONTEXT, -1,
1174
"getMIC called in invalid state!");
1175
}
1176
}
1177
1178
@Deprecated(since="11")
1179
public final void getMIC(InputStream is, OutputStream os,
1180
MessageProp msgProp) throws GSSException {
1181
if (mechContext != null) {
1182
mechContext.getMIC(is, os, msgProp);
1183
} else {
1184
throw new GSSException(GSSException.NO_CONTEXT, -1,
1185
"getMIC called in invalid state!");
1186
}
1187
}
1188
1189
public final void verifyMIC(byte []inTok, int tokOffset, int tokLen,
1190
byte[] inMsg, int msgOffset, int msgLen,
1191
MessageProp msgProp)
1192
throws GSSException {
1193
if (mechContext != null) {
1194
mechContext.verifyMIC(inTok, tokOffset, tokLen, inMsg, msgOffset,
1195
msgLen, msgProp);
1196
} else {
1197
throw new GSSException(GSSException.NO_CONTEXT, -1,
1198
"verifyMIC called in invalid state!");
1199
}
1200
}
1201
1202
@Deprecated(since="11")
1203
public final void verifyMIC(InputStream is, InputStream msgStr,
1204
MessageProp msgProp) throws GSSException {
1205
if (mechContext != null) {
1206
mechContext.verifyMIC(is, msgStr, msgProp);
1207
} else {
1208
throw new GSSException(GSSException.NO_CONTEXT, -1,
1209
"verifyMIC called in invalid state!");
1210
}
1211
}
1212
1213
private static String printState(int state) {
1214
switch (state) {
1215
case STATE_NEW:
1216
return ("STATE_NEW");
1217
case STATE_IN_PROCESS:
1218
return ("STATE_IN_PROCESS");
1219
case STATE_DONE:
1220
return ("STATE_DONE");
1221
case STATE_DELETED:
1222
return ("STATE_DELETED");
1223
default:
1224
return ("Unknown state " + state);
1225
}
1226
}
1227
1228
/**
1229
* Retrieve attribute of the context for {@code type}.
1230
*/
1231
public Object inquireSecContext(String type)
1232
throws GSSException {
1233
if (mechContext == null) {
1234
throw new GSSException(GSSException.NO_CONTEXT, -1,
1235
"Underlying mech not established.");
1236
}
1237
if (mechContext instanceof GSSContextImpl) {
1238
return ((GSSContextImpl)mechContext).inquireSecContext(type);
1239
} else {
1240
throw new GSSException(GSSException.BAD_MECH, -1,
1241
"inquireSecContext not supported by underlying mech.");
1242
}
1243
}
1244
}
1245
1246
1247