提交 84a9b032 编写于 作者: W weijun

6975866: api/org_ietf/jgss/GSSContext/index.html#wrapUnwrapIOTest started to fail since jdk7 b102

Reviewed-by: valeriep
上级 c86e1caa
/* /*
* Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -710,29 +710,21 @@ class CipherHelper { ...@@ -710,29 +710,21 @@ class CipherHelper {
* where HMAC is on {16-byte confounder | plaintext | 16-byte token_header} * where HMAC is on {16-byte confounder | plaintext | 16-byte token_header}
* HMAC is not encrypted; it is appended at the end. * HMAC is not encrypted; it is appended at the end.
*/ */
void encryptData(WrapToken_v2 token, byte[] confounder, byte[] tokenHeader, byte[] encryptData(WrapToken_v2 token, byte[] confounder, byte[] tokenHeader,
byte[] plaintext, int start, int len, int key_usage, OutputStream os) byte[] plaintext, int start, int len, int key_usage)
throws GSSException, IOException { throws GSSException {
byte[] ctext = null;
switch (etype) { switch (etype) {
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96: case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
ctext = aes128Encrypt(confounder, tokenHeader, return aes128Encrypt(confounder, tokenHeader,
plaintext, start, len, key_usage); plaintext, start, len, key_usage);
break; case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96: return aes256Encrypt(confounder, tokenHeader,
ctext = aes256Encrypt(confounder, tokenHeader, plaintext, start, len, key_usage);
plaintext, start, len, key_usage); default:
break; throw new GSSException(GSSException.FAILURE, -1,
default: "Unsupported etype: " + etype);
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported etype: " + etype);
} }
// Krb5Token.debug("EncryptedData = " +
// Krb5Token.getHexBytes(ctext) + "\n");
// Write to stream
os.write(ctext);
} }
void encryptData(WrapToken token, byte[] confounder, byte[] plaintext, void encryptData(WrapToken token, byte[] confounder, byte[] plaintext,
......
/* /*
* Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,12 +29,11 @@ import org.ietf.jgss.*; ...@@ -29,12 +29,11 @@ import org.ietf.jgss.*;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
/** /**
* This class represents the new format of GSS MIC tokens, as specified * This class represents the new format of GSS MIC tokens, as specified
* in draft-ietf-krb-wg-gssapi-cfx-07.txt * in RFC 4121
* *
* MIC tokens = { 16-byte token-header | HMAC } * MIC tokens = { 16-byte token-header | HMAC }
* where HMAC is on { plaintext | 16-byte token-header } * where HMAC is on { plaintext | 16-byte token-header }
...@@ -48,12 +47,11 @@ class MicToken_v2 extends MessageToken_v2 { ...@@ -48,12 +47,11 @@ class MicToken_v2 extends MessageToken_v2 {
byte[] tokenBytes, int tokenOffset, int tokenLen, byte[] tokenBytes, int tokenOffset, int tokenLen,
MessageProp prop) throws GSSException { MessageProp prop) throws GSSException {
super(Krb5Token.MIC_ID_v2, context, super(Krb5Token.MIC_ID_v2, context,
tokenBytes, tokenOffset, tokenLen, prop); tokenBytes, tokenOffset, tokenLen, prop);
} }
public MicToken_v2(Krb5Context context, public MicToken_v2(Krb5Context context, InputStream is, MessageProp prop)
InputStream is, MessageProp prop) throws GSSException {
throws GSSException {
super(Krb5Token.MIC_ID_v2, context, is, prop); super(Krb5Token.MIC_ID_v2, context, is, prop);
} }
...@@ -64,7 +62,6 @@ class MicToken_v2 extends MessageToken_v2 { ...@@ -64,7 +62,6 @@ class MicToken_v2 extends MessageToken_v2 {
} }
public void verify(InputStream data) throws GSSException { public void verify(InputStream data) throws GSSException {
byte[] dataBytes = null; byte[] dataBytes = null;
try { try {
dataBytes = new byte[data.available()]; dataBytes = new byte[data.available()];
...@@ -79,7 +76,7 @@ class MicToken_v2 extends MessageToken_v2 { ...@@ -79,7 +76,7 @@ class MicToken_v2 extends MessageToken_v2 {
public MicToken_v2(Krb5Context context, MessageProp prop, public MicToken_v2(Krb5Context context, MessageProp prop,
byte[] data, int pos, int len) byte[] data, int pos, int len)
throws GSSException { throws GSSException {
super(Krb5Token.MIC_ID_v2, context); super(Krb5Token.MIC_ID_v2, context);
// debug("Application data to MicToken verify is [" + // debug("Application data to MicToken verify is [" +
...@@ -89,7 +86,7 @@ class MicToken_v2 extends MessageToken_v2 { ...@@ -89,7 +86,7 @@ class MicToken_v2 extends MessageToken_v2 {
} }
public MicToken_v2(Krb5Context context, MessageProp prop, InputStream data) public MicToken_v2(Krb5Context context, MessageProp prop, InputStream data)
throws GSSException, IOException { throws GSSException, IOException {
super(Krb5Token.MIC_ID_v2, context); super(Krb5Token.MIC_ID_v2, context);
byte[] dataBytes = new byte[data.available()]; byte[] dataBytes = new byte[data.available()];
...@@ -101,22 +98,21 @@ class MicToken_v2 extends MessageToken_v2 { ...@@ -101,22 +98,21 @@ class MicToken_v2 extends MessageToken_v2 {
genSignAndSeqNumber(prop, dataBytes, 0, dataBytes.length); genSignAndSeqNumber(prop, dataBytes, 0, dataBytes.length);
} }
public int encode(byte[] outToken, int offset) public byte[] encode() throws IOException {
throws IOException, GSSException { // XXX Fine tune this initial size
ByteArrayOutputStream bos = new ByteArrayOutputStream(50);
encode(bos);
return bos.toByteArray();
}
// Token is small public int encode(byte[] outToken, int offset) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] token = encode();
super.encode(bos);
byte[] token = bos.toByteArray();
System.arraycopy(token, 0, outToken, offset, token.length); System.arraycopy(token, 0, outToken, offset, token.length);
return token.length; return token.length;
} }
public byte[] encode() throws IOException, GSSException { public void encode(OutputStream os) throws IOException {
encodeHeader(os);
// XXX Fine tune this initial size os.write(checksum);
ByteArrayOutputStream bos = new ByteArrayOutputStream(50);
encode(bos);
return bos.toByteArray();
} }
} }
/* /*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,14 +27,11 @@ package sun.security.jgss.krb5; ...@@ -27,14 +27,11 @@ package sun.security.jgss.krb5;
import org.ietf.jgss.*; import org.ietf.jgss.*;
import sun.security.jgss.*; import sun.security.jgss.*;
import java.security.GeneralSecurityException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import sun.security.krb5.Confounder; import sun.security.krb5.Confounder;
import sun.security.krb5.KrbException;
/** /**
* This class represents a token emitted by the GSSContext.wrap() * This class represents a token emitted by the GSSContext.wrap()
...@@ -336,24 +333,29 @@ class WrapToken extends MessageToken { ...@@ -336,24 +333,29 @@ class WrapToken extends MessageToken {
// debug("\t\tNo encryption was performed by peer.\n"); // debug("\t\tNo encryption was performed by peer.\n");
readFully(is, confounder); readFully(is, confounder);
// Data is always a multiple of 8 with this GSS Mech if (cipherHelper.isArcFour()) {
// Copy all but last block as they are padding = pads[1];
int numBlocks = (dataSize - CONFOUNDER_SIZE)/8 - 1; readFully(is, dataBuf, dataBufOffset, dataSize-CONFOUNDER_SIZE-1);
int offset = dataBufOffset; } else {
for (int i = 0; i < numBlocks; i++) { // Data is always a multiple of 8 with this GSS Mech
readFully(is, dataBuf, offset, 8); // Copy all but last block as they are
offset += 8; int numBlocks = (dataSize - CONFOUNDER_SIZE)/8 - 1;
int offset = dataBufOffset;
for (int i = 0; i < numBlocks; i++) {
readFully(is, dataBuf, offset, 8);
offset += 8;
}
byte[] finalBlock = new byte[8];
readFully(is, finalBlock);
int padSize = finalBlock[7];
padding = pads[padSize];
// debug("\t\tPadding applied was: " + padSize + "\n");
System.arraycopy(finalBlock, 0, dataBuf, offset,
finalBlock.length - padSize);
} }
byte[] finalBlock = new byte[8];
readFully(is, finalBlock);
int padSize = finalBlock[7];
padding = pads[padSize];
// debug("\t\tPadding applied was: " + padSize + "\n");
System.arraycopy(finalBlock, 0, dataBuf, offset,
finalBlock.length - padSize);
} }
} catch (IOException e) { } catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1, throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
......
/* /*
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,66 +27,30 @@ package sun.security.jgss.krb5; ...@@ -27,66 +27,30 @@ package sun.security.jgss.krb5;
import org.ietf.jgss.*; import org.ietf.jgss.*;
import sun.security.jgss.*; import sun.security.jgss.*;
import java.security.GeneralSecurityException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import sun.security.krb5.Confounder; import sun.security.krb5.Confounder;
import sun.security.krb5.KrbException;
/** /**
* This class represents the new format of GSS tokens, as specified in * This class represents the new format of GSS tokens, as specified in RFC
* draft-ietf-krb-wg-gssapi-cfx-07.txt, emitted by the GSSContext.wrap() * 4121, emitted by the GSSContext.wrap() call. It is a MessageToken except
* call. It is a MessageToken except that it also contains plaintext or * that it also contains plaintext or encrypted data at the end. A WrapToken
* encrypted data at the end. A WrapToken has certain other rules that are * has certain other rules that are peculiar to it and different from a
* peculiar to it and different from a MICToken, which is another type of * MICToken, which is another type of MessageToken. All data in a WrapToken is
* MessageToken. All data in a WrapToken is prepended by a random counfounder * prepended by a random confounder of 16 bytes. Thus, all application data
* of 16 bytes. Thus, all application data is replaced by * is replaced by (confounder || data || tokenHeader || checksum).
* (confounder || data || tokenHeader || checksum).
* *
* @author Seema Malkani * @author Seema Malkani
*/ */
class WrapToken_v2 extends MessageToken_v2 { class WrapToken_v2 extends MessageToken_v2 {
/**
* The size of the random confounder used in a WrapToken.
*/
static final int CONFOUNDER_SIZE = 16;
/*
* A token may come in either in an InputStream or as a
* byte[]. Store a reference to it in either case and process
* it's data only later when getData() is called and
* decryption/copying is needed to be done. Note that JCE can
* decrypt both from a byte[] and from an InputStream.
*/
private boolean readTokenFromInputStream = true;
private InputStream is = null;
private byte[] tokenBytes = null;
private int tokenOffset = 0;
private int tokenLen = 0;
/*
* Application data may come from an InputStream or from a
* byte[]. However, it will always be stored and processed as a
* byte[] since
* (a) the MessageDigest class only accepts a byte[] as input and
* (b) It allows writing to an OuputStream via a CipherOutputStream.
*/
private byte[] dataBytes = null;
private int dataOffset = 0;
private int dataLen = 0;
// the len of the token data:
// (confounder || data || tokenHeader || checksum)
private int dataSize = 0;
// Accessed by CipherHelper // Accessed by CipherHelper
byte[] confounder = null; byte[] confounder = null;
private boolean privacy = false; private final boolean privacy;
private boolean initiator = true;
/** /**
* Constructs a WrapToken from token bytes obtained from the * Constructs a WrapToken from token bytes obtained from the
...@@ -104,30 +68,9 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -104,30 +68,9 @@ class WrapToken_v2 extends MessageToken_v2 {
byte[] tokenBytes, int tokenOffset, int tokenLen, byte[] tokenBytes, int tokenOffset, int tokenLen,
MessageProp prop) throws GSSException { MessageProp prop) throws GSSException {
// Just parse the MessageToken part first
super(Krb5Token.WRAP_ID_v2, context, super(Krb5Token.WRAP_ID_v2, context,
tokenBytes, tokenOffset, tokenLen, prop); tokenBytes, tokenOffset, tokenLen, prop);
this.readTokenFromInputStream = false;
// rotate token bytes as per RRC
byte[] new_tokenBytes = new byte[tokenLen];
if (rotate_left(tokenBytes, tokenOffset, new_tokenBytes, tokenLen)) {
this.tokenBytes = new_tokenBytes;
this.tokenOffset = 0;
} else {
this.tokenBytes = tokenBytes;
this.tokenOffset = tokenOffset;
}
// Will need the token bytes again when extracting data
this.tokenLen = tokenLen;
this.privacy = prop.getPrivacy(); this.privacy = prop.getPrivacy();
dataSize = tokenLen - TOKEN_HEADER_SIZE;
// save initiator
this.initiator = context.isInitiator();
} }
/** /**
...@@ -145,27 +88,8 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -145,27 +88,8 @@ class WrapToken_v2 extends MessageToken_v2 {
InputStream is, MessageProp prop) InputStream is, MessageProp prop)
throws GSSException { throws GSSException {
// Just parse the MessageToken part first
super(Krb5Token.WRAP_ID_v2, context, is, prop); super(Krb5Token.WRAP_ID_v2, context, is, prop);
// Will need the token bytes again when extracting data
this.is = is;
this.privacy = prop.getPrivacy(); this.privacy = prop.getPrivacy();
// get the token length
try {
this.tokenLen = is.available();
} catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
getTokenName(getTokenId())
+ ": " + e.getMessage());
}
// data size
dataSize = tokenLen - TOKEN_HEADER_SIZE;
// save initiator
this.initiator = context.isInitiator();
} }
/** /**
...@@ -177,13 +101,9 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -177,13 +101,9 @@ class WrapToken_v2 extends MessageToken_v2 {
*/ */
public byte[] getData() throws GSSException { public byte[] getData() throws GSSException {
byte[] temp = new byte[dataSize]; byte[] temp = new byte[tokenDataLen];
int len = getData(temp, 0); int len = getData(temp, 0);
// len obtained is after removing confounder, tokenHeader and HMAC return Arrays.copyOf(temp, len);
byte[] retVal = new byte[len];
System.arraycopy(temp, 0, retVal, 0, retVal.length);
return retVal;
} }
/** /**
...@@ -200,69 +120,26 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -200,69 +120,26 @@ class WrapToken_v2 extends MessageToken_v2 {
public int getData(byte[] dataBuf, int dataBufOffset) public int getData(byte[] dataBuf, int dataBufOffset)
throws GSSException { throws GSSException {
if (readTokenFromInputStream)
getDataFromStream(dataBuf, dataBufOffset);
else
getDataFromBuffer(dataBuf, dataBufOffset);
int retVal = 0;
if (privacy) {
retVal = dataSize - confounder.length -
TOKEN_HEADER_SIZE - cipherHelper.getChecksumLength();
} else {
retVal = dataSize - cipherHelper.getChecksumLength();
}
return retVal;
}
/**
* Helper routine to obtain the application data transmitted in
* this WrapToken. It is called if the WrapToken was constructed
* with a byte array as input.
* @param dataBuf the output buffer into which the data must be
* written
* @param dataBufOffset the offset at which to write the data
* @throws GSSException if an error occurs while decrypting any
* cipher text and checking for validity
*/
private void getDataFromBuffer(byte[] dataBuf, int dataBufOffset)
throws GSSException {
int dataPos = tokenOffset + TOKEN_HEADER_SIZE;
int data_length = 0;
if (dataPos + dataSize > tokenOffset + tokenLen)
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
"Insufficient data in "
+ getTokenName(getTokenId()));
// debug("WrapToken cons: data is token is [" + // debug("WrapToken cons: data is token is [" +
// getHexBytes(tokenBytes, tokenOffset, tokenLen) + "]\n"); // getHexBytes(tokenBytes, tokenOffset, tokenLen) + "]\n");
confounder = new byte[CONFOUNDER_SIZE];
// Do decryption if this token was privacy protected. // Do decryption if this token was privacy protected.
if (privacy) { if (privacy) {
// decrypt data // decrypt data
cipherHelper.decryptData(this, tokenBytes, dataPos, dataSize, cipherHelper.decryptData(this, tokenData, 0, tokenDataLen,
dataBuf, dataBufOffset, getKeyUsage()); dataBuf, dataBufOffset, getKeyUsage());
/*
debug("\t\tDecrypted data is [" + return tokenDataLen - CONFOUNDER_SIZE -
getHexBytes(confounder) + " " + TOKEN_HEADER_SIZE - cipherHelper.getChecksumLength();
getHexBytes(dataBuf, dataBufOffset,
dataSize - CONFOUNDER_SIZE) +
"]\n");
*/
data_length = dataSize - CONFOUNDER_SIZE -
TOKEN_HEADER_SIZE - cipherHelper.getChecksumLength();
} else { } else {
// Token data is in cleartext // Token data is in cleartext
debug("\t\tNo encryption was performed by peer.\n"); // debug("\t\tNo encryption was performed by peer.\n");
// data // data
data_length = dataSize - cipherHelper.getChecksumLength(); int data_length = tokenDataLen - cipherHelper.getChecksumLength();
System.arraycopy(tokenBytes, dataPos, System.arraycopy(tokenData, 0,
dataBuf, dataBufOffset, dataBuf, dataBufOffset,
data_length); data_length);
// debug("\t\tData is: " + getHexBytes(dataBuf, data_length)); // debug("\t\tData is: " + getHexBytes(dataBuf, data_length));
...@@ -274,95 +151,26 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -274,95 +151,26 @@ class WrapToken_v2 extends MessageToken_v2 {
throw new GSSException(GSSException.BAD_MIC, -1, throw new GSSException(GSSException.BAD_MIC, -1,
"Corrupt checksum in Wrap token"); "Corrupt checksum in Wrap token");
} }
return data_length;
} }
} }
/** /**
* Helper routine to obtain the application data transmitted in * Writes a WrapToken_v2 object
* this WrapToken. It is called if the WrapToken was constructed
* with an Inputstream.
* @param dataBuf the output buffer into which the data must be
* written
* @param dataBufOffset the offset at which to write the data
* @throws GSSException if an error occurs while decrypting any
* cipher text and checking for validity
*/ */
private void getDataFromStream(byte[] dataBuf, int dataBufOffset)
throws GSSException {
int data_length = 0;
// Don't check the token length. Data will be read on demand from
// the InputStream.
// debug("WrapToken cons: data will be read from InputStream.\n");
confounder = new byte[CONFOUNDER_SIZE];
try {
// Do decryption if this token was privacy protected.
if (privacy) {
cipherHelper.decryptData(this, is, dataSize,
dataBuf, dataBufOffset, getKeyUsage());
/*
debug("\t\tDecrypted data is [" +
getHexBytes(confounder) + " " +
getHexBytes(dataBuf, dataBufOffset,
dataSize - CONFOUNDER_SIZE) +
"]\n");
*/
data_length = dataSize - CONFOUNDER_SIZE -
TOKEN_HEADER_SIZE - cipherHelper.getChecksumLength();
} else {
// Token data is in cleartext
debug("\t\tNo encryption was performed by peer.\n");
readFully(is, confounder);
// read the data
data_length = dataSize - cipherHelper.getChecksumLength();
readFully(is, dataBuf, dataBufOffset, data_length);
/*
* Make sure checksum is not corrupt
*/
if (!verifySign(dataBuf, dataBufOffset, data_length)) {
throw new GSSException(GSSException.BAD_MIC, -1,
"Corrupt checksum in Wrap token");
}
}
} catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
getTokenName(getTokenId())
+ ": " + e.getMessage());
}
}
public WrapToken_v2(Krb5Context context, MessageProp prop, public WrapToken_v2(Krb5Context context, MessageProp prop,
byte[] dataBytes, int dataOffset, int dataLen) byte[] dataBytes, int dataOffset, int dataLen)
throws GSSException { throws GSSException {
super(Krb5Token.WRAP_ID_v2, context); super(Krb5Token.WRAP_ID_v2, context);
confounder = Confounder.bytes(CONFOUNDER_SIZE); confounder = Confounder.bytes(CONFOUNDER_SIZE);
dataSize = confounder.length + dataLen + TOKEN_HEADER_SIZE +
cipherHelper.getChecksumLength();
this.dataBytes = dataBytes;
this.dataOffset = dataOffset;
this.dataLen = dataLen;
// save initiator
this.initiator = context.isInitiator();
// debug("\nWrapToken cons: data to wrap is [" + // debug("\nWrapToken cons: data to wrap is [" +
// getHexBytes(confounder) + " " + // getHexBytes(confounder) + " " +
// getHexBytes(dataBytes, dataOffset, dataLen) + "]\n"); // getHexBytes(dataBytes, dataOffset, dataLen) + "]\n");
genSignAndSeqNumber(prop, genSignAndSeqNumber(prop, dataBytes, dataOffset, dataLen);
dataBytes, dataOffset, dataLen);
/* /*
* If the application decides to ask for privacy when the context * If the application decides to ask for privacy when the context
...@@ -374,110 +182,42 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -374,110 +182,42 @@ class WrapToken_v2 extends MessageToken_v2 {
prop.setPrivacy(false); prop.setPrivacy(false);
privacy = prop.getPrivacy(); privacy = prop.getPrivacy();
}
public void encode(OutputStream os) throws IOException, GSSException {
super.encode(os);
// debug("\n\nWriting data: [");
if (!privacy) { if (!privacy) {
// Wrap Tokens (without confidentiality) = // Wrap Tokens (without confidentiality) =
// { 16 byte token_header | plaintext | 12-byte HMAC } // { 16 byte token_header | plaintext | 12-byte HMAC }
// where HMAC is on { plaintext | token_header } // where HMAC is on { plaintext | token_header }
// calculate checksum tokenData = new byte[dataLen + checksum.length];
byte[] checksum = getChecksum(dataBytes, dataOffset, dataLen); System.arraycopy(dataBytes, dataOffset, tokenData, 0, dataLen);
System.arraycopy(checksum, 0, tokenData, dataLen, checksum.length);
// data
// debug(" " + getHexBytes(dataBytes, dataOffset, dataLen));
os.write(dataBytes, dataOffset, dataLen);
// write HMAC
// debug(" " + getHexBytes(checksum,
// cipherHelper.getChecksumLength()));
os.write(checksum);
} else { } else {
// Wrap Tokens (with confidentiality) = // Wrap Tokens (with confidentiality) =
// { 16 byte token_header | // { 16 byte token_header |
// Encrypt(16-byte confounder | plaintext | token_header) | // Encrypt(16-byte confounder | plaintext | token_header) |
// 12-byte HMAC } // 12-byte HMAC }
cipherHelper.encryptData(this, confounder, getTokenHeader(), tokenData = cipherHelper.encryptData(this, confounder, getTokenHeader(),
dataBytes, dataOffset, dataLen, getKeyUsage(), os); dataBytes, dataOffset, dataLen, getKeyUsage());
} }
// debug("]\n");
} }
public byte[] encode() throws IOException, GSSException { public void encode(OutputStream os) throws IOException {
// XXX Fine tune this initial size encodeHeader(os);
ByteArrayOutputStream bos = new ByteArrayOutputStream(dataSize + 50); os.write(tokenData);
encode(bos);
return bos.toByteArray();
} }
public int encode(byte[] outToken, int offset) public byte[] encode() throws IOException {
throws IOException, GSSException { ByteArrayOutputStream bos = new ByteArrayOutputStream(
MessageToken_v2.TOKEN_HEADER_SIZE + tokenData.length);
int retVal = 0; encode(bos);
return bos.toByteArray();
// Token header is small
ByteArrayOutputStream bos = new ByteArrayOutputStream();
super.encode(bos);
byte[] header = bos.toByteArray();
System.arraycopy(header, 0, outToken, offset, header.length);
offset += header.length;
// debug("WrapToken.encode: Writing data: [");
if (!privacy) {
// Wrap Tokens (without confidentiality) =
// { 16 byte token_header | plaintext | 12-byte HMAC }
// where HMAC is on { plaintext | token_header }
// calculate checksum
byte[] checksum = getChecksum(dataBytes, dataOffset, dataLen);
// data
// debug(" " + getHexBytes(dataBytes, dataOffset, dataLen));
System.arraycopy(dataBytes, dataOffset, outToken, offset,
dataLen);
offset += dataLen;
// write HMAC
// debug(" " + getHexBytes(checksum,
// cipherHelper.getChecksumLength()));
System.arraycopy(checksum, 0, outToken, offset,
cipherHelper.getChecksumLength());
retVal = header.length + dataLen + cipherHelper.getChecksumLength();
} else {
// Wrap Tokens (with confidentiality) =
// { 16 byte token_header |
// Encrypt(16-byte confounder | plaintext | token_header) |
// 12-byte HMAC }
int cLen = cipherHelper.encryptData(this, confounder,
getTokenHeader(), dataBytes, dataOffset, dataLen,
outToken, offset, getKeyUsage());
retVal = header.length + cLen;
// debug(getHexBytes(outToken, offset, dataSize));
}
// debug("]\n");
// %%% assume that plaintext length == ciphertext len
return retVal;
} }
protected int getKrb5TokenSize() throws GSSException { public int encode(byte[] outToken, int offset) throws IOException {
return (getTokenSize() + dataSize); byte[] token = encode();
System.arraycopy(token, 0, outToken, offset, token.length);
return token.length;
} }
// This implementation is way to conservative. And it certainly // This implementation is way to conservative. And it certainly
...@@ -485,6 +225,7 @@ class WrapToken_v2 extends MessageToken_v2 { ...@@ -485,6 +225,7 @@ class WrapToken_v2 extends MessageToken_v2 {
static int getSizeLimit(int qop, boolean confReq, int maxTokenSize, static int getSizeLimit(int qop, boolean confReq, int maxTokenSize,
CipherHelper ch) throws GSSException { CipherHelper ch) throws GSSException {
return (GSSHeader.getMaxMechTokenSize(OID, maxTokenSize) - return (GSSHeader.getMaxMechTokenSize(OID, maxTokenSize) -
(getTokenSize(ch) + CONFOUNDER_SIZE) - 8 /* safety */); (TOKEN_HEADER_SIZE + ch.getChecksumLength() + CONFOUNDER_SIZE)
- 8 /* safety */);
} }
} }
/* /*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,34 @@ ...@@ -25,6 +25,34 @@
* @test * @test
* @bug 6706974 * @bug 6706974
* @summary Add krb5 test infrastructure * @summary Add krb5 test infrastructure
* @run main/othervm BasicKrb5Test
* @run main/othervm BasicKrb5Test des-cbc-crc
* @run main/othervm BasicKrb5Test des-cbc-md5
* @run main/othervm BasicKrb5Test des3-cbc-sha1
* @run main/othervm BasicKrb5Test aes128-cts
* @run main/othervm BasicKrb5Test aes256-cts
* @run main/othervm BasicKrb5Test rc4-hmac
* @run main/othervm BasicKrb5Test -s
* @run main/othervm BasicKrb5Test des-cbc-crc -s
* @run main/othervm BasicKrb5Test des-cbc-md5 -s
* @run main/othervm BasicKrb5Test des3-cbc-sha1 -s
* @run main/othervm BasicKrb5Test aes128-cts -s
* @run main/othervm BasicKrb5Test aes256-cts -s
* @run main/othervm BasicKrb5Test rc4-hmac -s
* @run main/othervm BasicKrb5Test -C
* @run main/othervm BasicKrb5Test des-cbc-crc -C
* @run main/othervm BasicKrb5Test des-cbc-md5 -C
* @run main/othervm BasicKrb5Test des3-cbc-sha1 -C
* @run main/othervm BasicKrb5Test aes128-cts -C
* @run main/othervm BasicKrb5Test aes256-cts -C
* @run main/othervm BasicKrb5Test rc4-hmac -C
* @run main/othervm BasicKrb5Test -s -C
* @run main/othervm BasicKrb5Test des-cbc-crc -s -C
* @run main/othervm BasicKrb5Test des-cbc-md5 -s -C
* @run main/othervm BasicKrb5Test des3-cbc-sha1 -s -C
* @run main/othervm BasicKrb5Test aes128-cts -s -C
* @run main/othervm BasicKrb5Test aes256-cts -s -C
* @run main/othervm BasicKrb5Test rc4-hmac -s -C
*/ */
import org.ietf.jgss.GSSName; import org.ietf.jgss.GSSName;
...@@ -39,6 +67,7 @@ import sun.security.krb5.internal.crypto.EType; ...@@ -39,6 +67,7 @@ import sun.security.krb5.internal.crypto.EType;
*/ */
public class BasicKrb5Test { public class BasicKrb5Test {
private static boolean conf = true;
/** /**
* @param args empty or etype * @param args empty or etype
*/ */
...@@ -46,8 +75,10 @@ public class BasicKrb5Test { ...@@ -46,8 +75,10 @@ public class BasicKrb5Test {
throws Exception { throws Exception {
String etype = null; String etype = null;
if (args.length > 0) { for (String arg: args) {
etype = args[0]; if (arg.equals("-s")) Context.usingStream = true;
else if(arg.equals("-C")) conf = false;
else etype = arg;
} }
// Creates and starts the KDC. This line must be put ahead of etype check // Creates and starts the KDC. This line must be put ahead of etype check
...@@ -56,8 +87,9 @@ public class BasicKrb5Test { ...@@ -56,8 +87,9 @@ public class BasicKrb5Test {
System.out.println("Testing etype " + etype); System.out.println("Testing etype " + etype);
if (etype != null && !EType.isSupported(Config.getInstance().getType(etype))) { if (etype != null && !EType.isSupported(Config.getInstance().getType(etype))) {
// aes256 is not enabled on all systems
System.out.println("Not supported."); System.out.println("Not supported.");
System.exit(0); return;
} }
new BasicKrb5Test().go(OneKDC.SERVER, OneKDC.BACKEND); new BasicKrb5Test().go(OneKDC.SERVER, OneKDC.BACKEND);
...@@ -71,6 +103,7 @@ public class BasicKrb5Test { ...@@ -71,6 +103,7 @@ public class BasicKrb5Test {
c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID); c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
c.x().requestCredDeleg(true); c.x().requestCredDeleg(true);
c.x().requestConf(conf);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
c.status(); c.status();
...@@ -90,6 +123,7 @@ public class BasicKrb5Test { ...@@ -90,6 +123,7 @@ public class BasicKrb5Test {
s = null; s = null;
s2.startAsClient(backend, GSSUtil.GSS_KRB5_MECH_OID); s2.startAsClient(backend, GSSUtil.GSS_KRB5_MECH_OID);
s2.x().requestConf(conf);
b.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); b.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
s2.status(); s2.status();
......
/* /*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -42,7 +42,8 @@ import org.ietf.jgss.Oid; ...@@ -42,7 +42,8 @@ import org.ietf.jgss.Oid;
import com.sun.security.jgss.ExtendedGSSContext; import com.sun.security.jgss.ExtendedGSSContext;
import com.sun.security.jgss.InquireType; import com.sun.security.jgss.InquireType;
import com.sun.security.jgss.AuthorizationDataEntry; import com.sun.security.jgss.AuthorizationDataEntry;
import java.io.File; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/** /**
* Context of a JGSS subject, encapsulating Subject and GSSContext. * Context of a JGSS subject, encapsulating Subject and GSSContext.
...@@ -78,6 +79,8 @@ public class Context { ...@@ -78,6 +79,8 @@ public class Context {
private String name; private String name;
private GSSCredential cred; // see static method delegated(). private GSSCredential cred; // see static method delegated().
static boolean usingStream = false;
private Context() {} private Context() {}
/** /**
...@@ -365,7 +368,14 @@ public class Context { ...@@ -365,7 +368,14 @@ public class Context {
public byte[] run(Context me, byte[] dummy) throws Exception { public byte[] run(Context me, byte[] dummy) throws Exception {
System.out.println("wrap"); System.out.println("wrap");
MessageProp p1 = new MessageProp(0, true); MessageProp p1 = new MessageProp(0, true);
byte[] out = me.x.wrap(messageBytes, 0, messageBytes.length, p1); byte[] out;
if (usingStream) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
me.x.wrap(new ByteArrayInputStream(messageBytes), os, p1);
out = os.toByteArray();
} else {
out = me.x.wrap(messageBytes, 0, messageBytes.length, p1);
}
System.out.println(printProp(p1)); System.out.println(printProp(p1));
return out; return out;
} }
...@@ -375,27 +385,46 @@ public class Context { ...@@ -375,27 +385,46 @@ public class Context {
@Override @Override
public byte[] run(Context me, byte[] input) throws Exception { public byte[] run(Context me, byte[] input) throws Exception {
MessageProp p1 = new MessageProp(0, true); MessageProp p1 = new MessageProp(0, true);
byte[] bytes = me.x.unwrap(input, 0, input.length, p1); byte[] bytes;
if (usingStream) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
me.x.unwrap(new ByteArrayInputStream(input), os, p1);
bytes = os.toByteArray();
} else {
bytes = me.x.unwrap(input, 0, input.length, p1);
}
if (!Arrays.equals(messageBytes, bytes)) if (!Arrays.equals(messageBytes, bytes))
throw new Exception("wrap/unwrap mismatch"); throw new Exception("wrap/unwrap mismatch");
System.out.println("unwrap"); System.out.println("unwrap");
System.out.println(printProp(p1)); System.out.println(printProp(p1));
p1 = new MessageProp(0, true); p1 = new MessageProp(0, true);
System.out.println("getMIC"); System.out.println("getMIC");
bytes = me.x.getMIC(bytes, 0, bytes.length, p1); if (usingStream) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
me.x.getMIC(new ByteArrayInputStream(messageBytes), os, p1);
bytes = os.toByteArray();
} else {
bytes = me.x.getMIC(messageBytes, 0, messageBytes.length, p1);
}
System.out.println(printProp(p1)); System.out.println(printProp(p1));
return bytes; return bytes;
} }
}, t); }, t);
// Re-unwrap should make p2.isDuplicateToken() returns true // Re-unwrap should make p2.isDuplicateToken() returns true
s1.doAs(new Action() { s1.doAs(new Action() {
@Override @Override
public byte[] run(Context me, byte[] input) throws Exception { public byte[] run(Context me, byte[] input) throws Exception {
MessageProp p1 = new MessageProp(0, true); MessageProp p1 = new MessageProp(0, true);
System.out.println("verifyMIC"); System.out.println("verifyMIC");
me.x.verifyMIC(input, 0, input.length, if (usingStream) {
messageBytes, 0, messageBytes.length, me.x.verifyMIC(new ByteArrayInputStream(input),
p1); new ByteArrayInputStream(messageBytes), p1);
} else {
me.x.verifyMIC(input, 0, input.length,
messageBytes, 0, messageBytes.length,
p1);
}
System.out.println(printProp(p1)); System.out.println(printProp(p1));
return null; return null;
} }
...@@ -416,7 +445,9 @@ public class Context { ...@@ -416,7 +445,9 @@ public class Context {
sb.append(prop.isGapToken()?"gap, ":""); sb.append(prop.isGapToken()?"gap, ":"");
sb.append(prop.isOldToken()?"old, ":""); sb.append(prop.isOldToken()?"old, ":"");
sb.append(prop.isUnseqToken()?"unseq, ":""); sb.append(prop.isUnseqToken()?"unseq, ":"");
sb.append(prop.getMinorString()+ "(" + prop.getMinorStatus()+")"); if (prop.getMinorStatus() != 0) {
sb.append(prop.getMinorString()+ "(" + prop.getMinorStatus()+")");
}
return sb.toString(); return sb.toString();
} }
...@@ -442,7 +473,13 @@ public class Context { ...@@ -442,7 +473,13 @@ public class Context {
return null; return null;
} else { } else {
System.out.println(c.name + " call initSecContext"); System.out.println(c.name + " call initSecContext");
return me.x.initSecContext(input, 0, input.length); if (usingStream) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
me.x.initSecContext(new ByteArrayInputStream(input), os);
return os.size() == 0 ? null : os.toByteArray();
} else {
return me.x.initSecContext(input, 0, input.length);
}
} }
} }
}, t); }, t);
...@@ -460,7 +497,13 @@ public class Context { ...@@ -460,7 +497,13 @@ public class Context {
return null; return null;
} else { } else {
System.out.println(s.name + " called acceptSecContext"); System.out.println(s.name + " called acceptSecContext");
return me.x.acceptSecContext(input, 0, input.length); if (usingStream) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
me.x.acceptSecContext(new ByteArrayInputStream(input), os);
return os.size() == 0 ? null : os.toByteArray();
} else {
return me.x.acceptSecContext(input, 0, input.length);
}
} }
} }
}, t); }, t);
......
#
# Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test
# @bug 6706974
# @summary Add krb5 test infrastructure
# @run shell/timeout=300 basic.sh
#
if [ "${TESTSRC}" = "" ] ; then
TESTSRC="."
fi
if [ "${TESTJAVA}" = "" ] ; then
echo "TESTJAVA not set. Test cannot execute."
echo "FAILED!!!"
exit 1
fi
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
Windows_* )
FS="\\"
SEP=";"
;;
CYGWIN* )
FS="/"
SEP=";"
;;
* )
FS="/"
SEP=":"
;;
esac
${TESTJAVA}${FS}bin${FS}javac -XDignore.symbol.file -d . \
${TESTSRC}${FS}BasicKrb5Test.java \
${TESTSRC}${FS}KDC.java \
${TESTSRC}${FS}OneKDC.java \
${TESTSRC}${FS}Action.java \
${TESTSRC}${FS}Context.java \
|| exit 10
# Add $TESTSRC to classpath so that customized nameservice can be used
J="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}. BasicKrb5Test"
$J || exit 100
$J des-cbc-crc || exit 1
$J des-cbc-md5 || exit 3
$J des3-cbc-sha1 || exit 16
$J aes128-cts || exit 17
$J aes256-cts || exit 18
$J rc4-hmac || exit 23
exit 0
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册