0N/A/*
2362N/A * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.jgss.krb5;
0N/A
0N/Aimport org.ietf.jgss.*;
0N/Aimport sun.security.jgss.*;
0N/Aimport sun.security.krb5.*;
0N/Aimport java.io.InputStream;
0N/Aimport java.io.OutputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.ByteArrayInputStream;
0N/Aimport java.security.GeneralSecurityException;
0N/Aimport java.security.MessageDigest;
0N/A
0N/A/**
0N/A * This class is a base class for other token definitions that pertain to
0N/A * per-message GSS-API calls. Conceptually GSS-API has two types of
0N/A * per-message tokens: WrapToken and MicToken. They differ in the respect
0N/A * that a WrapToken carries additional plaintext or ciphertext application
0N/A * data besides just the sequence number and checksum. This class
0N/A * encapsulates the commonality in the structure of the WrapToken and the
0N/A * MicToken. This structure can be represented as:
0N/A * <p>
0N/A * <pre>
0N/A * 0..1 TOK_ID Identification field.
0N/A * 01 01 - Mic token
0N/A * 02 01 - Wrap token
0N/A * 2..3 SGN_ALG Checksum algorithm indicator.
0N/A * 00 00 - DES MAC MD5
0N/A * 01 00 - MD2.5
0N/A * 02 00 - DES MAC
0N/A * 04 00 - HMAC SHA1 DES3-KD
0N/A * 11 00 - RC4-HMAC
0N/A * 4..5 SEAL_ALG ff ff - none
0N/A * 00 00 - DES
0N/A * 02 00 - DES3-KD
0N/A * 10 00 - RC4-HMAC
0N/A * 6..7 Filler Contains ff ff
0N/A * 8..15 SND_SEQ Encrypted sequence number field.
0N/A * 16..s+15 SGN_CKSUM Checksum of plaintext padded data,
0N/A * calculated according to algorithm
0N/A * specified in SGN_ALG field.
0N/A * s+16..last Data encrypted or plaintext padded data
0N/A * </pre>
0N/A * Where "s" indicates the size of the checksum.
0N/A * <p>
0N/A * As always, this is preceeded by a GSSHeader.
0N/A *
0N/A * @author Mayank Upadhyay
0N/A * @author Ram Marti
0N/A * @see sun.security.jgss.GSSHeader
0N/A */
0N/A
0N/Aabstract class MessageToken extends Krb5Token {
0N/A /* Fields in header minus checksum size */
0N/A private static final int TOKEN_NO_CKSUM_SIZE = 16;
0N/A
0N/A /**
0N/A * Filler data as defined in the specification of the Kerberos v5 GSS-API
0N/A * Mechanism.
0N/A */
0N/A private static final int FILLER = 0xffff;
0N/A
0N/A // Signing algorithm values (for the SNG_ALG field)
0N/A
0N/A // From RFC 1964
0N/A /* Use a DES MAC MD5 checksum */
0N/A static final int SGN_ALG_DES_MAC_MD5 = 0x0000;
0N/A
0N/A /* Use DES MAC checksum. */
0N/A static final int SGN_ALG_DES_MAC = 0x0200;
0N/A
0N/A // From draft-raeburn-cat-gssapi-krb5-3des-00
0N/A /* Use a HMAC SHA1 DES3 -KD checksum */
0N/A static final int SGN_ALG_HMAC_SHA1_DES3_KD = 0x0400;
0N/A
0N/A // Sealing algorithm values (for the SEAL_ALG field)
0N/A
0N/A // RFC 1964
0N/A /**
0N/A * A value for the SEAL_ALG field that indicates that no encryption was
0N/A * used.
0N/A */
0N/A static final int SEAL_ALG_NONE = 0xffff;
0N/A /* Use DES CBC encryption algorithm. */
0N/A static final int SEAL_ALG_DES = 0x0000;
0N/A
0N/A // From draft-raeburn-cat-gssapi-krb5-3des-00
0N/A /**
0N/A * Use DES3-KD sealing algorithm. (draft-raeburn-cat-gssapi-krb5-3des-00)
0N/A * This algorithm uses triple-DES with key derivation, with a usage
0N/A * value KG_USAGE_SEAL. Padding is still to 8-byte multiples, and the
0N/A * IV for encrypting application data is zero.
0N/A */
0N/A static final int SEAL_ALG_DES3_KD = 0x0200;
0N/A
0N/A // draft draft-brezak-win2k-krb-rc4-hmac-04.txt
0N/A static final int SEAL_ALG_ARCFOUR_HMAC = 0x1000;
0N/A static final int SGN_ALG_HMAC_MD5_ARCFOUR = 0x1100;
0N/A
0N/A private static final int TOKEN_ID_POS = 0;
0N/A private static final int SIGN_ALG_POS = 2;
0N/A private static final int SEAL_ALG_POS = 4;
0N/A
0N/A private int seqNumber;
0N/A
0N/A private boolean confState = true;
0N/A private boolean initiator = true;
0N/A
0N/A private int tokenId = 0;
0N/A private GSSHeader gssHeader = null;
0N/A private MessageTokenHeader tokenHeader = null;
0N/A private byte[] checksum = null;
0N/A private byte[] encSeqNumber = null;
0N/A private byte[] seqNumberData = null;
0N/A
0N/A /* cipher instance used by the corresponding GSSContext */
0N/A CipherHelper cipherHelper = null;
0N/A
0N/A
0N/A /**
0N/A * Constructs a MessageToken from a byte array. If there are more bytes
0N/A * in the array than needed, the extra bytes are simply ignroed.
0N/A *
0N/A * @param tokenId the token id that should be contained in this token as
0N/A * it is read.
0N/A * @param context the Kerberos context associated with this token
0N/A * @param tokenBytes the byte array containing the token
0N/A * @param tokenOffset the offset where the token begins
0N/A * @param tokenLen the length of the token
0N/A * @param prop the MessageProp structure in which the properties of the
0N/A * token should be stored.
0N/A * @throws GSSException if there is a problem parsing the token
0N/A */
0N/A MessageToken(int tokenId, Krb5Context context,
0N/A byte[] tokenBytes, int tokenOffset, int tokenLen,
0N/A MessageProp prop) throws GSSException {
0N/A this(tokenId, context,
0N/A new ByteArrayInputStream(tokenBytes, tokenOffset, tokenLen),
0N/A prop);
0N/A }
0N/A
0N/A /**
0N/A * Constructs a MessageToken from an InputStream. Bytes will be read on
0N/A * demand and the thread might block if there are not enough bytes to
0N/A * complete the token.
0N/A *
0N/A * @param tokenId the token id that should be contained in this token as
0N/A * it is read.
0N/A * @param context the Kerberos context associated with this token
0N/A * @param is the InputStream from which to read
0N/A * @param prop the MessageProp structure in which the properties of the
0N/A * token should be stored.
0N/A * @throws GSSException if there is a problem reading from the
0N/A * InputStream or parsing the token
0N/A */
0N/A MessageToken(int tokenId, Krb5Context context, InputStream is,
0N/A MessageProp prop) throws GSSException {
0N/A init(tokenId, context);
0N/A
0N/A try {
0N/A gssHeader = new GSSHeader(is);
0N/A
0N/A if (!gssHeader.getOid().equals(OID)) {
0N/A throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
0N/A getTokenName(tokenId));
0N/A }
0N/A if (!confState) {
0N/A prop.setPrivacy(false);
0N/A }
0N/A
0N/A tokenHeader = new MessageTokenHeader(is, prop);
0N/A
0N/A encSeqNumber = new byte[8];
0N/A readFully(is, encSeqNumber);
0N/A
0N/A // debug("\n\tRead EncSeq#=" +
0N/A // getHexBytes(encSeqNumber, encSeqNumber.length));
0N/A
0N/A checksum = new byte[cipherHelper.getChecksumLength()];
0N/A readFully(is, checksum);
0N/A
0N/A // debug("\n\tRead checksum=" +
0N/A // getHexBytes(checksum, checksum.length));
0N/A // debug("\nLeaving MessageToken.Cons\n");
0N/A
0N/A } catch (IOException e) {
0N/A throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
0N/A getTokenName(tokenId) + ":" + e.getMessage());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Used to obtain the GSSHeader that was at the start of this
0N/A * token.
0N/A */
0N/A public final GSSHeader getGSSHeader() {
0N/A return gssHeader;
0N/A }
0N/A
0N/A /**
0N/A * Used to obtain the token id that was contained in this token.
0N/A * @return the token id in the token
0N/A */
0N/A public final int getTokenId() {
0N/A return tokenId;
0N/A }
0N/A
0N/A /**
0N/A * Used to obtain the encrypted sequence number in this token.
0N/A * @return the encrypted sequence number in the token
0N/A */
0N/A public final byte[] getEncSeqNumber() {
0N/A return encSeqNumber;
0N/A }
0N/A
0N/A /**
0N/A * Used to obtain the checksum that was contained in this token.
0N/A * @return the checksum in the token
0N/A */
0N/A public final byte[] getChecksum() {
0N/A return checksum;
0N/A }
0N/A
0N/A /**
0N/A * Used to determine if this token contains any encrypted data.
0N/A * @return true if it contains any encrypted data, false if there is only
0N/A * plaintext data or if there is no data.
0N/A */
0N/A public final boolean getConfState() {
0N/A return confState;
0N/A }
0N/A
0N/A /**
0N/A * Generates the checksum field and the encrypted sequence number
0N/A * field. The encrypted sequence number uses the 8 bytes of the checksum
0N/A * as an initial vector in a fixed DesCbc algorithm.
0N/A *
0N/A * @param prop the MessageProp structure that determines what sort of
0N/A * checksum and sealing algorithm should be used. The lower byte
0N/A * of qop determines the checksum algorithm while the upper byte
0N/A * determines the signing algorithm.
0N/A * Checksum values are:
0N/A * 0 - default (DES_MAC)
0N/A * 1 - MD5
0N/A * 2 - DES_MD5
0N/A * 3 - DES_MAC
0N/A * 4 - HMAC_SHA1
0N/A * Sealing values are:
0N/A * 0 - default (DES)
0N/A * 1 - DES
0N/A * 2 - DES3-KD
0N/A *
0N/A * @param optionalHeader an optional header that will be processed first
0N/A * during checksum calculation
0N/A *
0N/A * @param data the application data to checksum
0N/A * @param offset the offset where the data starts
0N/A * @param len the length of the data
0N/A *
0N/A * @param optionalTrailer an optional trailer that will be processed
0N/A * last during checksum calculation. e.g., padding that should be
0N/A * appended to the application data
0N/A *
0N/A * @throws GSSException if an error occurs in the checksum calculation or
0N/A * encryption sequence number calculation.
0N/A */
0N/A public void genSignAndSeqNumber(MessageProp prop,
0N/A byte[] optionalHeader,
0N/A byte[] data, int offset, int len,
0N/A byte[] optionalTrailer)
0N/A throws GSSException {
0N/A
0N/A // debug("Inside MessageToken.genSignAndSeqNumber:\n");
0N/A
0N/A int qop = prop.getQOP();
0N/A if (qop != 0) {
0N/A qop = 0;
0N/A prop.setQOP(qop);
0N/A }
0N/A
0N/A if (!confState) {
0N/A prop.setPrivacy(false);
0N/A }
0N/A
0N/A // Create a token header with the correct sign and seal algorithm
0N/A // values.
0N/A tokenHeader =
0N/A new MessageTokenHeader(tokenId, prop.getPrivacy(), qop);
0N/A
0N/A // Calculate SGN_CKSUM
0N/A
0N/A checksum =
0N/A getChecksum(optionalHeader, data, offset, len, optionalTrailer);
0N/A
0N/A // debug("\n\tCalc checksum=" +
0N/A // getHexBytes(checksum, checksum.length));
0N/A
0N/A // Calculate SND_SEQ
0N/A
0N/A seqNumberData = new byte[8];
0N/A
0N/A // When using this RC4 based encryption type, the sequence number is
0N/A // always sent in big-endian rather than little-endian order.
0N/A if (cipherHelper.isArcFour()) {
0N/A writeBigEndian(seqNumber, seqNumberData);
0N/A } else {
0N/A // for all other etypes
0N/A writeLittleEndian(seqNumber, seqNumberData);
0N/A }
0N/A if (!initiator) {
0N/A seqNumberData[4] = (byte)0xff;
0N/A seqNumberData[5] = (byte)0xff;
0N/A seqNumberData[6] = (byte)0xff;
0N/A seqNumberData[7] = (byte)0xff;
0N/A }
0N/A
0N/A encSeqNumber = cipherHelper.encryptSeq(checksum, seqNumberData, 0, 8);
0N/A
0N/A // debug("\n\tCalc seqNum=" +
0N/A // getHexBytes(seqNumberData, seqNumberData.length));
0N/A // debug("\n\tCalc encSeqNum=" +
0N/A // getHexBytes(encSeqNumber, encSeqNumber.length));
0N/A }
0N/A
0N/A /**
0N/A * Verifies that the checksum field and sequence number direction bytes
0N/A * are valid and consistent with the application data.
0N/A *
0N/A * @param optionalHeader an optional header that will be processed first
0N/A * during checksum calculation.
0N/A *
0N/A * @param data the application data
0N/A * @param offset the offset where the data begins
0N/A * @param len the length of the application data
0N/A *
0N/A * @param optionalTrailer an optional trailer that will be processed last
0N/A * during checksum calculation. e.g., padding that should be appended to
0N/A * the application data
0N/A *
0N/A * @throws GSSException if an error occurs in the checksum calculation or
0N/A * encryption sequence number calculation.
0N/A */
0N/A public final boolean verifySignAndSeqNumber(byte[] optionalHeader,
0N/A byte[] data, int offset, int len,
0N/A byte[] optionalTrailer)
0N/A throws GSSException {
0N/A // debug("\tIn verifySign:\n");
0N/A
0N/A // debug("\t\tchecksum: [" + getHexBytes(checksum) + "]\n");
0N/A
0N/A byte[] myChecksum =
0N/A getChecksum(optionalHeader, data, offset, len, optionalTrailer);
0N/A
0N/A // debug("\t\tmychecksum: [" + getHexBytes(myChecksum) +"]\n");
0N/A // debug("\t\tchecksum: [" + getHexBytes(checksum) + "]\n");
0N/A
0N/A if (MessageDigest.isEqual(checksum, myChecksum)) {
0N/A
0N/A seqNumberData = cipherHelper.decryptSeq(
0N/A checksum, encSeqNumber, 0, 8);
0N/A
0N/A // debug("\t\tencSeqNumber: [" + getHexBytes(encSeqNumber)
0N/A // + "]\n");
0N/A // debug("\t\tseqNumberData: [" + getHexBytes(seqNumberData)
0N/A // + "]\n");
0N/A
0N/A /*
0N/A * The token from the initiator has direction bytes 0x00 and
0N/A * the token from the acceptor has direction bytes 0xff.
0N/A */
0N/A byte directionByte = 0;
0N/A if (initiator)
0N/A directionByte = (byte) 0xff; // Received token from acceptor
0N/A
0N/A if ((seqNumberData[4] == directionByte) &&
0N/A (seqNumberData[5] == directionByte) &&
0N/A (seqNumberData[6] == directionByte) &&
0N/A (seqNumberData[7] == directionByte))
0N/A return true;
0N/A }
0N/A
0N/A return false;
0N/A
0N/A }
0N/A
0N/A public final int getSequenceNumber() {
0N/A int sequenceNum = 0;
0N/A if (cipherHelper.isArcFour()) {
0N/A sequenceNum = readBigEndian(seqNumberData, 0, 4);
0N/A } else {
0N/A sequenceNum = readLittleEndian(seqNumberData, 0, 4);
0N/A }
0N/A return sequenceNum;
0N/A }
0N/A
0N/A /**
0N/A * Computes the checksum based on the algorithm stored in the
0N/A * tokenHeader.
0N/A *
0N/A * @param optionalHeader an optional header that will be processed first
0N/A * during checksum calculation.
0N/A *
0N/A * @param data the application data
0N/A * @param offset the offset where the data begins
0N/A * @param len the length of the application data
0N/A *
0N/A * @param optionalTrailer an optional trailer that will be processed last
0N/A * during checksum calculation. e.g., padding that should be appended to
0N/A * the application data
0N/A *
0N/A * @throws GSSException if an error occurs in the checksum calculation.
0N/A */
0N/A private byte[] getChecksum(byte[] optionalHeader,
0N/A byte[] data, int offset, int len,
0N/A byte[] optionalTrailer)
0N/A throws GSSException {
0N/A
0N/A // debug("Will do getChecksum:\n");
0N/A
0N/A /*
0N/A * For checksum calculation the token header bytes i.e., the first 8
0N/A * bytes following the GSSHeader, are logically prepended to the
0N/A * application data to bind the data to this particular token.
0N/A *
0N/A * Note: There is no such requirement wrt adding padding to the
0N/A * application data for checksumming, although the cryptographic
0N/A * algorithm used might itself apply some padding.
0N/A */
0N/A
0N/A byte[] tokenHeaderBytes = tokenHeader.getBytes();
0N/A byte[] existingHeader = optionalHeader;
0N/A byte[] checksumDataHeader = tokenHeaderBytes;
0N/A
0N/A if (existingHeader != null) {
0N/A checksumDataHeader = new byte[tokenHeaderBytes.length +
0N/A existingHeader.length];
0N/A System.arraycopy(tokenHeaderBytes, 0,
0N/A checksumDataHeader, 0, tokenHeaderBytes.length);
0N/A System.arraycopy(existingHeader, 0,
0N/A checksumDataHeader, tokenHeaderBytes.length,
0N/A existingHeader.length);
0N/A }
0N/A
0N/A return cipherHelper.calculateChecksum(tokenHeader.getSignAlg(),
0N/A checksumDataHeader, optionalTrailer, data, offset, len, tokenId);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Constructs an empty MessageToken for the local context to send to
0N/A * the peer. It also increments the local sequence number in the
0N/A * Krb5Context instance it uses after obtaining the object lock for
0N/A * it.
0N/A *
0N/A * @param tokenId the token id that should be contained in this token
0N/A * @param context the Kerberos context associated with this token
0N/A */
0N/A MessageToken(int tokenId, Krb5Context context) throws GSSException {
0N/A /*
0N/A debug("\n============================");
0N/A debug("\nMySessionKey=" +
0N/A getHexBytes(context.getMySessionKey().getBytes()));
0N/A debug("\nPeerSessionKey=" +
0N/A getHexBytes(context.getPeerSessionKey().getBytes()));
0N/A debug("\n============================\n");
0N/A */
0N/A init(tokenId, context);
0N/A this.seqNumber = context.incrementMySequenceNumber();
0N/A }
0N/A
0N/A private void init(int tokenId, Krb5Context context) throws GSSException {
0N/A this.tokenId = tokenId;
0N/A // Just for consistency check in Wrap
0N/A this.confState = context.getConfState();
0N/A
0N/A this.initiator = context.isInitiator();
0N/A
0N/A this.cipherHelper = context.getCipherHelper(null);
0N/A // debug("In MessageToken.Cons");
0N/A }
0N/A
0N/A /**
0N/A * Encodes a GSSHeader and this token onto an OutputStream.
0N/A *
0N/A * @param os the OutputStream to which this should be written
0N/A * @throws GSSException if an error occurs while writing to the OutputStream
0N/A */
0N/A public void encode(OutputStream os) throws IOException, GSSException {
0N/A gssHeader = new GSSHeader(OID, getKrb5TokenSize());
0N/A gssHeader.encode(os);
0N/A tokenHeader.encode(os);
0N/A // debug("Writing seqNumber: " + getHexBytes(encSeqNumber));
0N/A os.write(encSeqNumber);
0N/A // debug("Writing checksum: " + getHexBytes(checksum));
0N/A os.write(checksum);
0N/A }
0N/A
0N/A /**
0N/A * Obtains the size of this token. Note that this excludes the size of
0N/A * the GSSHeader.
0N/A * @return token size
0N/A */
0N/A protected int getKrb5TokenSize() throws GSSException {
0N/A return getTokenSize();
0N/A }
0N/A
0N/A protected final int getTokenSize() throws GSSException {
0N/A return TOKEN_NO_CKSUM_SIZE + cipherHelper.getChecksumLength();
0N/A }
0N/A
0N/A protected static final int getTokenSize(CipherHelper ch)
0N/A throws GSSException {
0N/A return TOKEN_NO_CKSUM_SIZE + ch.getChecksumLength();
0N/A }
0N/A
0N/A /**
0N/A * Obtains the conext key that is associated with this token.
0N/A * @return the context key
0N/A */
0N/A /*
0N/A public final byte[] getContextKey() {
0N/A return contextKey;
0N/A }
0N/A */
0N/A
0N/A /**
0N/A * Obtains the encryption algorithm that should be used in this token
0N/A * given the state of confidentiality the application requested.
0N/A * Requested qop must be consistent with negotiated session key.
0N/A * @param confRequested true if the application desired confidentiality
0N/A * on this token, false otherwise
0N/A * @param qop the qop requested by the application
0N/A * @throws GSSException if qop is incompatible with the negotiated
0N/A * session key
0N/A */
0N/A protected abstract int getSealAlg(boolean confRequested, int qop)
0N/A throws GSSException;
0N/A
0N/A // ******************************************* //
0N/A // I N N E R C L A S S E S F O L L O W
0N/A // ******************************************* //
0N/A
0N/A /**
0N/A * This inner class represents the initial portion of the message token
0N/A * and contains information about the checksum and encryption algorithms
0N/A * that are in use. It constitutes the first 8 bytes of the
0N/A * message token:
0N/A * <pre>
0N/A * 0..1 TOK_ID Identification field.
0N/A * 01 01 - Mic token
0N/A * 02 01 - Wrap token
0N/A * 2..3 SGN_ALG Checksum algorithm indicator.
0N/A * 00 00 - DES MAC MD5
0N/A * 01 00 - MD2.5
0N/A * 02 00 - DES MAC
0N/A * 04 00 - HMAC SHA1 DES3-KD
0N/A * 11 00 - RC4-HMAC
0N/A * 4..5 SEAL_ALG ff ff - none
0N/A * 00 00 - DES
0N/A * 02 00 - DES3-KD
0N/A * 10 00 - RC4-HMAC
0N/A * 6..7 Filler Contains ff ff
0N/A * </pre>
0N/A */
0N/A class MessageTokenHeader {
0N/A
0N/A private int tokenId;
0N/A private int signAlg;
0N/A private int sealAlg;
0N/A
0N/A private byte[] bytes = new byte[8];
0N/A
0N/A /**
0N/A * Constructs a MessageTokenHeader for the specified token type with
0N/A * appropriate checksum and encryption algorithms fields.
0N/A *
0N/A * @param tokenId the token id for this mesage token
0N/A * @param conf true if confidentiality will be resuested with this
0N/A * message token, false otherwise.
0N/A * @param qop the value of the quality of protection that will be
0N/A * desired.
0N/A */
0N/A public MessageTokenHeader(int tokenId, boolean conf, int qop)
0N/A throws GSSException {
0N/A
0N/A this.tokenId = tokenId;
0N/A
0N/A signAlg = MessageToken.this.getSgnAlg(qop);
0N/A
0N/A sealAlg = MessageToken.this.getSealAlg(conf, qop);
0N/A
0N/A bytes[0] = (byte) (tokenId >>> 8);
0N/A bytes[1] = (byte) (tokenId);
0N/A
0N/A bytes[2] = (byte) (signAlg >>> 8);
0N/A bytes[3] = (byte) (signAlg);
0N/A
0N/A bytes[4] = (byte) (sealAlg >>> 8);
0N/A bytes[5] = (byte) (sealAlg);
0N/A
0N/A bytes[6] = (byte) (MessageToken.FILLER >>> 8);
0N/A bytes[7] = (byte) (MessageToken.FILLER);
0N/A }
0N/A
0N/A /**
0N/A * Constructs a MessageTokenHeader by reading it from an InputStream
0N/A * and sets the appropriate confidentiality and quality of protection
0N/A * values in a MessageProp structure.
0N/A *
0N/A * @param is the InputStream to read from
0N/A * @param prop the MessageProp to populate
0N/A * @throws IOException is an error occurs while reading from the
0N/A * InputStream
0N/A */
0N/A public MessageTokenHeader(InputStream is, MessageProp prop)
0N/A throws IOException {
0N/A readFully(is, bytes);
0N/A tokenId = readInt(bytes, TOKEN_ID_POS);
0N/A signAlg = readInt(bytes, SIGN_ALG_POS);
0N/A sealAlg = readInt(bytes, SEAL_ALG_POS);
0N/A // debug("\nMessageTokenHeader read tokenId=" +
0N/A // getHexBytes(bytes) + "\n");
0N/A // XXX compare to FILLER
0N/A int temp = readInt(bytes, SEAL_ALG_POS + 2);
0N/A
0N/A // debug("SIGN_ALG=" + signAlg);
0N/A
0N/A switch (sealAlg) {
0N/A case SEAL_ALG_DES:
0N/A case SEAL_ALG_DES3_KD:
0N/A case SEAL_ALG_ARCFOUR_HMAC:
0N/A prop.setPrivacy(true);
0N/A break;
0N/A
0N/A default:
0N/A prop.setPrivacy(false);
0N/A }
0N/A
0N/A prop.setQOP(0); // default
0N/A }
0N/A
0N/A /**
0N/A * Encodes this MessageTokenHeader onto an OutputStream
0N/A * @param os the OutputStream to write to
0N/A * @throws IOException is an error occurs while writing
0N/A */
0N/A public final void encode(OutputStream os) throws IOException {
0N/A os.write(bytes);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns the token id for the message token.
0N/A * @return the token id
0N/A * @see sun.security.jgss.krb5.Krb5Token#MIC_ID
0N/A * @see sun.security.jgss.krb5.Krb5Token#WRAP_ID
0N/A */
0N/A public final int getTokenId() {
0N/A return tokenId;
0N/A }
0N/A
0N/A /**
0N/A * Returns the sign algorithm for the message token.
0N/A * @return the sign algorithm
0N/A * @see sun.security.jgss.krb5.MessageToken#SIGN_DES_MAC
0N/A * @see sun.security.jgss.krb5.MessageToken#SIGN_DES_MAC_MD5
0N/A */
0N/A public final int getSignAlg() {
0N/A return signAlg;
0N/A }
0N/A
0N/A /**
0N/A * Returns the seal algorithm for the message token.
0N/A * @return the seal algorithm
0N/A * @see sun.security.jgss.krb5.MessageToken#SEAL_ALG_DES
0N/A * @see sun.security.jgss.krb5.MessageToken#SEAL_ALG_NONE
0N/A */
0N/A public final int getSealAlg() {
0N/A return sealAlg;
0N/A }
0N/A
0N/A /**
0N/A * Returns the bytes of this header.
0N/A * @return 8 bytes that form this header
0N/A */
0N/A public final byte[] getBytes() {
0N/A return bytes;
0N/A }
0N/A } // end of class MessageTokenHeader
0N/A
0N/A
0N/A /**
0N/A * Determine signing algorithm based on QOP.
0N/A */
0N/A protected int getSgnAlg(int qop) throws GSSException {
0N/A // QOP ignored
0N/A return cipherHelper.getSgnAlg();
0N/A }
0N/A}