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/wrapper/NativeGSSContext.java
41161 views
1
/*
2
* Copyright (c) 2005, 2021, 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.wrapper;
27
28
import org.ietf.jgss.*;
29
import java.security.Provider;
30
import sun.security.jgss.GSSHeader;
31
import sun.security.jgss.GSSUtil;
32
import sun.security.jgss.GSSExceptionImpl;
33
import sun.security.jgss.spi.*;
34
import sun.security.util.DerValue;
35
import sun.security.util.ObjectIdentifier;
36
import sun.security.jgss.spnego.NegTokenInit;
37
import sun.security.jgss.spnego.NegTokenTarg;
38
import javax.security.auth.kerberos.DelegationPermission;
39
import java.io.*;
40
41
42
/**
43
* This class is essentially a wrapper class for the gss_ctx_id_t
44
* structure of the native GSS library.
45
* @author Valerie Peng
46
* @since 1.6
47
*/
48
class NativeGSSContext implements GSSContextSpi {
49
50
private static final int GSS_C_DELEG_FLAG = 1;
51
private static final int GSS_C_MUTUAL_FLAG = 2;
52
private static final int GSS_C_REPLAY_FLAG = 4;
53
private static final int GSS_C_SEQUENCE_FLAG = 8;
54
private static final int GSS_C_CONF_FLAG = 16;
55
private static final int GSS_C_INTEG_FLAG = 32;
56
private static final int GSS_C_ANON_FLAG = 64;
57
private static final int GSS_C_PROT_READY_FLAG = 128;
58
private static final int GSS_C_TRANS_FLAG = 256;
59
60
private static final int NUM_OF_INQUIRE_VALUES = 6;
61
62
// Warning: The following 9 fields are used by NativeUtil.c
63
private long pContext = 0; // Pointer to the gss_ctx_id_t structure
64
private GSSNameElement srcName;
65
private GSSNameElement targetName;
66
private boolean isInitiator;
67
private boolean isEstablished;
68
private GSSCredElement delegatedCred;
69
private int flags;
70
private int lifetime = GSSCredential.DEFAULT_LIFETIME;
71
private Oid actualMech; // Assigned during context establishment
72
73
private GSSCredElement cred;
74
private GSSCredElement disposeCred;
75
76
private ChannelBinding cb;
77
private GSSCredElement disposeDelegatedCred;
78
private final GSSLibStub cStub;
79
80
private boolean skipDelegPermCheck;
81
private boolean skipServicePermCheck;
82
83
// Retrieve the (preferred) mech out of SPNEGO tokens, i.e.
84
// NegTokenInit & NegTokenTarg
85
private static Oid getMechFromSpNegoToken(byte[] token,
86
boolean isInitiator)
87
throws GSSException {
88
Oid mech = null;
89
if (isInitiator) {
90
GSSHeader header = null;
91
try {
92
header = new GSSHeader(new ByteArrayInputStream(token));
93
} catch (IOException ioe) {
94
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
95
}
96
int negTokenLen = header.getMechTokenLength();
97
byte[] negToken = new byte[negTokenLen];
98
System.arraycopy(token, token.length-negTokenLen,
99
negToken, 0, negToken.length);
100
101
NegTokenInit ntok = new NegTokenInit(negToken);
102
if (ntok.getMechToken() != null) {
103
Oid[] mechList = ntok.getMechTypeList();
104
mech = mechList[0];
105
}
106
} else {
107
NegTokenTarg ntok = new NegTokenTarg(token);
108
mech = ntok.getSupportedMech();
109
}
110
return mech;
111
}
112
113
// Perform the Service permission check
114
@SuppressWarnings("removal")
115
private void doServicePermCheck() throws GSSException {
116
if (System.getSecurityManager() != null) {
117
String action = (isInitiator? "initiate" : "accept");
118
// Need to check Service permission for accessing
119
// initiator cred for SPNEGO during context establishment
120
if (GSSUtil.isSpNegoMech(cStub.getMech()) && isInitiator
121
&& !isEstablished) {
122
if (srcName == null) {
123
// Check by creating default initiator KRB5 cred
124
GSSCredElement tempCred =
125
new GSSCredElement(null, lifetime,
126
GSSCredential.INITIATE_ONLY,
127
GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID));
128
tempCred.dispose();
129
} else {
130
String tgsName = Krb5Util.getTGSName(srcName);
131
Krb5Util.checkServicePermission(tgsName, action);
132
}
133
}
134
String targetStr = targetName.getKrbName();
135
Krb5Util.checkServicePermission(targetStr, action);
136
skipServicePermCheck = true;
137
}
138
}
139
140
// Perform the Delegation permission check
141
private void doDelegPermCheck() throws GSSException {
142
@SuppressWarnings("removal")
143
SecurityManager sm = System.getSecurityManager();
144
if (sm != null) {
145
String targetStr = targetName.getKrbName();
146
String tgsStr = Krb5Util.getTGSName(targetName);
147
StringBuilder sb = new StringBuilder("\"");
148
sb.append(targetStr).append("\" \"");
149
sb.append(tgsStr).append('\"');
150
String krbPrincPair = sb.toString();
151
SunNativeProvider.debug("Checking DelegationPermission (" +
152
krbPrincPair + ")");
153
DelegationPermission perm =
154
new DelegationPermission(krbPrincPair);
155
sm.checkPermission(perm);
156
skipDelegPermCheck = true;
157
}
158
}
159
160
private byte[] retrieveToken(InputStream is, int mechTokenLen)
161
throws GSSException {
162
try {
163
byte[] result = null;
164
if (mechTokenLen != -1) {
165
// Need to add back the GSS header for a complete GSS token
166
SunNativeProvider.debug("Precomputed mechToken length: " +
167
mechTokenLen);
168
GSSHeader gssHeader = new GSSHeader
169
(ObjectIdentifier.of(cStub.getMech().toString()),
170
mechTokenLen);
171
ByteArrayOutputStream baos = new ByteArrayOutputStream(600);
172
173
byte[] mechToken = new byte[mechTokenLen];
174
int len = is.read(mechToken);
175
assert(mechTokenLen == len);
176
gssHeader.encode(baos);
177
baos.write(mechToken);
178
result = baos.toByteArray();
179
} else {
180
// Must be unparsed GSS token or SPNEGO's NegTokenTarg token
181
assert(mechTokenLen == -1);
182
DerValue dv = new DerValue(is);
183
result = dv.toByteArray();
184
}
185
SunNativeProvider.debug("Complete Token length: " +
186
result.length);
187
return result;
188
} catch (IOException ioe) {
189
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
190
}
191
}
192
193
// Constructor for context initiator
194
NativeGSSContext(GSSNameElement peer, GSSCredElement myCred,
195
int time, GSSLibStub stub) throws GSSException {
196
if (peer == null) {
197
throw new GSSException(GSSException.FAILURE, 1, "null peer");
198
}
199
cStub = stub;
200
cred = myCred;
201
disposeCred = null;
202
targetName = peer;
203
isInitiator = true;
204
lifetime = time;
205
206
if (GSSUtil.isKerberosMech(cStub.getMech())) {
207
doServicePermCheck();
208
if (cred == null) {
209
disposeCred = cred =
210
new GSSCredElement(null, lifetime,
211
GSSCredential.INITIATE_ONLY, cStub);
212
}
213
srcName = cred.getName();
214
}
215
}
216
217
// Constructor for context acceptor
218
NativeGSSContext(GSSCredElement myCred, GSSLibStub stub)
219
throws GSSException {
220
cStub = stub;
221
cred = myCred;
222
disposeCred = null;
223
224
if (cred != null) targetName = cred.getName();
225
226
isInitiator = false;
227
// Defer Service permission check for default acceptor cred
228
// to acceptSecContext()
229
if (GSSUtil.isKerberosMech(cStub.getMech()) && targetName != null) {
230
doServicePermCheck();
231
}
232
233
// srcName and potentially targetName (when myCred is null)
234
// will be set in GSSLibStub.acceptContext(...)
235
}
236
237
// Constructor for imported context
238
// Warning: called by NativeUtil.c
239
NativeGSSContext(long pCtxt, GSSLibStub stub) throws GSSException {
240
assert(pContext != 0);
241
pContext = pCtxt;
242
cStub = stub;
243
244
// Set everything except cred, cb, delegatedCred
245
long[] info = cStub.inquireContext(pContext);
246
if (info.length != NUM_OF_INQUIRE_VALUES) {
247
throw new RuntimeException("Bug w/ GSSLibStub.inquireContext()");
248
}
249
srcName = new GSSNameElement(info[0], cStub);
250
targetName = new GSSNameElement(info[1], cStub);
251
isInitiator = (info[2] != 0);
252
isEstablished = (info[3] != 0);
253
flags = (int) info[4];
254
lifetime = (int) info[5];
255
256
// Do Service Permission check when importing SPNEGO context
257
// just to be safe
258
Oid mech = cStub.getMech();
259
if (GSSUtil.isSpNegoMech(mech) || GSSUtil.isKerberosMech(mech)) {
260
doServicePermCheck();
261
}
262
}
263
264
public Provider getProvider() {
265
return SunNativeProvider.INSTANCE;
266
}
267
268
public byte[] initSecContext(InputStream is, int mechTokenLen)
269
throws GSSException {
270
byte[] outToken = null;
271
if ((!isEstablished) && (isInitiator)) {
272
byte[] inToken = null;
273
// Ignore the specified input stream on the first call
274
if (pContext != 0) {
275
inToken = retrieveToken(is, mechTokenLen);
276
SunNativeProvider.debug("initSecContext=> inToken len=" +
277
inToken.length);
278
}
279
280
if (!getCredDelegState()) skipDelegPermCheck = true;
281
282
if (GSSUtil.isKerberosMech(cStub.getMech()) && !skipDelegPermCheck) {
283
doDelegPermCheck();
284
}
285
286
long pCred = (cred == null? 0 : cred.pCred);
287
outToken = cStub.initContext(pCred, targetName.pName,
288
cb, inToken, this);
289
SunNativeProvider.debug("initSecContext=> outToken len=" +
290
(outToken == null ? 0 : outToken.length));
291
292
// Only inspect the token when the permission check
293
// has not been performed
294
if (GSSUtil.isSpNegoMech(cStub.getMech()) && outToken != null) {
295
// WORKAROUND for SEAM bug#6287358
296
actualMech = getMechFromSpNegoToken(outToken, true);
297
298
if (GSSUtil.isKerberosMech(actualMech)) {
299
if (!skipServicePermCheck) doServicePermCheck();
300
if (!skipDelegPermCheck) doDelegPermCheck();
301
}
302
}
303
304
if (isEstablished) {
305
if (srcName == null) {
306
srcName = new GSSNameElement
307
(cStub.getContextName(pContext, true), cStub);
308
}
309
if (cred == null) {
310
disposeCred = cred =
311
new GSSCredElement(srcName, lifetime,
312
GSSCredential.INITIATE_ONLY, cStub);
313
}
314
}
315
}
316
return outToken;
317
}
318
319
public byte[] acceptSecContext(InputStream is, int mechTokenLen)
320
throws GSSException {
321
byte[] outToken = null;
322
if ((!isEstablished) && (!isInitiator)) {
323
byte[] inToken = retrieveToken(is, mechTokenLen);
324
SunNativeProvider.debug("acceptSecContext=> inToken len=" +
325
inToken.length);
326
long pCred = (cred == null? 0 : cred.pCred);
327
outToken = cStub.acceptContext(pCred, cb, inToken, this);
328
disposeDelegatedCred = delegatedCred;
329
SunNativeProvider.debug("acceptSecContext=> outToken len=" +
330
(outToken == null? 0 : outToken.length));
331
332
if (targetName == null) {
333
targetName = new GSSNameElement
334
(cStub.getContextName(pContext, false), cStub);
335
// Replace the current default acceptor cred now that
336
// the context acceptor name is available
337
if (disposeCred != null) {
338
disposeCred.dispose();
339
}
340
disposeCred = cred =
341
new GSSCredElement(targetName, lifetime,
342
GSSCredential.ACCEPT_ONLY, cStub);
343
}
344
345
// Only inspect token when the permission check has not
346
// been performed
347
if (GSSUtil.isSpNegoMech(cStub.getMech()) &&
348
(outToken != null) && !skipServicePermCheck) {
349
if (GSSUtil.isKerberosMech(getMechFromSpNegoToken
350
(outToken, false))) {
351
doServicePermCheck();
352
}
353
}
354
}
355
return outToken;
356
}
357
358
public boolean isEstablished() {
359
return isEstablished;
360
}
361
362
public void dispose() throws GSSException {
363
if (disposeCred != null) {
364
disposeCred.dispose();
365
}
366
if (disposeDelegatedCred != null) {
367
disposeDelegatedCred.dispose();
368
}
369
disposeDelegatedCred = disposeCred = cred = null;
370
srcName = null;
371
targetName = null;
372
delegatedCred = null;
373
if (pContext != 0) {
374
pContext = cStub.deleteContext(pContext);
375
pContext = 0;
376
}
377
}
378
379
public int getWrapSizeLimit(int qop, boolean confReq,
380
int maxTokenSize)
381
throws GSSException {
382
return cStub.wrapSizeLimit(pContext, (confReq? 1:0), qop,
383
maxTokenSize);
384
}
385
386
public byte[] wrap(byte[] inBuf, int offset, int len,
387
MessageProp msgProp) throws GSSException {
388
byte[] data = inBuf;
389
if ((offset != 0) || (len != inBuf.length)) {
390
data = new byte[len];
391
System.arraycopy(inBuf, offset, data, 0, len);
392
}
393
return cStub.wrap(pContext, data, msgProp);
394
}
395
public void wrap(byte[] inBuf, int offset, int len,
396
OutputStream os, MessageProp msgProp)
397
throws GSSException {
398
try {
399
byte[] result = wrap(inBuf, offset, len, msgProp);
400
os.write(result);
401
} catch (IOException ioe) {
402
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
403
}
404
}
405
public int wrap(byte[] inBuf, int inOffset, int len, byte[] outBuf,
406
int outOffset, MessageProp msgProp)
407
throws GSSException {
408
byte[] result = wrap(inBuf, inOffset, len, msgProp);
409
System.arraycopy(result, 0, outBuf, outOffset, result.length);
410
return result.length;
411
}
412
public void wrap(InputStream inStream, OutputStream outStream,
413
MessageProp msgProp) throws GSSException {
414
try {
415
byte[] data = new byte[inStream.available()];
416
int length = inStream.read(data);
417
byte[] token = wrap(data, 0, length, msgProp);
418
outStream.write(token);
419
} catch (IOException ioe) {
420
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
421
}
422
}
423
424
public byte[] unwrap(byte[] inBuf, int offset, int len,
425
MessageProp msgProp)
426
throws GSSException {
427
if ((offset != 0) || (len != inBuf.length)) {
428
byte[] temp = new byte[len];
429
System.arraycopy(inBuf, offset, temp, 0, len);
430
return cStub.unwrap(pContext, temp, msgProp);
431
} else {
432
return cStub.unwrap(pContext, inBuf, msgProp);
433
}
434
}
435
public int unwrap(byte[] inBuf, int inOffset, int len,
436
byte[] outBuf, int outOffset,
437
MessageProp msgProp) throws GSSException {
438
byte[] result = null;
439
if ((inOffset != 0) || (len != inBuf.length)) {
440
byte[] temp = new byte[len];
441
System.arraycopy(inBuf, inOffset, temp, 0, len);
442
result = cStub.unwrap(pContext, temp, msgProp);
443
} else {
444
result = cStub.unwrap(pContext, inBuf, msgProp);
445
}
446
System.arraycopy(result, 0, outBuf, outOffset, result.length);
447
return result.length;
448
}
449
public void unwrap(InputStream inStream, OutputStream outStream,
450
MessageProp msgProp) throws GSSException {
451
try {
452
byte[] wrapped = new byte[inStream.available()];
453
int wLength = inStream.read(wrapped);
454
byte[] data = unwrap(wrapped, 0, wLength, msgProp);
455
outStream.write(data);
456
outStream.flush();
457
} catch (IOException ioe) {
458
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
459
}
460
}
461
462
public int unwrap(InputStream inStream,
463
byte[] outBuf, int outOffset,
464
MessageProp msgProp) throws GSSException {
465
byte[] wrapped = null;
466
int wLength = 0;
467
try {
468
wrapped = new byte[inStream.available()];
469
wLength = inStream.read(wrapped);
470
byte[] result = unwrap(wrapped, 0, wLength, msgProp);
471
} catch (IOException ioe) {
472
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
473
}
474
byte[] result = unwrap(wrapped, 0, wLength, msgProp);
475
System.arraycopy(result, 0, outBuf, outOffset, result.length);
476
return result.length;
477
}
478
479
public byte[] getMIC(byte[] in, int offset, int len,
480
MessageProp msgProp) throws GSSException {
481
int qop = (msgProp == null? 0:msgProp.getQOP());
482
byte[] inMsg = in;
483
if ((offset != 0) || (len != in.length)) {
484
inMsg = new byte[len];
485
System.arraycopy(in, offset, inMsg, 0, len);
486
}
487
return cStub.getMic(pContext, qop, inMsg);
488
}
489
490
public void getMIC(InputStream inStream, OutputStream outStream,
491
MessageProp msgProp) throws GSSException {
492
try {
493
int length = 0;
494
byte[] msg = new byte[inStream.available()];
495
length = inStream.read(msg);
496
497
byte[] msgToken = getMIC(msg, 0, length, msgProp);
498
if ((msgToken != null) && msgToken.length != 0) {
499
outStream.write(msgToken);
500
}
501
} catch (IOException ioe) {
502
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
503
}
504
}
505
506
public void verifyMIC(byte[] inToken, int tOffset, int tLen,
507
byte[] inMsg, int mOffset, int mLen,
508
MessageProp msgProp) throws GSSException {
509
byte[] token = inToken;
510
byte[] msg = inMsg;
511
if ((tOffset != 0) || (tLen != inToken.length)) {
512
token = new byte[tLen];
513
System.arraycopy(inToken, tOffset, token, 0, tLen);
514
}
515
if ((mOffset != 0) || (mLen != inMsg.length)) {
516
msg = new byte[mLen];
517
System.arraycopy(inMsg, mOffset, msg, 0, mLen);
518
}
519
cStub.verifyMic(pContext, token, msg, msgProp);
520
}
521
522
public void verifyMIC(InputStream tokStream, InputStream msgStream,
523
MessageProp msgProp) throws GSSException {
524
try {
525
byte[] msg = new byte[msgStream.available()];
526
int mLength = msgStream.read(msg);
527
byte[] tok = new byte[tokStream.available()];
528
int tLength = tokStream.read(tok);
529
verifyMIC(tok, 0, tLength, msg, 0, mLength, msgProp);
530
} catch (IOException ioe) {
531
throw new GSSExceptionImpl(GSSException.FAILURE, ioe);
532
}
533
}
534
535
public byte[] export() throws GSSException {
536
byte[] result = cStub.exportContext(pContext);
537
pContext = 0;
538
return result;
539
}
540
541
private void changeFlags(int flagMask, boolean isEnable) {
542
if (isInitiator && pContext == 0) {
543
if (isEnable) {
544
flags |= flagMask;
545
} else {
546
flags &= ~flagMask;
547
}
548
}
549
}
550
public void requestMutualAuth(boolean state) throws GSSException {
551
changeFlags(GSS_C_MUTUAL_FLAG, state);
552
}
553
public void requestReplayDet(boolean state) throws GSSException {
554
changeFlags(GSS_C_REPLAY_FLAG, state);
555
}
556
public void requestSequenceDet(boolean state) throws GSSException {
557
changeFlags(GSS_C_SEQUENCE_FLAG, state);
558
}
559
public void requestCredDeleg(boolean state) throws GSSException {
560
changeFlags(GSS_C_DELEG_FLAG, state);
561
}
562
public void requestAnonymity(boolean state) throws GSSException {
563
changeFlags(GSS_C_ANON_FLAG, state);
564
}
565
public void requestConf(boolean state) throws GSSException {
566
changeFlags(GSS_C_CONF_FLAG, state);
567
}
568
public void requestInteg(boolean state) throws GSSException {
569
changeFlags(GSS_C_INTEG_FLAG, state);
570
}
571
public void requestDelegPolicy(boolean state) throws GSSException {
572
// Not supported, ignore
573
}
574
public void requestLifetime(int lifetime) throws GSSException {
575
if (isInitiator && pContext == 0) {
576
this.lifetime = lifetime;
577
}
578
}
579
public void setChannelBinding(ChannelBinding cb) throws GSSException {
580
if (pContext == 0) {
581
this.cb = cb;
582
}
583
}
584
585
private boolean checkFlags(int flagMask) {
586
return ((flags & flagMask) != 0);
587
}
588
public boolean getCredDelegState() {
589
return checkFlags(GSS_C_DELEG_FLAG);
590
}
591
public boolean getMutualAuthState() {
592
return checkFlags(GSS_C_MUTUAL_FLAG);
593
}
594
public boolean getReplayDetState() {
595
return checkFlags(GSS_C_REPLAY_FLAG);
596
}
597
public boolean getSequenceDetState() {
598
return checkFlags(GSS_C_SEQUENCE_FLAG);
599
}
600
public boolean getAnonymityState() {
601
return checkFlags(GSS_C_ANON_FLAG);
602
}
603
public boolean isTransferable() throws GSSException {
604
return checkFlags(GSS_C_TRANS_FLAG);
605
}
606
public boolean isProtReady() {
607
return checkFlags(GSS_C_PROT_READY_FLAG);
608
}
609
public boolean getConfState() {
610
return checkFlags(GSS_C_CONF_FLAG);
611
}
612
public boolean getIntegState() {
613
return checkFlags(GSS_C_INTEG_FLAG);
614
}
615
public boolean getDelegPolicyState() {
616
return false;
617
}
618
public int getLifetime() {
619
return cStub.getContextTime(pContext);
620
}
621
public GSSNameSpi getSrcName() throws GSSException {
622
return srcName;
623
}
624
public GSSNameSpi getTargName() throws GSSException {
625
return targetName;
626
}
627
public Oid getMech() throws GSSException {
628
if (isEstablished && actualMech != null) {
629
return actualMech;
630
} else {
631
return cStub.getMech();
632
}
633
}
634
public GSSCredentialSpi getDelegCred() throws GSSException {
635
disposeDelegatedCred = null;
636
return delegatedCred;
637
}
638
public boolean isInitiator() {
639
return isInitiator;
640
}
641
642
@SuppressWarnings("deprecation")
643
protected void finalize() throws Throwable {
644
dispose();
645
}
646
647
public Object inquireSecContext(String type)
648
throws GSSException {
649
throw new GSSException(GSSException.UNAVAILABLE, -1,
650
"Inquire type not supported.");
651
}
652
}
653
654