6975866: api/org_ietf/jgss/GSSContext/index.html#wrapUnwrapIOTest started to fail since jdk7 b102
Reviewed-by: valeriep
--- a/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -710,29 +710,21 @@
* where HMAC is on {16-byte confounder | plaintext | 16-byte token_header}
* HMAC is not encrypted; it is appended at the end.
*/
- void encryptData(WrapToken_v2 token, byte[] confounder, byte[] tokenHeader,
- byte[] plaintext, int start, int len, int key_usage, OutputStream os)
- throws GSSException, IOException {
+ byte[] encryptData(WrapToken_v2 token, byte[] confounder, byte[] tokenHeader,
+ byte[] plaintext, int start, int len, int key_usage)
+ throws GSSException {
- byte[] ctext = null;
switch (etype) {
- case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
- ctext = aes128Encrypt(confounder, tokenHeader,
- plaintext, start, len, key_usage);
- break;
- case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
- ctext = aes256Encrypt(confounder, tokenHeader,
- plaintext, start, len, key_usage);
- break;
- default:
- throw new GSSException(GSSException.FAILURE, -1,
- "Unsupported etype: " + etype);
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
+ return aes128Encrypt(confounder, tokenHeader,
+ plaintext, start, len, key_usage);
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
+ return aes256Encrypt(confounder, tokenHeader,
+ plaintext, start, len, key_usage);
+ default:
+ 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,
--- a/jdk/src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,42 +26,40 @@
package sun.security.jgss.krb5;
import org.ietf.jgss.*;
-import sun.security.jgss.*;
-import sun.security.krb5.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
-import java.security.GeneralSecurityException;
+import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
+import java.util.Arrays;
/**
* This class is a base class for new GSS token definitions, as defined
- * in draft-ietf-krb-wg-gssapi-cfx-07.txt, that pertain to per-message
- * GSS-API calls. Conceptually GSS-API has two types of per-message tokens:
- * WrapToken and MicToken. They differ in the respect that a WrapToken
- * carries additional plaintext or ciphertext application data besides
- * just the sequence number and checksum. This class encapsulates the
- * commonality in the structure of the WrapToken and the MicToken.
- * This structure can be represented as:
+ * in RFC 4121, that pertain to per-message GSS-API calls. Conceptually
+ * GSS-API has two types of per-message tokens: WrapToken and MicToken.
+ * They differ in the respect that a WrapToken carries additional plaintext
+ * or ciphertext application data besides just the sequence number and
+ * checksum. This class encapsulates the commonality in the structure of
+ * the WrapToken and the MicToken. This structure can be represented as:
* <p>
* <pre>
- * Wrap Tokens
+ * Wrap Tokens
*
* Octet no Name Description
* ---------------------------------------------------------------
* 0..1 TOK_ID Identification field. Tokens emitted by
- * GSS_Wrap() contain the the hex value 05 04
- * expressed in big endian order in this field.
+ * GSS_Wrap() contain the hex value 05 04
+ * expressed in big-endian order in this field.
* 2 Flags Attributes field, as described in section
* 4.2.2.
* 3 Filler Contains the hex value FF.
- * 4..5 EC Contains the "extra count" field, in big
+ * 4..5 EC Contains the "extra count" field, in big-
* endian order as described in section 4.2.3.
* 6..7 RRC Contains the "right rotation count" in big
* endian order, as described in section 4.2.5.
* 8..15 SND_SEQ Sequence number field in clear text,
- * expressed in big endian order.
+ * expressed in big-endian order.
* 16..last Data Encrypted data for Wrap tokens with
* confidentiality, or plaintext data followed
* by the checksum for Wrap tokens without
@@ -73,67 +71,82 @@
* -----------------------------------------------------------------
* 0..1 TOK_ID Identification field. Tokens emitted by
* GSS_GetMIC() contain the hex value 04 04
- * expressed in big endian order in this field.
+ * expressed in big-endian order in this field.
* 2 Flags Attributes field, as described in section
* 4.2.2.
* 3..7 Filler Contains five octets of hex value FF.
* 8..15 SND_SEQ Sequence number field in clear text,
- * expressed in big endian order.
+ * expressed in big-endian order.
* 16..last SGN_CKSUM Checksum of the "to-be-signed" data and
* octet 0..15, as described in section 4.2.4.
*
* </pre>
* <p>
+ * This class is the super class of WrapToken_v2 and MicToken_v2. The token's
+ * header (bytes[0..15]) and data (byte[16..]) are saved in tokenHeader and
+ * tokenData fields. Since there is no easy way to find out the exact length
+ * of a WrapToken_v2 token from any header info, in the case of reading from
+ * stream, we read all available() bytes into the token.
+ * <p>
+ * All read actions are performed in this super class. On the write part, the
+ * super class only write the tokenHeader, and the content writing is inside
+ * child classes.
*
* @author Seema Malkani
*/
abstract class MessageToken_v2 extends Krb5Token {
+ protected static final int TOKEN_HEADER_SIZE = 16;
private static final int TOKEN_ID_POS = 0;
private static final int TOKEN_FLAG_POS = 2;
private static final int TOKEN_EC_POS = 4;
private static final int TOKEN_RRC_POS = 6;
- // token header size
- static final int TOKEN_HEADER_SIZE = 16;
-
- private int tokenId = 0;
- private int seqNumber;
-
- // EC and RRC fields
- private int ec = 0;
- private int rrc = 0;
-
- private boolean confState = true;
- private boolean initiator = true;
+ /**
+ * The size of the random confounder used in a WrapToken.
+ */
+ protected static final int CONFOUNDER_SIZE = 16;
- byte[] confounder = null;
- byte[] checksum = null;
-
- private int key_usage = 0;
- private byte[] seqNumberData = null;
-
- private MessageTokenHeader tokenHeader = null;
-
- /* cipher instance used by the corresponding GSSContext */
- CipherHelper cipherHelper = null;
-
- // draft-ietf-krb-wg-gssapi-cfx-07
+ // RFC 4121, key usage values
static final int KG_USAGE_ACCEPTOR_SEAL = 22;
static final int KG_USAGE_ACCEPTOR_SIGN = 23;
static final int KG_USAGE_INITIATOR_SEAL = 24;
static final int KG_USAGE_INITIATOR_SIGN = 25;
- // draft-ietf-krb-wg-gssapi-cfx-07
+ // RFC 4121, Flags Field
private static final int FLAG_SENDER_IS_ACCEPTOR = 1;
private static final int FLAG_WRAP_CONFIDENTIAL = 2;
private static final int FLAG_ACCEPTOR_SUBKEY = 4;
private static final int FILLER = 0xff;
+ private MessageTokenHeader tokenHeader = null;
+
+ // Common field
+ private int tokenId = 0;
+ private int seqNumber;
+ protected byte[] tokenData; // content of token, without the header
+ protected int tokenDataLen;
+
+ // Key usage number for crypto action
+ private int key_usage = 0;
+
+ // EC and RRC fields, WrapToken only
+ private int ec = 0;
+ private int rrc = 0;
+
+ // Checksum. Always in MicToken, might be in WrapToken
+ byte[] checksum = null;
+
+ // Context properties
+ private boolean confState = true;
+ private boolean initiator = true;
+
+ /* cipher instance used by the corresponding GSSContext */
+ CipherHelper cipherHelper = null;
+
/**
- * Constructs a MessageToken from a byte array. If there are more bytes
- * in the array than needed, the extra bytes are simply ignroed.
+ * Constructs a MessageToken from a byte array.
*
* @param tokenId the token id that should be contained in this token as
* it is read.
@@ -156,7 +169,9 @@
/**
* Constructs a MessageToken from an InputStream. Bytes will be read on
* demand and the thread might block if there are not enough bytes to
- * complete the token.
+ * complete the token. Please note there is no accurate way to find out
+ * the size of a token, but we try our best to make sure there is
+ * enough bytes to construct one.
*
* @param tokenId the token id that should be contained in this token as
* it is read.
@@ -186,25 +201,58 @@
: KG_USAGE_ACCEPTOR_SIGN);
}
- // Read checksum
- int tokenLen = is.available();
- byte[] data = new byte[tokenLen];
- readFully(is, data);
- checksum = new byte[cipherHelper.getChecksumLength()];
- System.arraycopy(data, tokenLen-cipherHelper.getChecksumLength(),
- checksum, 0, cipherHelper.getChecksumLength());
- // debug("\nLeaving MessageToken.Cons\n");
+ int minSize = 0; // minimal size for token data
+ if (tokenId == Krb5Token.WRAP_ID_v2 && prop.getPrivacy()) {
+ minSize = CONFOUNDER_SIZE +
+ TOKEN_HEADER_SIZE + cipherHelper.getChecksumLength();
+ } else {
+ minSize = cipherHelper.getChecksumLength();
+ }
- // validate EC for Wrap tokens without confidentiality
- if (!prop.getPrivacy() &&
- (tokenId == Krb5Token.WRAP_ID_v2)) {
- if (checksum.length != ec) {
- throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
- getTokenName(tokenId) + ":" + "EC incorrect!");
+ // Read token data
+ if (tokenId == Krb5Token.MIC_ID_v2) {
+ // The only case we can precisely predict the token data length
+ tokenDataLen = minSize;
+ tokenData = new byte[minSize];
+ readFully(is, tokenData);
+ } else {
+ tokenDataLen = is.available();
+ if (tokenDataLen >= minSize) { // read in one shot
+ tokenData = new byte[tokenDataLen];
+ readFully(is, tokenData);
+ } else {
+ byte[] tmp = new byte[minSize];
+ readFully(is, tmp);
+ // Hope while blocked in the read above, more data would
+ // come and is.available() below contains the whole token.
+ int more = is.available();
+ tokenDataLen = minSize + more;
+ tokenData = Arrays.copyOf(tmp, tokenDataLen);
+ readFully(is, tokenData, minSize, more);
}
}
+ if (tokenId == Krb5Token.WRAP_ID_v2) {
+ // Does non-confidential data needs a rotate?
+ rotate();
+ }
+ if (tokenId == Krb5Token.MIC_ID_v2 ||
+ (tokenId == Krb5Token.WRAP_ID_v2 && !prop.getPrivacy())) {
+ // Read checksum
+ int chkLen = cipherHelper.getChecksumLength();
+ checksum = new byte[chkLen];
+ System.arraycopy(tokenData, tokenDataLen-chkLen,
+ checksum, 0, chkLen);
+
+ // validate EC for Wrap tokens without confidentiality
+ if (tokenId == Krb5Token.WRAP_ID_v2 && !prop.getPrivacy()) {
+ if (chkLen != ec) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+ getTokenName(tokenId) + ":" + "EC incorrect!");
+ }
+ }
+ }
} catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
getTokenName(tokenId) + ":" + e.getMessage());
@@ -263,8 +311,7 @@
prop.setPrivacy(false);
}
- // Create a new gss token header as defined in
- // draft-ietf-krb-wg-gssapi-cfx-07
+ // Create a new gss token header as defined in RFC 4121
tokenHeader = new MessageTokenHeader(tokenId,
prop.getPrivacy(), true);
// debug("\n\t Message Header = " +
@@ -326,50 +373,21 @@
* Rotate bytes as per the "RRC" (Right Rotation Count) received.
* Our implementation does not do any rotates when sending, only
* when receiving, we rotate left as per the RRC count, to revert it.
- *
- * @return true if bytes are rotated
*/
- public boolean rotate_left(byte[] in_bytes, int tokenOffset,
- byte[] out_bytes, int bufsize) {
-
- int offset = 0;
- // debug("\nRotate left: (before rotation) in_bytes = [ " +
- // getHexBytes(in_bytes, tokenOffset, bufsize) + "]");
- if (rrc > 0) {
- if (bufsize == 0) {
- return false;
- }
- rrc = rrc % (bufsize - TOKEN_HEADER_SIZE);
- if (rrc == 0) {
- return false;
- }
+ private void rotate() {
+ if (rrc % tokenDataLen != 0) {
+ rrc = rrc % tokenDataLen;
+ byte[] newBytes = new byte[tokenDataLen];
- // if offset is not zero
- if (tokenOffset > 0) {
- offset += tokenOffset;
- }
-
- // copy the header
- System.arraycopy(in_bytes, offset, out_bytes, 0, TOKEN_HEADER_SIZE);
- offset += TOKEN_HEADER_SIZE;
+ System.arraycopy(tokenData, rrc, newBytes, 0, tokenDataLen-rrc);
+ System.arraycopy(tokenData, 0, newBytes, tokenDataLen-rrc, rrc);
- // copy rest of the bytes
- System.arraycopy(in_bytes, offset+rrc, out_bytes,
- TOKEN_HEADER_SIZE, bufsize-TOKEN_HEADER_SIZE-rrc);
-
- // copy the bytes specified by rrc count
- System.arraycopy(in_bytes, offset, out_bytes,
- bufsize-TOKEN_HEADER_SIZE-rrc, rrc);
-
- // debug("\nRotate left: (after rotation) out_bytes = [ " +
- // getHexBytes(out_bytes, 0, bufsize) + "]");
- return true;
+ tokenData = newBytes;
}
- return false;
}
public final int getSequenceNumber() {
- return (readBigEndian(seqNumberData, 0, 4));
+ return seqNumber;
}
/**
@@ -444,44 +462,25 @@
this.cipherHelper = context.getCipherHelper(null);
// debug("In MessageToken.Cons");
-
- // draft-ietf-krb-wg-gssapi-cfx-07
- this.tokenId = tokenId;
}
/**
- * Encodes a GSSHeader and this token onto an OutputStream.
+ * Encodes a MessageTokenHeader onto an OutputStream.
*
* @param os the OutputStream to which this should be written
- * @throws GSSException if an error occurs while writing to the OutputStream
+ * @throws IOException is an error occurs while writing to the OutputStream
*/
- public void encode(OutputStream os) throws IOException, GSSException {
- // debug("Writing tokenHeader " + getHexBytes(tokenHeader.getBytes());
- // (16 bytes of token header that includes sequence Number)
+ protected void encodeHeader(OutputStream os) throws IOException {
tokenHeader.encode(os);
- // debug("Writing checksum: " + getHexBytes(checksum));
- if (tokenId == MIC_ID_v2) {
- os.write(checksum);
- }
}
/**
- * Obtains the size of this token. Note that this excludes the size of
- * the GSSHeader.
- * @return token size
+ * Encodes a MessageToken_v2 onto an OutputStream.
+ *
+ * @param os the OutputStream to which this should be written
+ * @throws IOException is an error occurs while encoding the token
*/
- protected int getKrb5TokenSize() throws GSSException {
- return getTokenSize();
- }
-
- protected final int getTokenSize() throws GSSException {
- return (TOKEN_HEADER_SIZE + cipherHelper.getChecksumLength());
- }
-
- protected static final int getTokenSize(CipherHelper ch)
- throws GSSException {
- return (TOKEN_HEADER_SIZE + ch.getChecksumLength());
- }
+ public abstract void encode(OutputStream os) throws IOException;
protected final byte[] getTokenHeader() {
return (tokenHeader.getBytes());
@@ -493,45 +492,14 @@
/**
* This inner class represents the initial portion of the message token.
- * It constitutes the first 16 bytes of the message token:
- * <pre>
- * Wrap Tokens
- *
- * Octet no Name Description
- * ---------------------------------------------------------------
- * 0..1 TOK_ID Identification field. Tokens emitted by
- * GSS_Wrap() contain the the hex value 05 04
- * expressed in big endian order in this field.
- * 2 Flags Attributes field, as described in section
- * 4.2.2.
- * 3 Filler Contains the hex value FF.
- * 4..5 EC Contains the "extra count" field, in big
- * endian order as described in section 4.2.3.
- * 6..7 RRC Contains the "right rotation count" in big
- * endian order, as described in section 4.2.5.
- * 8..15 SND_SEQ Sequence number field in clear text,
- * expressed in big endian order.
- *
- * MIC Tokens
- *
- * Octet no Name Description
- * -----------------------------------------------------------------
- * 0..1 TOK_ID Identification field. Tokens emitted by
- * GSS_GetMIC() contain the hex value 04 04
- * expressed in big endian order in this field.
- * 2 Flags Attributes field, as described in section
- * 4.2.2.
- * 3..7 Filler Contains five octets of hex value FF.
- * 8..15 SND_SEQ Sequence number field in clear text,
- * expressed in big endian order.
- * </pre>
+ * It constitutes the first 16 bytes of the message token.
*/
class MessageTokenHeader {
private int tokenId;
private byte[] bytes = new byte[TOKEN_HEADER_SIZE];
- // new token header draft-ietf-krb-wg-gssapi-cfx-07
+ // Writes a new token header
public MessageTokenHeader(int tokenId, boolean conf,
boolean have_acceptor_subkey) throws GSSException {
@@ -542,16 +510,15 @@
// Flags (Note: MIT impl requires subkey)
int flags = 0;
- flags = ((initiator ? 0 : FLAG_SENDER_IS_ACCEPTOR) |
+ flags = (initiator ? 0 : FLAG_SENDER_IS_ACCEPTOR) |
((conf && tokenId != MIC_ID_v2) ?
FLAG_WRAP_CONFIDENTIAL : 0) |
- (have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
+ (have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0);
bytes[2] = (byte) flags;
// filler
bytes[3] = (byte) FILLER;
- // EC and RRC fields
if (tokenId == WRAP_ID_v2) {
// EC field
bytes[4] = (byte) 0;
@@ -560,21 +527,19 @@
bytes[6] = (byte) 0;
bytes[7] = (byte) 0;
} else if (tokenId == MIC_ID_v2) {
- // octets of filler FF
+ // more filler for MicToken
for (int i = 4; i < 8; i++) {
bytes[i] = (byte) FILLER;
}
}
- // Calculate SND_SEQ
- seqNumberData = new byte[8];
- writeBigEndian(seqNumber, seqNumberData, 4);
- System.arraycopy(seqNumberData, 0, bytes, 8, 8);
+ // Calculate SND_SEQ, only write 4 bytes from the 12th position
+ writeBigEndian(seqNumber, bytes, 12);
}
/**
- * Constructs a MessageTokenHeader by reading it from an InputStream
- * and sets the appropriate confidentiality and quality of protection
+ * Reads a MessageTokenHeader from an InputStream and sets the
+ * appropriate confidentiality and quality of protection
* values in a MessageProp structure.
*
* @param is the InputStream to read from
@@ -588,15 +553,23 @@
readFully(is, bytes, 0, TOKEN_HEADER_SIZE);
tokenId = readInt(bytes, TOKEN_ID_POS);
+ // validate Token ID
+ if (tokenId != tokId) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+ getTokenName(tokenId) + ":" + "Defective Token ID!");
+ }
+
/*
* Validate new GSS TokenHeader
*/
- // valid acceptor_flag is set
+
+ // valid acceptor_flag
+ // If I am initiator, the received token should have ACCEPTOR on
int acceptor_flag = (initiator ? FLAG_SENDER_IS_ACCEPTOR : 0);
int flag = bytes[TOKEN_FLAG_POS] & FLAG_SENDER_IS_ACCEPTOR;
- if (!(flag == acceptor_flag)) {
+ if (flag != acceptor_flag) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
- getTokenName(tokenId) + ":" + "Acceptor Flag Missing!");
+ getTokenName(tokenId) + ":" + "Acceptor Flag Error!");
}
// check for confidentiality
@@ -608,21 +581,20 @@
prop.setPrivacy(false);
}
- // validate Token ID
- if (tokenId != tokId) {
- throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
- getTokenName(tokenId) + ":" + "Defective Token ID!");
- }
+ if (tokenId == WRAP_ID_v2) {
+ // validate filler
+ if ((bytes[3] & 0xff) != FILLER) {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+ getTokenName(tokenId) + ":" + "Defective Token Filler!");
+ }
- // validate filler
- if ((bytes[3] & 0xff) != FILLER) {
- throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
- getTokenName(tokenId) + ":" + "Defective Token Filler!");
- }
+ // read EC field
+ ec = readBigEndian(bytes, TOKEN_EC_POS, 2);
- // validate next 4 bytes of filler for MIC tokens
- if (tokenId == MIC_ID_v2) {
- for (int i = 4; i < 8; i++) {
+ // read RRC field
+ rrc = readBigEndian(bytes, TOKEN_RRC_POS, 2);
+ } else if (tokenId == MIC_ID_v2) {
+ for (int i = 3; i < 8; i++) {
if ((bytes[i] & 0xff) != FILLER) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN,
-1, getTokenName(tokenId) + ":" +
@@ -631,18 +603,11 @@
}
}
- // read EC field
- ec = readBigEndian(bytes, TOKEN_EC_POS, 2);
-
- // read RRC field
- rrc = readBigEndian(bytes, TOKEN_RRC_POS, 2);
-
// set default QOP
prop.setQOP(0);
// sequence number
- seqNumberData = new byte[8];
- System.arraycopy(bytes, 8, seqNumberData, 0, 8);
+ seqNumber = readBigEndian(bytes, 0, 8);
}
/**
--- a/jdk/src/share/classes/sun/security/jgss/krb5/MicToken_v2.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/MicToken_v2.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,12 +29,11 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/**
* 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 }
* where HMAC is on { plaintext | 16-byte token-header }
@@ -48,12 +47,11 @@
byte[] tokenBytes, int tokenOffset, int tokenLen,
MessageProp prop) throws GSSException {
super(Krb5Token.MIC_ID_v2, context,
- tokenBytes, tokenOffset, tokenLen, prop);
+ tokenBytes, tokenOffset, tokenLen, prop);
}
- public MicToken_v2(Krb5Context context,
- InputStream is, MessageProp prop)
- throws GSSException {
+ public MicToken_v2(Krb5Context context, InputStream is, MessageProp prop)
+ throws GSSException {
super(Krb5Token.MIC_ID_v2, context, is, prop);
}
@@ -64,7 +62,6 @@
}
public void verify(InputStream data) throws GSSException {
-
byte[] dataBytes = null;
try {
dataBytes = new byte[data.available()];
@@ -79,7 +76,7 @@
public MicToken_v2(Krb5Context context, MessageProp prop,
byte[] data, int pos, int len)
- throws GSSException {
+ throws GSSException {
super(Krb5Token.MIC_ID_v2, context);
// debug("Application data to MicToken verify is [" +
@@ -89,7 +86,7 @@
}
public MicToken_v2(Krb5Context context, MessageProp prop, InputStream data)
- throws GSSException, IOException {
+ throws GSSException, IOException {
super(Krb5Token.MIC_ID_v2, context);
byte[] dataBytes = new byte[data.available()];
@@ -101,22 +98,21 @@
genSignAndSeqNumber(prop, dataBytes, 0, dataBytes.length);
}
- public int encode(byte[] outToken, int offset)
- throws IOException, GSSException {
-
- // Token is small
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- super.encode(bos);
- byte[] token = bos.toByteArray();
- System.arraycopy(token, 0, outToken, offset, token.length);
- return token.length;
- }
-
- public byte[] encode() throws IOException, GSSException {
-
+ public byte[] encode() throws IOException {
// XXX Fine tune this initial size
ByteArrayOutputStream bos = new ByteArrayOutputStream(50);
encode(bos);
return bos.toByteArray();
}
+
+ public int encode(byte[] outToken, int offset) throws IOException {
+ byte[] token = encode();
+ System.arraycopy(token, 0, outToken, offset, token.length);
+ return token.length;
+ }
+
+ public void encode(OutputStream os) throws IOException {
+ encodeHeader(os);
+ os.write(checksum);
+ }
}
--- a/jdk/src/share/classes/sun/security/jgss/krb5/WrapToken.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/WrapToken.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,14 +27,11 @@
import org.ietf.jgss.*;
import sun.security.jgss.*;
-import java.security.GeneralSecurityException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import sun.security.krb5.Confounder;
-import sun.security.krb5.KrbException;
/**
* This class represents a token emitted by the GSSContext.wrap()
@@ -336,24 +333,29 @@
// debug("\t\tNo encryption was performed by peer.\n");
readFully(is, confounder);
- // Data is always a multiple of 8 with this GSS Mech
- // Copy all but last block as they are
- int numBlocks = (dataSize - CONFOUNDER_SIZE)/8 - 1;
- int offset = dataBufOffset;
- for (int i = 0; i < numBlocks; i++) {
- readFully(is, dataBuf, offset, 8);
- offset += 8;
- }
+ if (cipherHelper.isArcFour()) {
+ padding = pads[1];
+ readFully(is, dataBuf, dataBufOffset, dataSize-CONFOUNDER_SIZE-1);
+ } else {
+ // Data is always a multiple of 8 with this GSS Mech
+ // Copy all but last block as they are
+ 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);
+ byte[] finalBlock = new byte[8];
+ readFully(is, finalBlock);
- int padSize = finalBlock[7];
- padding = pads[padSize];
+ int padSize = finalBlock[7];
+ padding = pads[padSize];
- // debug("\t\tPadding applied was: " + padSize + "\n");
- System.arraycopy(finalBlock, 0, dataBuf, offset,
- finalBlock.length - padSize);
+ // debug("\t\tPadding applied was: " + padSize + "\n");
+ System.arraycopy(finalBlock, 0, dataBuf, offset,
+ finalBlock.length - padSize);
+ }
}
} catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
--- a/jdk/src/share/classes/sun/security/jgss/krb5/WrapToken_v2.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/WrapToken_v2.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,66 +27,30 @@
import org.ietf.jgss.*;
import sun.security.jgss.*;
-import java.security.GeneralSecurityException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
import sun.security.krb5.Confounder;
-import sun.security.krb5.KrbException;
/**
- * This class represents the new format of GSS tokens, as specified in
- * draft-ietf-krb-wg-gssapi-cfx-07.txt, emitted by the GSSContext.wrap()
- * call. It is a MessageToken except that it also contains plaintext or
- * encrypted data at the end. A WrapToken has certain other rules that are
- * peculiar to it and different from a MICToken, which is another type of
- * MessageToken. All data in a WrapToken is prepended by a random counfounder
- * of 16 bytes. Thus, all application data is replaced by
- * (confounder || data || tokenHeader || checksum).
+ * This class represents the new format of GSS tokens, as specified in RFC
+ * 4121, emitted by the GSSContext.wrap() call. It is a MessageToken except
+ * that it also contains plaintext or encrypted data at the end. A WrapToken
+ * has certain other rules that are peculiar to it and different from a
+ * MICToken, which is another type of MessageToken. All data in a WrapToken is
+ * prepended by a random confounder of 16 bytes. Thus, all application data
+ * is replaced by (confounder || data || tokenHeader || checksum).
*
* @author Seema Malkani
*/
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
byte[] confounder = null;
- private boolean privacy = false;
- private boolean initiator = true;
+ private final boolean privacy;
/**
* Constructs a WrapToken from token bytes obtained from the
@@ -104,30 +68,9 @@
byte[] tokenBytes, int tokenOffset, int tokenLen,
MessageProp prop) throws GSSException {
- // Just parse the MessageToken part first
super(Krb5Token.WRAP_ID_v2, context,
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();
-
- dataSize = tokenLen - TOKEN_HEADER_SIZE;
-
- // save initiator
- this.initiator = context.isInitiator();
-
}
/**
@@ -145,27 +88,8 @@
InputStream is, MessageProp prop)
throws GSSException {
- // Just parse the MessageToken part first
super(Krb5Token.WRAP_ID_v2, context, is, prop);
-
- // Will need the token bytes again when extracting data
- this.is = is;
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 @@
*/
public byte[] getData() throws GSSException {
- byte[] temp = new byte[dataSize];
+ byte[] temp = new byte[tokenDataLen];
int len = getData(temp, 0);
- // len obtained is after removing confounder, tokenHeader and HMAC
-
- byte[] retVal = new byte[len];
- System.arraycopy(temp, 0, retVal, 0, retVal.length);
- return retVal;
+ return Arrays.copyOf(temp, len);
}
/**
@@ -200,69 +120,26 @@
public int getData(byte[] dataBuf, int dataBufOffset)
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 [" +
// getHexBytes(tokenBytes, tokenOffset, tokenLen) + "]\n");
- confounder = new byte[CONFOUNDER_SIZE];
// Do decryption if this token was privacy protected.
if (privacy) {
// decrypt data
- cipherHelper.decryptData(this, tokenBytes, dataPos, dataSize,
+ cipherHelper.decryptData(this, tokenData, 0, tokenDataLen,
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();
+ return tokenDataLen - CONFOUNDER_SIZE -
+ TOKEN_HEADER_SIZE - cipherHelper.getChecksumLength();
} else {
// 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_length = dataSize - cipherHelper.getChecksumLength();
- System.arraycopy(tokenBytes, dataPos,
+ int data_length = tokenDataLen - cipherHelper.getChecksumLength();
+ System.arraycopy(tokenData, 0,
dataBuf, dataBufOffset,
data_length);
// debug("\t\tData is: " + getHexBytes(dataBuf, data_length));
@@ -274,95 +151,26 @@
throw new GSSException(GSSException.BAD_MIC, -1,
"Corrupt checksum in Wrap token");
}
+ return data_length;
}
}
/**
- * Helper routine to obtain the application data transmitted in
- * 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
+ * Writes a WrapToken_v2 object
*/
- 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,
byte[] dataBytes, int dataOffset, int dataLen)
- throws GSSException {
+ throws GSSException {
super(Krb5Token.WRAP_ID_v2, context);
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 [" +
// getHexBytes(confounder) + " " +
// getHexBytes(dataBytes, dataOffset, dataLen) + "]\n");
- genSignAndSeqNumber(prop,
- dataBytes, dataOffset, dataLen);
+ genSignAndSeqNumber(prop, dataBytes, dataOffset, dataLen);
/*
* If the application decides to ask for privacy when the context
@@ -374,110 +182,42 @@
prop.setPrivacy(false);
privacy = prop.getPrivacy();
- }
- public void encode(OutputStream os) throws IOException, GSSException {
-
- super.encode(os);
-
- // debug("\n\nWriting 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));
- os.write(dataBytes, dataOffset, dataLen);
-
- // write HMAC
- // debug(" " + getHexBytes(checksum,
- // cipherHelper.getChecksumLength()));
- os.write(checksum);
-
+ tokenData = new byte[dataLen + checksum.length];
+ System.arraycopy(dataBytes, dataOffset, tokenData, 0, dataLen);
+ System.arraycopy(checksum, 0, tokenData, dataLen, checksum.length);
} else {
-
// Wrap Tokens (with confidentiality) =
// { 16 byte token_header |
// Encrypt(16-byte confounder | plaintext | token_header) |
// 12-byte HMAC }
- cipherHelper.encryptData(this, confounder, getTokenHeader(),
- dataBytes, dataOffset, dataLen, getKeyUsage(), os);
-
+ tokenData = cipherHelper.encryptData(this, confounder, getTokenHeader(),
+ dataBytes, dataOffset, dataLen, getKeyUsage());
}
- // debug("]\n");
}
- public byte[] encode() throws IOException, GSSException {
- // XXX Fine tune this initial size
- ByteArrayOutputStream bos = new ByteArrayOutputStream(dataSize + 50);
+ public void encode(OutputStream os) throws IOException {
+ encodeHeader(os);
+ os.write(tokenData);
+ }
+
+ public byte[] encode() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(
+ MessageToken_v2.TOKEN_HEADER_SIZE + tokenData.length);
encode(bos);
return bos.toByteArray();
}
- public int encode(byte[] outToken, int offset)
- throws IOException, GSSException {
-
- int retVal = 0;
-
- // 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 {
- return (getTokenSize() + dataSize);
+ public int encode(byte[] outToken, int offset) throws IOException {
+ byte[] token = encode();
+ System.arraycopy(token, 0, outToken, offset, token.length);
+ return token.length;
}
// This implementation is way to conservative. And it certainly
@@ -485,6 +225,7 @@
static int getSizeLimit(int qop, boolean confReq, int maxTokenSize,
CipherHelper ch) throws GSSException {
return (GSSHeader.getMaxMechTokenSize(OID, maxTokenSize) -
- (getTokenSize(ch) + CONFOUNDER_SIZE) - 8 /* safety */);
+ (TOKEN_HEADER_SIZE + ch.getChecksumLength() + CONFOUNDER_SIZE)
+ - 8 /* safety */);
}
}
--- a/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,34 @@
* @test
* @bug 6706974
* @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;
@@ -39,6 +67,7 @@
*/
public class BasicKrb5Test {
+ private static boolean conf = true;
/**
* @param args empty or etype
*/
@@ -46,8 +75,10 @@
throws Exception {
String etype = null;
- if (args.length > 0) {
- etype = args[0];
+ for (String arg: args) {
+ 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
@@ -56,8 +87,9 @@
System.out.println("Testing etype " + etype);
if (etype != null && !EType.isSupported(Config.getInstance().getType(etype))) {
+ // aes256 is not enabled on all systems
System.out.println("Not supported.");
- System.exit(0);
+ return;
}
new BasicKrb5Test().go(OneKDC.SERVER, OneKDC.BACKEND);
@@ -71,6 +103,7 @@
c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
c.x().requestCredDeleg(true);
+ c.x().requestConf(conf);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
c.status();
@@ -90,6 +123,7 @@
s = null;
s2.startAsClient(backend, GSSUtil.GSS_KRB5_MECH_OID);
+ s2.x().requestConf(conf);
b.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
s2.status();
--- a/jdk/test/sun/security/krb5/auto/Context.java Thu Dec 16 20:52:09 2010 +0530
+++ b/jdk/test/sun/security/krb5/auto/Context.java Fri Dec 17 11:03:33 2010 +0800
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,8 @@
import com.sun.security.jgss.ExtendedGSSContext;
import com.sun.security.jgss.InquireType;
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.
@@ -78,6 +79,8 @@
private String name;
private GSSCredential cred; // see static method delegated().
+ static boolean usingStream = false;
+
private Context() {}
/**
@@ -365,7 +368,14 @@
public byte[] run(Context me, byte[] dummy) throws Exception {
System.out.println("wrap");
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));
return out;
}
@@ -375,27 +385,46 @@
@Override
public byte[] run(Context me, byte[] input) throws Exception {
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))
throw new Exception("wrap/unwrap mismatch");
System.out.println("unwrap");
System.out.println(printProp(p1));
p1 = new MessageProp(0, true);
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));
return bytes;
}
}, t);
+
// Re-unwrap should make p2.isDuplicateToken() returns true
s1.doAs(new Action() {
@Override
public byte[] run(Context me, byte[] input) throws Exception {
MessageProp p1 = new MessageProp(0, true);
System.out.println("verifyMIC");
- me.x.verifyMIC(input, 0, input.length,
- messageBytes, 0, messageBytes.length,
- p1);
+ if (usingStream) {
+ me.x.verifyMIC(new ByteArrayInputStream(input),
+ new ByteArrayInputStream(messageBytes), p1);
+ } else {
+ me.x.verifyMIC(input, 0, input.length,
+ messageBytes, 0, messageBytes.length,
+ p1);
+ }
System.out.println(printProp(p1));
return null;
}
@@ -416,7 +445,9 @@
sb.append(prop.isGapToken()?"gap, ":"");
sb.append(prop.isOldToken()?"old, ":"");
sb.append(prop.isUnseqToken()?"unseq, ":"");
- sb.append(prop.getMinorString()+ "(" + prop.getMinorStatus()+")");
+ if (prop.getMinorStatus() != 0) {
+ sb.append(prop.getMinorString()+ "(" + prop.getMinorStatus()+")");
+ }
return sb.toString();
}
@@ -442,7 +473,13 @@
return null;
} else {
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);
@@ -460,7 +497,13 @@
return null;
} else {
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);
--- a/jdk/test/sun/security/krb5/auto/basic.sh Thu Dec 16 20:52:09 2010 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#
-# 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