OpenJDK / jdk8u / jdk8u / jdk
changeset 3321:1f0f0737f04e
6975866: api/org_ietf/jgss/GSSContext/index.html#wrapUnwrapIOTest started to fail since jdk7 b102
Reviewed-by: valeriep
author | weijun |
---|---|
date | Fri, 17 Dec 2010 11:03:33 +0800 |
parents | e67a399dd4ad |
children | ae84db37130a |
files | src/share/classes/sun/security/jgss/krb5/CipherHelper.java src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java src/share/classes/sun/security/jgss/krb5/MicToken_v2.java src/share/classes/sun/security/jgss/krb5/WrapToken.java src/share/classes/sun/security/jgss/krb5/WrapToken_v2.java test/sun/security/krb5/auto/BasicKrb5Test.java test/sun/security/krb5/auto/Context.java test/sun/security/krb5/auto/basic.sh |
diffstat | 8 files changed, 344 insertions(+), 646 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/sun/security/jgss/krb5/CipherHelper.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/src/share/classes/sun/security/jgss/krb5/MicToken_v2.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/src/share/classes/sun/security/jgss/krb5/WrapToken.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/src/share/classes/sun/security/jgss/krb5/WrapToken_v2.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/test/sun/security/krb5/auto/BasicKrb5Test.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/test/sun/security/krb5/auto/Context.java Thu Dec 16 20:52:09 2010 +0530 +++ b/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/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