Showing the changes to java/pkg/sun/security/jgss/wrapper/NativeGSSContext.java (1 of 18352 files). Show all
Unified · Split
| @@ -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 | |||
| 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 com.sun.security.jgss.InquireType; | ||
| 40 | import 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 | */ | ||
| 49 | class 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 | } | ||