History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/jgss/wrapper/NativeGSSContext.java (1 of 18352 files). Show all

Unified · Split

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