feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,110 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.internal.util.KerberosFlags;
import sun.security.util.*;
import java.io.IOException;
/**
* Implements the ASN.1 APOptions type.
*
* <pre>{@code
* APOptions ::= KerberosFlags
* -- reserved(0),
* -- use-session-key(1),
* -- mutual-required(2)
*
* KerberosFlags ::= BIT STRING (SIZE (32..MAX))
* -- minimum number of bits shall be sent,
* -- but no fewer than 32
*
* }</pre>
* <p>
* This definition reflects the Network Working Group RFC4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class APOptions extends KerberosFlags {
public APOptions() {
super(Krb5.AP_OPTS_MAX + 1);
}
public APOptions(int oneBit) throws Asn1Exception {
super(Krb5.AP_OPTS_MAX + 1);
set(oneBit, true);
}
public APOptions(int size, byte[] data) throws Asn1Exception {
super(size, data);
if ((size > data.length * BITS_PER_UNIT) || (size > Krb5.AP_OPTS_MAX + 1)) {
throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH);
}
}
public APOptions(boolean[] data) throws Asn1Exception {
super(data);
if (data.length > Krb5.AP_OPTS_MAX + 1) {
throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH);
}
}
public APOptions(DerValue encoding) throws IOException, Asn1Exception {
this(encoding.getUnalignedBitString(true).toBooleanArray());
}
/**
* Parse (unmarshal) an APOptions from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicate if this data field is optional.
* @return an instance of APOptions.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public static APOptions parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
} else {
DerValue subDer = der.getData().getDerValue();
return new APOptions(subDer);
}
}
}

View File

@@ -0,0 +1,141 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 AP-REP type.
*
* <pre>{@code
* AP-REP ::= [APPLICATION 15] SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (15),
* enc-part [2] EncryptedData -- EncAPRepPart
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class APRep {
public int pvno;
public int msgType;
public EncryptedData encPart;
public APRep(EncryptedData new_encPart) {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_AP_REP;
encPart = new_encPart;
}
public APRep(byte[] data) throws Asn1Exception,
KrbApErrException, IOException {
init(new DerValue(data));
}
public APRep(DerValue encoding) throws Asn1Exception,
KrbApErrException, IOException {
init(encoding);
}
/**
* Initializes an APRep object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data
* stream does not match the pre-defined value.
*/
private void init(DerValue encoding) throws Asn1Exception,
KrbApErrException, IOException {
if (((encoding.getTag() & (byte) (0x1F)) != Krb5.KRB_AP_REP)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
DerValue der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
DerValue subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) != (byte) 0x00) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) != (byte) 0x01) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != Krb5.KRB_AP_REP) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
encPart = EncryptedData.parse(der.getData(), (byte) 0x02, false);
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an APRep object.
* @return byte array of encoded APRep object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), temp);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x02), encPart.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
DerOutputStream aprep = new DerOutputStream();
aprep.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) 0x0F), temp);
return aprep.toByteArray();
}
}

View File

@@ -0,0 +1,151 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 AP-REQ type.
*
* <pre>{@code
* AP-REQ ::= [APPLICATION 14] SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (14),
* ap-options [2] APOptions,
* ticket [3] Ticket,
* authenticator [4] EncryptedData -- Authenticator
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class APReq {
public int pvno;
public int msgType;
public APOptions apOptions;
public Ticket ticket;
public EncryptedData authenticator;
public APReq(
APOptions new_apOptions,
Ticket new_ticket,
EncryptedData new_authenticator) {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_AP_REQ;
apOptions = new_apOptions;
ticket = new_ticket;
authenticator = new_authenticator;
}
public APReq(byte[] data) throws Asn1Exception, IOException, KrbApErrException, RealmException {
init(new DerValue(data));
}
public APReq(DerValue encoding) throws Asn1Exception, IOException, KrbApErrException, RealmException {
init(encoding);
}
/**
* Initializes an APReq object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data stream does not match the pre-defined value.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private void init(DerValue encoding) throws Asn1Exception,
IOException, KrbApErrException, RealmException {
DerValue der, subDer;
if (((encoding.getTag() & (byte) 0x1F) != Krb5.KRB_AP_REQ)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) != (byte) 0x00) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) != (byte) 0x01) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != Krb5.KRB_AP_REQ) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
apOptions = APOptions.parse(der.getData(), (byte) 0x02, false);
ticket = Ticket.parse(der.getData(), (byte) 0x03, false);
authenticator = EncryptedData.parse(der.getData(), (byte) 0x04, false);
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an APReq object.
* @return byte array of encoded APReq object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), temp);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x02), apOptions.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x03), ticket.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x04), authenticator.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
DerOutputStream apreq = new DerOutputStream();
apreq.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) 0x0E), temp);
return apreq.toByteArray();
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.Realm;
import sun.security.krb5.RealmException;
import sun.security.util.*;
import java.io.IOException;
public class ASRep extends KDCRep {
public ASRep(
PAData[] new_pAData,
PrincipalName new_cname,
Ticket new_ticket,
EncryptedData new_encPart) throws IOException {
super(new_pAData, new_cname, new_ticket,
new_encPart, Krb5.KRB_AS_REP);
}
public ASRep(byte[] data) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(new DerValue(data));
}
public ASRep(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding);
}
private void init(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding, Krb5.KRB_AS_REP);
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.io.IOException;
public class ASReq extends KDCReq {
public ASReq(PAData[] new_pAData, KDCReqBody new_reqBody) throws IOException {
super(new_pAData, new_reqBody, Krb5.KRB_AS_REQ);
}
public ASReq(byte[] data) throws Asn1Exception, KrbException, IOException {
init(new DerValue(data));
}
public ASReq(DerValue encoding) throws Asn1Exception, KrbException, IOException {
init(encoding);
}
private void init(DerValue encoding) throws Asn1Exception, IOException, KrbException {
super.init(encoding, Krb5.KRB_AS_REQ);
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.EncryptionKey;
import java.util.BitSet;
public class AuthContext {
public HostAddress remoteAddress;
public int remotePort;
public HostAddress localAddress;
public int localPort;
public EncryptionKey keyBlock;
public EncryptionKey localSubkey;
public EncryptionKey remoteSubkey;
public BitSet authContextFlags;
public int remoteSeqNumber;
public int localSeqNumber;
public Authenticator authenticator;
public int reqCksumType;
public int safeCksumType;
public byte[] initializationVector;
//public ReplayCache replayCache;
};

View File

@@ -0,0 +1,221 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 Authenticator type.
*
* <pre>{@code
* Authenticator ::= [APPLICATION 2] SEQUENCE {
* authenticator-vno [0] INTEGER (5),
* crealm [1] Realm,
* cname [2] PrincipalName,
* cksum [3] Checksum OPTIONAL,
* cusec [4] Microseconds,
* ctime [5] KerberosTime,
* subkey [6] EncryptionKey OPTIONAL,
* seq-number [7] UInt32 OPTIONAL,
* authorization-data [8] AuthorizationData OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class Authenticator {
public int authenticator_vno;
public PrincipalName cname;
Checksum cksum; //optional
public int cusec;
public KerberosTime ctime;
EncryptionKey subKey; //optional
Integer seqNumber; //optional
public AuthorizationData authorizationData; //optional
public Authenticator(
PrincipalName new_cname,
Checksum new_cksum,
int new_cusec,
KerberosTime new_ctime,
EncryptionKey new_subKey,
Integer new_seqNumber,
AuthorizationData new_authorizationData) {
authenticator_vno = Krb5.AUTHNETICATOR_VNO;
cname = new_cname;
cksum = new_cksum;
cusec = new_cusec;
ctime = new_ctime;
subKey = new_subKey;
seqNumber = new_seqNumber;
authorizationData = new_authorizationData;
}
public Authenticator(byte[] data)
throws Asn1Exception, IOException, KrbApErrException, RealmException {
init(new DerValue(data));
}
public Authenticator(DerValue encoding)
throws Asn1Exception, IOException, KrbApErrException, RealmException {
init(encoding);
}
/**
* Initializes an Authenticator object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data
* stream does not match the pre-defined value.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private void init(DerValue encoding)
throws Asn1Exception, IOException, KrbApErrException, RealmException {
DerValue der, subDer;
//may not be the correct error code for a tag
//mismatch on an encrypted structure
if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x02)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) != (byte) 0x00) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
authenticator_vno = subDer.getData().getBigInteger().intValue();
if (authenticator_vno != 5) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
Realm crealm = Realm.parse(der.getData(), (byte) 0x01, false);
cname = PrincipalName.parse(der.getData(), (byte) 0x02, false, crealm);
cksum = Checksum.parse(der.getData(), (byte) 0x03, true);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) == 0x04) {
cusec = subDer.getData().getBigInteger().intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
ctime = KerberosTime.parse(der.getData(), (byte) 0x05, false);
if (der.getData().available() > 0) {
subKey = EncryptionKey.parse(der.getData(), (byte) 0x06, true);
} else {
subKey = null;
seqNumber = null;
authorizationData = null;
}
if (der.getData().available() > 0) {
if ((der.getData().peekByte() & 0x1F) == 0x07) {
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x07) {
seqNumber = new Integer(subDer.getData().getBigInteger().intValue());
}
}
} else {
seqNumber = null;
authorizationData = null;
}
if (der.getData().available() > 0) {
authorizationData = AuthorizationData.parse(der.getData(), (byte) 0x08, true);
} else {
authorizationData = null;
}
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an Authenticator object.
* @return byte array of encoded Authenticator object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
Vector<DerValue> v = new Vector<>();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(authenticator_vno));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp.toByteArray()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), cname.getRealm().asn1Encode()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x02), cname.asn1Encode()));
if (cksum != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x03), cksum.asn1Encode()));
}
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(cusec));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x04), temp.toByteArray()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x05), ctime.asn1Encode()));
if (subKey != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x06), subKey.asn1Encode()));
}
if (seqNumber != null) {
temp = new DerOutputStream();
// encode as an unsigned integer (UInt32)
temp.putInteger(BigInteger.valueOf(seqNumber.longValue()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x07), temp.toByteArray()));
}
if (authorizationData != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x08), authorizationData.asn1Encode()));
}
DerValue der[] = new DerValue[v.size()];
v.copyInto(der);
temp = new DerOutputStream();
temp.putSequence(der);
DerOutputStream out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) 0x02), temp);
return out.toByteArray();
}
public final Checksum getChecksum() {
return cksum;
}
public final Integer getSeqNumber() {
return seqNumber;
}
public final EncryptionKey getSubKey() {
return subKey;
}
}

View File

@@ -0,0 +1,184 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.util.Vector;
import java.io.IOException;
import sun.security.krb5.internal.ccache.CCacheOutputStream;
/**
* In RFC4120, the ASN.1 AuthorizationData is defined as:
*
* AuthorizationData ::= SEQUENCE OF SEQUENCE {
* ad-type [0] Int32,
* ad-data [1] OCTET STRING
* }
*
* Here, two classes are used to implement it and they can be represented as follows:
*
* AuthorizationData ::= SEQUENCE OF AuthorizationDataEntry
* AuthorizationDataEntry ::= SEQUENCE {
* ad-type[0] Int32,
* ad-data[1] OCTET STRING
* }
*/
public class AuthorizationData implements Cloneable {
private AuthorizationDataEntry[] entry = null;
private AuthorizationData() {
}
public AuthorizationData(AuthorizationDataEntry[] new_entries)
throws IOException {
if (new_entries != null) {
entry = new AuthorizationDataEntry[new_entries.length];
for (int i = 0; i < new_entries.length; i++) {
if (new_entries[i] == null) {
throw new IOException("Cannot create an AuthorizationData");
} else {
entry[i] = (AuthorizationDataEntry) new_entries[i].clone();
}
}
}
}
public AuthorizationData(AuthorizationDataEntry new_entry) {
entry = new AuthorizationDataEntry[1];
entry[0] = new_entry;
}
public Object clone() {
AuthorizationData new_authorizationData =
new AuthorizationData();
if (entry != null) {
new_authorizationData.entry =
new AuthorizationDataEntry[entry.length];
for (int i = 0; i < entry.length; i++) {
new_authorizationData.entry[i] =
(AuthorizationDataEntry) entry[i].clone();
}
}
return new_authorizationData;
}
/**
* Constructs a new <code>AuthorizationData,</code> instance.
* @param der a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public AuthorizationData(DerValue der) throws Asn1Exception, IOException {
Vector<AuthorizationDataEntry> v = new Vector<>();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
while (der.getData().available() > 0) {
v.addElement(new AuthorizationDataEntry(der.getData().getDerValue()));
}
if (v.size() > 0) {
entry = new AuthorizationDataEntry[v.size()];
v.copyInto(entry);
}
}
/**
* Encodes an <code>AuthorizationData</code> object.
* @return byte array of encoded <code>AuthorizationData</code> object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerValue der[] = new DerValue[entry.length];
for (int i = 0; i < entry.length; i++) {
der[i] = new DerValue(entry[i].asn1Encode());
}
bytes.putSequence(der);
return bytes.toByteArray();
}
/**
* Parse (unmarshal) an <code>AuthorizationData</code> object from a DER input stream.
* This form of parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional
* @return an instance of AuthorizationData.
*
*/
public static AuthorizationData parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte) data.peekByte() & (byte) 0x1F) != explicitTag)) {
return null;
}
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte) 0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
} else {
DerValue subDer = der.getData().getDerValue();
return new AuthorizationData(subDer);
}
}
/**
* Writes <code>AuthorizationData</code> data fields to a output stream.
*
* @param cos a <code>CCacheOutputStream</code> to be written to.
* @exception IOException if an I/O exception occurs.
*/
public void writeAuth(CCacheOutputStream cos) throws IOException {
for (int i = 0; i < entry.length; i++) {
entry[i].writeEntry(cos);
}
}
public String toString() {
String retVal = "AuthorizationData:\n";
for (int i = 0; i < entry.length; i++) {
retVal += entry[i].toString();
}
return retVal;
}
public int count() {
return entry.length;
}
public AuthorizationDataEntry item(int i) {
return (AuthorizationDataEntry)entry[i].clone();
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import java.io.IOException;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.internal.ccache.CCacheOutputStream;
public class AuthorizationDataEntry implements Cloneable {
public int adType;
public byte[] adData;
private AuthorizationDataEntry() {
}
public AuthorizationDataEntry(
int new_adType,
byte[] new_adData) {
adType = new_adType;
adData = new_adData;
}
public Object clone() {
AuthorizationDataEntry new_authorizationDataEntry =
new AuthorizationDataEntry();
new_authorizationDataEntry.adType = adType;
if (adData != null) {
new_authorizationDataEntry.adData = new byte[adData.length];
System.arraycopy(adData, 0,
new_authorizationDataEntry.adData, 0, adData.length);
}
return new_authorizationDataEntry;
}
/**
* Constructs an instance of AuthorizationDataEntry.
* @param encoding a single DER-encoded value.
*/
public AuthorizationDataEntry(DerValue encoding) throws Asn1Exception, IOException {
DerValue der;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte) 0x1F) == (byte) 0x00) {
adType = der.getData().getBigInteger().intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte) 0x1F) == (byte) 0x01) {
adData = der.getData().getOctetString();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (encoding.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an AuthorizationDataEntry object.
* @return byte array of encoded AuthorizationDataEntry object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(adType);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp);
temp = new DerOutputStream();
temp.putOctetString(adData);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Writes the entry's data fields in FCC format to an output stream.
*
* @param cos a <code>CCacheOutputStream</code>.
* @exception IOException if an I/O exception occurs.
*/
public void writeEntry(CCacheOutputStream cos) throws IOException {
cos.write16(adType);
cos.write32(adData.length);
cos.write(adData, 0, adData.length);
}
public String toString() {
return ("adType=" + adType + " adData.length=" + adData.length);
}
}

View File

@@ -0,0 +1,561 @@
/*
* Copyright (c) 2001, 2021, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.DerValue;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
/**
* This class is a utility that contains much of the TGS-Exchange
* protocol. It is used by ../Credentials.java for service ticket
* acquisition in both the normal and the x-realm case.
*/
public class CredentialsUtil {
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
private static enum S4U2Type {
NONE, SELF, PROXY
}
/**
* Used by a middle server to acquire credentials on behalf of a
* user to itself using the S4U2self extension.
* @param user the user to impersonate
* @param ccreds the TGT of the middle service
* @return the new creds (cname=user, sname=middle)
*/
public static Credentials acquireS4U2selfCreds(PrincipalName user,
Credentials ccreds) throws KrbException, IOException {
if (!ccreds.isForwardable()) {
throw new KrbException("S4U2self needs a FORWARDABLE ticket");
}
PrincipalName sname = ccreds.getClient();
String uRealm = user.getRealmString();
String localRealm = ccreds.getClient().getRealmString();
if (!uRealm.equals(localRealm)) {
// Referrals will be required because the middle service
// and the user impersonated are on different realms.
if (Config.DISABLE_REFERRALS) {
throw new KrbException("Cross-realm S4U2Self request not" +
" possible when referrals are disabled.");
}
if (ccreds.getClientAlias() != null) {
// If the name was canonicalized, the user pick
// has preference. This gives the possibility of
// using FQDNs that KDCs may use to return referrals.
// I.e.: a SVC/host.realm-2.com@REALM-1.COM name
// may be used by REALM-1.COM KDC to return a
// referral to REALM-2.COM.
sname = ccreds.getClientAlias();
}
sname = new PrincipalName(sname.getNameType(),
sname.getNameStrings(), new Realm(uRealm));
}
Credentials creds = serviceCreds(
KDCOptions.with(KDCOptions.FORWARDABLE),
ccreds, ccreds.getClient(), sname, user,
null, new PAData[] {
new PAData(Krb5.PA_FOR_USER,
new PAForUserEnc(user,
ccreds.getSessionKey()).asn1Encode()),
new PAData(Krb5.PA_PAC_OPTIONS,
new PaPacOptions()
.setResourceBasedConstrainedDelegation(true)
.setClaims(true)
.asn1Encode())
}, S4U2Type.SELF);
if (!creds.getClient().equals(user)) {
throw new KrbException("S4U2self request not honored by KDC");
}
if (!creds.isForwardable()) {
throw new KrbException("S4U2self ticket must be FORWARDABLE");
}
return creds;
}
/**
* Used by a middle server to acquire a service ticket to a backend
* server using the S4U2proxy extension.
* @param backend the name of the backend service
* @param second the client's service ticket to the middle server
* @param ccreds the TGT of the middle server
* @return the creds (cname=client, sname=backend)
*/
public static Credentials acquireS4U2proxyCreds(
String backend, Ticket second,
PrincipalName client, Credentials ccreds)
throws KrbException, IOException {
PrincipalName backendPrincipal = new PrincipalName(backend);
String backendRealm = backendPrincipal.getRealmString();
String localRealm = ccreds.getClient().getRealmString();
if (!backendRealm.equals(localRealm)) {
// The middle service and the backend service are on
// different realms, so referrals will be required.
if (Config.DISABLE_REFERRALS) {
throw new KrbException("Cross-realm S4U2Proxy request not" +
" possible when referrals are disabled.");
}
backendPrincipal = new PrincipalName(
backendPrincipal.getNameType(),
backendPrincipal.getNameStrings(),
new Realm(localRealm));
}
Credentials creds = serviceCreds(KDCOptions.with(
KDCOptions.CNAME_IN_ADDL_TKT, KDCOptions.FORWARDABLE),
ccreds, ccreds.getClient(), backendPrincipal, null,
new Ticket[] {second}, new PAData[] {
new PAData(Krb5.PA_PAC_OPTIONS,
new PaPacOptions()
.setResourceBasedConstrainedDelegation(true)
.setClaims(true)
.asn1Encode())
}, S4U2Type.PROXY);
if (!creds.getClient().equals(client)) {
throw new KrbException("S4U2proxy request not honored by KDC");
}
return creds;
}
/**
* Acquires credentials for a specified service using initial
* credential. When the service has a different realm from the initial
* credential, we do cross-realm authentication - first, we use the
* current credential to get a cross-realm credential from the local KDC,
* then use that cross-realm credential to request service credential
* from the foreign KDC.
*
* @param service the name of service principal
* @param ccreds client's initial credential
*/
public static Credentials acquireServiceCreds(
String service, Credentials ccreds)
throws KrbException, IOException {
PrincipalName sname = new PrincipalName(service,
PrincipalName.KRB_NT_UNKNOWN);
return serviceCreds(sname, ccreds);
}
/**
* Gets a TGT to another realm
* @param localRealm this realm
* @param serviceRealm the other realm, cannot equals to localRealm
* @param ccreds TGT in this realm
* @param okAsDelegate an [out] argument to receive the okAsDelegate
* property. True only if all realms allow delegation.
* @return the TGT for the other realm, null if cannot find a path
* @throws KrbException if something goes wrong
*/
private static Credentials getTGTforRealm(String localRealm,
String serviceRealm, Credentials ccreds, boolean[] okAsDelegate)
throws KrbException {
// Get a list of realms to traverse
String[] realms = Realm.getRealmsList(localRealm, serviceRealm);
int i = 0, k = 0;
Credentials cTgt = null, newTgt = null, theTgt = null;
PrincipalName tempService = null;
String newTgtRealm = null;
okAsDelegate[0] = true;
for (cTgt = ccreds, i = 0; i < realms.length;) {
tempService = PrincipalName.tgsService(serviceRealm, realms[i]);
if (DEBUG) {
System.out.println(
">>> Credentials acquireServiceCreds: main loop: ["
+ i +"] tempService=" + tempService);
}
try {
newTgt = serviceCreds(tempService, cTgt);
} catch (Exception exc) {
newTgt = null;
}
if (newTgt == null) {
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
+ "no tgt; searching thru capath");
}
/*
* No tgt found. Let's go thru the realms list one by one.
*/
for (newTgt = null, k = i+1;
newTgt == null && k < realms.length; k++) {
tempService = PrincipalName.tgsService(realms[k], realms[i]);
if (DEBUG) {
System.out.println(
">>> Credentials acquireServiceCreds: "
+ "inner loop: [" + k
+ "] tempService=" + tempService);
}
try {
newTgt = serviceCreds(tempService, cTgt);
} catch (Exception exc) {
newTgt = null;
}
}
} // Ends 'if (newTgt == null)'
if (newTgt == null) {
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
+ "no tgt; cannot get creds");
}
break;
}
/*
* We have a tgt. It may or may not be for the target.
* If it's for the target realm, we're done looking for a tgt.
*/
newTgtRealm = newTgt.getServer().getInstanceComponent();
if (okAsDelegate[0] && !newTgt.checkDelegate()) {
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: " +
"global OK-AS-DELEGATE turned off at " +
newTgt.getServer());
}
okAsDelegate[0] = false;
}
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
+ "got tgt");
}
if (newTgtRealm.equals(serviceRealm)) {
/* We got the right tgt */
theTgt = newTgt;
break;
}
/*
* The new tgt is not for the target realm.
* See if the realm of the new tgt is in the list of realms
* and continue looking from there.
*/
for (k = i+1; k < realms.length; k++) {
if (newTgtRealm.equals(realms[k])) {
break;
}
}
if (k < realms.length) {
/*
* (re)set the counter so we start looking
* from the realm we just obtained a tgt for.
*/
i = k;
cTgt = newTgt;
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
+ "continuing with main loop counter reset to " + i);
}
continue;
}
else {
/*
* The new tgt's realm is not in the hierarchy of realms.
* It's probably not safe to get a tgt from
* a tgs that is outside the known list of realms.
* Give up now.
*/
break;
}
} // Ends outermost/main 'for' loop
return theTgt;
}
/*
* This method does the real job to request the service credential.
*/
private static Credentials serviceCreds(
PrincipalName service, Credentials ccreds)
throws KrbException, IOException {
return serviceCreds(new KDCOptions(), ccreds,
ccreds.getClient(), service, null, null,
null, S4U2Type.NONE);
}
/*
* Obtains credentials for a service (TGS).
* Cross-realm referrals are handled if enabled. A fallback scheme
* without cross-realm referrals supports is used in case of server
* error to maintain backward compatibility.
*/
private static Credentials serviceCreds(
KDCOptions options, Credentials asCreds,
PrincipalName cname, PrincipalName sname,
PrincipalName user, Ticket[] additionalTickets,
PAData[] extraPAs, S4U2Type s4u2Type)
throws KrbException, IOException {
if (!Config.DISABLE_REFERRALS) {
try {
return serviceCredsReferrals(options, asCreds, cname, sname,
s4u2Type, user, additionalTickets, extraPAs);
} catch (KrbException e) {
// Server may raise an error if CANONICALIZE is true.
// Try CANONICALIZE false.
}
}
return serviceCredsSingle(options, asCreds, cname,
asCreds.getClientAlias(), sname, sname, s4u2Type,
user, additionalTickets, extraPAs);
}
/*
* Obtains credentials for a service (TGS).
* May handle and follow cross-realm referrals as defined by RFC 6806.
*/
private static Credentials serviceCredsReferrals(
KDCOptions options, Credentials asCreds,
PrincipalName cname, PrincipalName sname,
S4U2Type s4u2Type, PrincipalName user,
Ticket[] additionalTickets, PAData[] extraPAs)
throws KrbException, IOException {
options = new KDCOptions(options.toBooleanArray());
options.set(KDCOptions.CANONICALIZE, true);
PrincipalName cSname = sname;
PrincipalName refSname = sname; // May change with referrals
Credentials creds = null;
boolean isReferral = false;
List<String> referrals = new LinkedList<>();
PrincipalName clientAlias = asCreds.getClientAlias();
while (referrals.size() <= Config.MAX_REFERRALS) {
ReferralsCache.ReferralCacheEntry ref =
ReferralsCache.get(cname, sname, user,
additionalTickets, refSname.getRealmString());
String toRealm = null;
if (ref == null) {
creds = serviceCredsSingle(options, asCreds, cname,
clientAlias, refSname, cSname, s4u2Type,
user, additionalTickets, extraPAs);
PrincipalName server = creds.getServer();
if (!refSname.equals(server)) {
String[] serverNameStrings = server.getNameStrings();
if (serverNameStrings.length == 2 &&
serverNameStrings[0].equals(
PrincipalName.TGS_DEFAULT_SRV_NAME) &&
!refSname.getRealmAsString().equals(
serverNameStrings[1])) {
// Server Name (sname) has the following format:
// krbtgt/TO-REALM.COM@FROM-REALM.COM
ReferralsCache.put(cname, sname, user,
additionalTickets, server.getRealmString(),
serverNameStrings[1], creds);
toRealm = serverNameStrings[1];
isReferral = true;
}
}
} else {
creds = ref.getCreds();
toRealm = ref.getToRealm();
isReferral = true;
}
if (isReferral) {
if (s4u2Type == S4U2Type.PROXY) {
Credentials[] credsInOut =
new Credentials[] {creds, null};
toRealm = handleS4U2ProxyReferral(asCreds,
credsInOut, sname);
creds = credsInOut[0];
if (additionalTickets == null ||
additionalTickets.length == 0 ||
credsInOut[1] == null) {
throw new KrbException("Additional tickets expected" +
" for S4U2Proxy.");
}
additionalTickets[0] = credsInOut[1].getTicket();
} else if (s4u2Type == S4U2Type.SELF) {
handleS4U2SelfReferral(extraPAs, user, creds);
}
if (referrals.contains(toRealm)) {
// Referrals loop detected
return null;
}
asCreds = creds;
refSname = new PrincipalName(refSname.getNameString(),
refSname.getNameType(), toRealm);
referrals.add(toRealm);
isReferral = false;
continue;
}
break;
}
return creds;
}
/*
* Obtains credentials for a service (TGS).
* If the service realm is different than the one in the TGT, a new TGT for
* the service realm is obtained first (see getTGTforRealm call). This is
* not expected when following cross-realm referrals because the referral
* TGT realm matches the service realm.
*/
private static Credentials serviceCredsSingle(
KDCOptions options, Credentials asCreds,
PrincipalName cname, PrincipalName clientAlias,
PrincipalName refSname, PrincipalName sname,
S4U2Type s4u2Type, PrincipalName user,
Ticket[] additionalTickets, PAData[] extraPAs)
throws KrbException, IOException {
Credentials theCreds = null;
boolean[] okAsDelegate = new boolean[]{true};
String[] serverAsCredsNames = asCreds.getServer().getNameStrings();
String tgtRealm = serverAsCredsNames[1];
String serviceRealm = refSname.getRealmString();
if (!serviceRealm.equals(tgtRealm)) {
// This is a cross-realm service request
if (DEBUG) {
System.out.println(">>> serviceCredsSingle:" +
" cross-realm authentication");
System.out.println(">>> serviceCredsSingle:" +
" obtaining credentials from " + tgtRealm +
" to " + serviceRealm);
}
Credentials newTgt = getTGTforRealm(tgtRealm, serviceRealm,
asCreds, okAsDelegate);
if (newTgt == null) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED,
"No service creds");
}
if (DEBUG) {
System.out.println(">>> Cross-realm TGT Credentials" +
" serviceCredsSingle: ");
Credentials.printDebug(newTgt);
}
if (s4u2Type == S4U2Type.SELF) {
handleS4U2SelfReferral(extraPAs, user, newTgt);
}
asCreds = newTgt;
cname = asCreds.getClient();
} else if (DEBUG) {
System.out.println(">>> Credentials serviceCredsSingle:" +
" same realm");
}
KrbTgsReq req = new KrbTgsReq(options, asCreds, cname, clientAlias,
refSname, sname, additionalTickets, extraPAs);
theCreds = req.sendAndGetCreds();
if (theCreds != null) {
if (DEBUG) {
System.out.println(">>> TGS credentials serviceCredsSingle:");
Credentials.printDebug(theCreds);
}
if (!okAsDelegate[0]) {
theCreds.resetDelegate();
}
}
return theCreds;
}
/**
* PA-FOR-USER may need to be regenerated if credentials
* change. This may happen when obtaining a TGT for a
* different realm or when using a referral TGT.
*/
private static void handleS4U2SelfReferral(PAData[] pas,
PrincipalName user, Credentials newCreds)
throws Asn1Exception, KrbException, IOException {
if (DEBUG) {
System.out.println(">>> Handling S4U2Self referral");
}
for (int i = 0; i < pas.length; i++) {
PAData pa = pas[i];
if (pa.getType() == Krb5.PA_FOR_USER) {
pas[i] = new PAData(Krb5.PA_FOR_USER,
new PAForUserEnc(user,
newCreds.getSessionKey()).asn1Encode());
break;
}
}
}
/**
* This method is called after receiving the first realm referral for
* a S4U2Proxy request. The credentials and tickets needed for the
* final S4U2Proxy request (in the referrals chain) are returned.
*
* Referrals are handled as described by MS-SFU (section 3.1.5.2.2
* Receives Referral).
*
* @param asCreds middle service credentials used for the first S4U2Proxy
* request
* @param credsInOut (in/out parameter):
* * input: first S4U2Proxy referral TGT received, null
* * output: referral TGT for final S4U2Proxy service request,
* client referral TGT for final S4U2Proxy service request
* (to be sent as additional-ticket)
* @param sname the backend service name
* @param additionalTickets (out parameter): the additional ticket for the
* last S4U2Proxy request is returned
* @return the backend realm for the last S4U2Proxy request
*/
private static String handleS4U2ProxyReferral(Credentials asCreds,
Credentials[] credsInOut, PrincipalName sname)
throws KrbException, IOException {
if (DEBUG) {
System.out.println(">>> Handling S4U2Proxy referral");
}
Credentials refTGT = null;
// Get a credential for the middle service to the backend so we know
// the backend realm, as described in MS-SFU (section 3.1.5.2.2).
Credentials middleSvcCredsInBackendRealm =
serviceCreds(sname, asCreds);
String backendRealm =
middleSvcCredsInBackendRealm.getServer().getRealmString();
String toRealm = credsInOut[0].getServer().getNameStrings()[1];
if (!toRealm.equals(backendRealm)) {
// More than 1 hop. Follow the referrals chain and obtain a
// TGT for the backend realm.
refTGT = getTGTforRealm(toRealm, backendRealm, credsInOut[0],
new boolean[1]);
} else {
// There was only 1 hop. The referral TGT received is already
// for the backend realm.
refTGT = credsInOut[0];
}
credsInOut[0] = getTGTforRealm(asCreds.getClient().getRealmString(),
backendRealm, asCreds, new boolean[1]);
credsInOut[1] = refTGT;
return backendRealm;
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2005, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
import sun.security.krb5.internal.util.KerberosString;
/**
* Implements the ASN.1 ETYPE-INFO-ENTRY type.
*
* ETYPE-INFO-ENTRY ::= SEQUENCE {
* etype [0] Int32,
* salt [1] OCTET STRING OPTIONAL
* }
*
* @author Seema Malkani
*/
public class ETypeInfo {
private int etype;
private String salt = null;
private static final byte TAG_TYPE = 0;
private static final byte TAG_VALUE = 1;
private ETypeInfo() {
}
public ETypeInfo(int etype, String salt) {
this.etype = etype;
this.salt = salt;
}
public Object clone() {
return new ETypeInfo(etype, salt);
}
/**
* Constructs a ETypeInfo object.
* @param encoding a DER-encoded data.
* @exception Asn1Exception if an error occurs while decoding an
* ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public ETypeInfo(DerValue encoding) throws Asn1Exception, IOException {
DerValue der = null;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
// etype
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
this.etype = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
// salt
if (encoding.getData().available() > 0) {
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x01) {
byte[] saltBytes = der.getData().getOctetString();
// Although salt is defined as an OCTET STRING, it's the
// encoding from of a string. As RFC 4120 says:
//
// "The salt, ..., is also completely unspecified with respect
// to character set and is probably locale-specific".
//
// It's known that this field is using the same encoding as
// KerberosString in most implementations.
if (KerberosString.MSNAME) {
this.salt = new String(saltBytes, "UTF8");
} else {
this.salt = new String(saltBytes);
}
}
}
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes this object to an OutputStream.
*
* @return byte array of the encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception Asn1Exception on encoding errors.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(etype);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
TAG_TYPE), temp);
if (salt != null) {
temp = new DerOutputStream();
if (KerberosString.MSNAME) {
temp.putOctetString(salt.getBytes("UTF8"));
} else {
temp.putOctetString(salt.getBytes());
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
TAG_VALUE), temp);
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
// accessor methods
public int getEType() {
return etype;
}
public String getSalt() {
return salt;
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2005, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
import sun.security.krb5.internal.util.KerberosString;
/**
* Implements the ASN.1 ETYPE-INFO-ENTRY type.
*
* ETYPE-INFO2-ENTRY ::= SEQUENCE {
* etype [0] Int32,
* salt [1] KerberosString OPTIONAL,
* s2kparams [2] OCTET STRING OPTIONAL
* }
*
* @author Seema Malkani
*/
public class ETypeInfo2 {
private int etype;
private String saltStr = null;
private byte[] s2kparams = null;
private static final byte TAG_TYPE = 0;
private static final byte TAG_VALUE1 = 1;
private static final byte TAG_VALUE2 = 2;
private ETypeInfo2() {
}
public ETypeInfo2(int etype, String salt, byte[] s2kparams) {
this.etype = etype;
this.saltStr = salt;
if (s2kparams != null) {
this.s2kparams = s2kparams.clone();
}
}
public Object clone() {
ETypeInfo2 etypeInfo2 = new ETypeInfo2();
etypeInfo2.etype = etype;
etypeInfo2.saltStr = saltStr;
if (s2kparams != null) {
etypeInfo2.s2kparams = new byte[s2kparams.length];
System.arraycopy(s2kparams, 0, etypeInfo2.s2kparams,
0, s2kparams.length);
}
return etypeInfo2;
}
/**
* Constructs a ETypeInfo2 object.
* @param encoding a DER-encoded data.
* @exception Asn1Exception if an error occurs while decoding an
* ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public ETypeInfo2(DerValue encoding) throws Asn1Exception, IOException {
DerValue der = null;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
// etype
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
this.etype = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
// salt
if (encoding.getData().available() > 0) {
if ((encoding.getData().peekByte() & 0x1F) == 0x01) {
der = encoding.getData().getDerValue();
this.saltStr = new KerberosString(
der.getData().getDerValue()).toString();
}
}
// s2kparams
if (encoding.getData().available() > 0) {
if ((encoding.getData().peekByte() & 0x1F) == 0x02) {
der = encoding.getData().getDerValue();
this.s2kparams = der.getData().getOctetString();
}
}
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes this object to an OutputStream.
*
* @return byte array of the encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception Asn1Exception on encoding errors.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(etype);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
TAG_TYPE), temp);
if (saltStr != null) {
temp = new DerOutputStream();
temp.putDerValue(new KerberosString(saltStr).toDerValue());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
TAG_VALUE1), temp);
}
if (s2kparams != null) {
temp = new DerOutputStream();
temp.putOctetString(s2kparams);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
TAG_VALUE2), temp);
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
// accessor methods
public int getEType() {
return etype;
}
public String getSalt() {
return saltStr;
}
public byte[] getParams() {
return ((s2kparams == null) ? null : s2kparams.clone());
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 EncAPRepPart type.
*
* <pre>{@code
* EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
* ctime [0] KerberosTime,
* cusec [1] Microseconds,
* subkey [2] EncryptionKey OPTIONAL,
* seq-number [3] UInt32 OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class EncAPRepPart {
public KerberosTime ctime;
public int cusec;
EncryptionKey subKey; //optional
Integer seqNumber; //optional
public EncAPRepPart(
KerberosTime new_ctime,
int new_cusec,
EncryptionKey new_subKey,
Integer new_seqNumber) {
ctime = new_ctime;
cusec = new_cusec;
subKey = new_subKey;
seqNumber = new_seqNumber;
}
public EncAPRepPart(byte[] data)
throws Asn1Exception, IOException {
init(new DerValue(data));
}
public EncAPRepPart(DerValue encoding)
throws Asn1Exception, IOException {
init(encoding);
}
/**
* Initializes an EncaPRepPart object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
private void init(DerValue encoding) throws Asn1Exception, IOException {
DerValue der, subDer;
if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x1B)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
ctime = KerberosTime.parse(der.getData(), (byte) 0x00, true);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x01) {
cusec = subDer.getData().getBigInteger().intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (der.getData().available() > 0) {
subKey = EncryptionKey.parse(der.getData(), (byte) 0x02, true);
} else {
subKey = null;
seqNumber = null;
}
if (der.getData().available() > 0) {
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) != 0x03) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
seqNumber = new Integer(subDer.getData().getBigInteger().intValue());
} else {
seqNumber = null;
}
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an EncAPRepPart object.
* @return byte array of encoded EncAPRepPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
Vector<DerValue> v = new Vector<>();
DerOutputStream temp = new DerOutputStream();
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), ctime.asn1Encode()));
temp.putInteger(BigInteger.valueOf(cusec));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), temp.toByteArray()));
if (subKey != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), subKey.asn1Encode()));
}
if (seqNumber != null) {
temp = new DerOutputStream();
// encode as an unsigned integer (UInt32)
temp.putInteger(BigInteger.valueOf(seqNumber.longValue()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), temp.toByteArray()));
}
DerValue der[] = new DerValue[v.size()];
v.copyInto(der);
temp = new DerOutputStream();
temp.putSequence(der);
DerOutputStream out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
true, (byte) 0x1B), temp);
return out.toByteArray();
}
public final EncryptionKey getSubKey() {
return subKey;
}
public final Integer getSeqNumber() {
return seqNumber;
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.io.IOException;
public class EncASRepPart extends EncKDCRepPart {
public EncASRepPart(
EncryptionKey new_key,
LastReq new_lastReq,
int new_nonce,
KerberosTime new_keyExpiration,
TicketFlags new_flags,
KerberosTime new_authtime,
KerberosTime new_starttime,
KerberosTime new_endtime,
KerberosTime new_renewTill,
PrincipalName new_sname,
HostAddresses new_caddr,
PAData[] new_pAData) {
super(
new_key,
new_lastReq,
new_nonce,
new_keyExpiration,
new_flags,
new_authtime,
new_starttime,
new_endtime,
new_renewTill,
new_sname,
new_caddr,
new_pAData,
Krb5.KRB_ENC_AS_REP_PART
);
//may need to use Krb5.KRB_ENC_TGS_REP_PART to mimic
//behavior of other implementaions, instead of above
}
public EncASRepPart(byte[] data) throws Asn1Exception,
IOException, KrbException {
init(new DerValue(data));
}
public EncASRepPart(DerValue encoding) throws Asn1Exception,
IOException, KrbException {
init(encoding);
}
private void init(DerValue encoding) throws Asn1Exception,
IOException, KrbException {
init(encoding, Krb5.KRB_ENC_AS_REP_PART);
}
public byte[] asn1Encode() throws Asn1Exception,
IOException {
return asn1Encode(Krb5.KRB_ENC_AS_REP_PART);
}
}

View File

@@ -0,0 +1,241 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 EncKDCRepPart type.
*
* <pre>{@code
* EncKDCRepPart ::= SEQUENCE {
* key [0] EncryptionKey,
* last-req [1] LastReq,
* nonce [2] UInt32,
* key-expiration [3] KerberosTime OPTIONAL,
* flags [4] TicketFlags,
* authtime [5] KerberosTime,
* starttime [6] KerberosTime OPTIONAL,
* endtime [7] KerberosTime,
* renew-till [8] KerberosTime OPTIONAL,
* srealm [9] Realm,
* sname [10] PrincipalName,
* caddr [11] HostAddresses OPTIONAL,
* encrypted-pa-data [12] SEQUENCE OF PA-DATA OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class EncKDCRepPart {
public EncryptionKey key;
public LastReq lastReq;
public int nonce;
public KerberosTime keyExpiration; //optional
public TicketFlags flags;
public KerberosTime authtime;
public KerberosTime starttime; //optional
public KerberosTime endtime;
public KerberosTime renewTill; //optional
public PrincipalName sname;
public HostAddresses caddr; //optional
public PAData[] pAData; //optional
public int msgType; //not included in sequence
public EncKDCRepPart(
EncryptionKey new_key,
LastReq new_lastReq,
int new_nonce,
KerberosTime new_keyExpiration,
TicketFlags new_flags,
KerberosTime new_authtime,
KerberosTime new_starttime,
KerberosTime new_endtime,
KerberosTime new_renewTill,
PrincipalName new_sname,
HostAddresses new_caddr,
PAData[] new_pAData,
int new_msgType) {
key = new_key;
lastReq = new_lastReq;
nonce = new_nonce;
keyExpiration = new_keyExpiration;
flags = new_flags;
authtime = new_authtime;
starttime = new_starttime;
endtime = new_endtime;
renewTill = new_renewTill;
sname = new_sname;
caddr = new_caddr;
pAData = new_pAData;
msgType = new_msgType;
}
public EncKDCRepPart() {
}
public EncKDCRepPart(byte[] data, int rep_type)
throws Asn1Exception, IOException, RealmException {
init(new DerValue(data), rep_type);
}
public EncKDCRepPart(DerValue encoding, int rep_type)
throws Asn1Exception, IOException, RealmException {
init(encoding, rep_type);
}
/**
* Initializes an EncKDCRepPart object.
*
* @param encoding a single DER-encoded value.
* @param rep_type type of the encrypted reply message.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while decoding an Realm object.
*/
protected void init(DerValue encoding, int rep_type)
throws Asn1Exception, IOException, RealmException {
DerValue der, subDer;
//implementations return the incorrect tag value, so
//we don't use the above line; instead we use the following
msgType = (encoding.getTag() & (byte) 0x1F);
if (msgType != Krb5.KRB_ENC_AS_REP_PART &&
msgType != Krb5.KRB_ENC_TGS_REP_PART) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
key = EncryptionKey.parse(der.getData(), (byte) 0x00, false);
lastReq = LastReq.parse(der.getData(), (byte) 0x01, false);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x02) {
nonce = subDer.getData().getBigInteger().intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
keyExpiration = KerberosTime.parse(der.getData(), (byte) 0x03, true);
flags = TicketFlags.parse(der.getData(), (byte) 0x04, false);
authtime = KerberosTime.parse(der.getData(), (byte) 0x05, false);
starttime = KerberosTime.parse(der.getData(), (byte) 0x06, true);
endtime = KerberosTime.parse(der.getData(), (byte) 0x07, false);
renewTill = KerberosTime.parse(der.getData(), (byte) 0x08, true);
Realm srealm = Realm.parse(der.getData(), (byte) 0x09, false);
sname = PrincipalName.parse(der.getData(), (byte) 0x0A, false, srealm);
if (der.getData().available() > 0) {
caddr = HostAddresses.parse(der.getData(), (byte) 0x0B, true);
}
if (der.getData().available() > 0) {
pAData = PAData.parseSequence(der.getData(), (byte) 0x0C, true);
}
// We observe extra data from MSAD
/*if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}*/
}
/**
* Encodes an EncKDCRepPart object.
* @param rep_type type of encrypted reply message.
* @return byte array of encoded EncKDCRepPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode(int rep_type) throws Asn1Exception,
IOException {
DerOutputStream bytes;
DerOutputStream temp = new DerOutputStream();
DerOutputStream out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), key.asn1Encode());
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), lastReq.asn1Encode());
temp.putInteger(BigInteger.valueOf(nonce));
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), temp);
if (keyExpiration != null) {
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), keyExpiration.asn1Encode());
}
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x04), flags.asn1Encode());
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x05), authtime.asn1Encode());
if (starttime != null) {
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x06), starttime.asn1Encode());
}
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x07), endtime.asn1Encode());
if (renewTill != null) {
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x08), renewTill.asn1Encode());
}
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x09), sname.getRealm().asn1Encode());
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x0A), sname.asn1Encode());
if (caddr != null) {
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x0B), caddr.asn1Encode());
}
if (pAData != null && pAData.length > 0) {
temp = new DerOutputStream();
for (int i = 0; i < pAData.length; i++) {
temp.write(pAData[i].asn1Encode());
}
bytes = new DerOutputStream();
bytes.write(DerValue.tag_SequenceOf, temp);
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x0C), bytes);
}
//should use the rep_type to build the encoding
//but other implementations do not; it is ignored and
//the cached msgType is used instead
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, out);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION,
true, (byte) msgType), temp);
return bytes.toByteArray();
}
}

View File

@@ -0,0 +1,215 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.RealmException;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 EncKrbCredPart type.
*
* <pre>{@code
* EncKrbCredPart ::= [APPLICATION 29] SEQUENCE {
* ticket-info [0] SEQUENCE OF KrbCredInfo,
* nonce [1] UInt32 OPTIONAL,
* timestamp [2] KerberosTime OPTIONAL,
* usec [3] Microseconds OPTIONAL,
* s-address [4] HostAddress OPTIONAL,
* r-address [5] HostAddress OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class EncKrbCredPart {
public KrbCredInfo[] ticketInfo = null;
public KerberosTime timeStamp; //optional
private Integer nonce; //optional
private Integer usec; //optional
private HostAddress sAddress; //optional
private HostAddresses rAddress; //optional
public EncKrbCredPart(
KrbCredInfo[] new_ticketInfo,
KerberosTime new_timeStamp,
Integer new_usec,
Integer new_nonce,
HostAddress new_sAddress,
HostAddresses new_rAddress) throws IOException {
if (new_ticketInfo != null) {
ticketInfo = new KrbCredInfo[new_ticketInfo.length];
for (int i = 0; i < new_ticketInfo.length; i++) {
if (new_ticketInfo[i] == null) {
throw new IOException("Cannot create a EncKrbCredPart");
} else {
ticketInfo[i] = (KrbCredInfo) new_ticketInfo[i].clone();
}
}
}
timeStamp = new_timeStamp;
usec = new_usec;
nonce = new_nonce;
sAddress = new_sAddress;
rAddress = new_rAddress;
}
public EncKrbCredPart(byte[] data) throws Asn1Exception,
IOException, RealmException {
init(new DerValue(data));
}
public EncKrbCredPart(DerValue encoding) throws Asn1Exception,
IOException, RealmException {
init(encoding);
}
/**
* Initializes an EncKrbCredPart object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private void init(DerValue encoding) throws Asn1Exception,
IOException, RealmException {
DerValue der, subDer;
//may not be the correct error code for a tag
//mismatch on an encrypted structure
nonce = null;
timeStamp = null;
usec = null;
sAddress = null;
rAddress = null;
if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x1D)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x00) {
DerValue derValues[] = subDer.getData().getSequence(1);
ticketInfo = new KrbCredInfo[derValues.length];
for (int i = 0; i < derValues.length; i++) {
ticketInfo[i] = new KrbCredInfo(derValues[i]);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (der.getData().available() > 0) {
if (((byte) (der.getData().peekByte()) & (byte) 0x1F) == (byte) 0x01) {
subDer = der.getData().getDerValue();
nonce = new Integer(subDer.getData().getBigInteger().intValue());
}
}
if (der.getData().available() > 0) {
timeStamp = KerberosTime.parse(der.getData(), (byte) 0x02, true);
}
if (der.getData().available() > 0) {
if (((byte) (der.getData().peekByte()) & (byte) 0x1F) == (byte) 0x03) {
subDer = der.getData().getDerValue();
usec = new Integer(subDer.getData().getBigInteger().intValue());
}
}
if (der.getData().available() > 0) {
sAddress = HostAddress.parse(der.getData(), (byte) 0x04, true);
}
if (der.getData().available() > 0) {
rAddress = HostAddresses.parse(der.getData(), (byte) 0x05, true);
}
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an EncKrbCredPart object.
* @return byte array of encoded EncKrbCredPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
DerValue[] tickets = new DerValue[ticketInfo.length];
for (int i = 0; i < ticketInfo.length; i++) {
tickets[i] = new DerValue(ticketInfo[i].asn1Encode());
}
temp.putSequence(tickets);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), temp);
if (nonce != null) {
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(nonce.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), temp);
}
if (timeStamp != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), timeStamp.asn1Encode());
}
if (usec != null) {
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(usec.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), temp);
}
if (sAddress != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x04), sAddress.asn1Encode());
}
if (rAddress != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x05), rAddress.asn1Encode());
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION,
true, (byte) 0x1D), temp);
return bytes.toByteArray();
}
}

View File

@@ -0,0 +1,173 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 EncKrbPrivPart type.
*
* <pre>{@code
* EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
* user-data [0] OCTET STRING,
* timestamp [1] KerberosTime OPTIONAL,
* usec [2] Microseconds OPTIONAL,
* seq-number [3] UInt32 OPTIONAL,
* s-address [4] HostAddress -- sender's addr --,
* r-address [5] HostAddress OPTIONAL -- recip's addr
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class EncKrbPrivPart {
public byte[] userData = null;
public KerberosTime timestamp; //optional
public Integer usec; //optional
public Integer seqNumber; //optional
public HostAddress sAddress; //optional
public HostAddress rAddress; //optional
public EncKrbPrivPart(
byte[] new_userData,
KerberosTime new_timestamp,
Integer new_usec,
Integer new_seqNumber,
HostAddress new_sAddress,
HostAddress new_rAddress) {
if (new_userData != null) {
userData = new_userData.clone();
}
timestamp = new_timestamp;
usec = new_usec;
seqNumber = new_seqNumber;
sAddress = new_sAddress;
rAddress = new_rAddress;
}
public EncKrbPrivPart(byte[] data) throws Asn1Exception, IOException {
init(new DerValue(data));
}
public EncKrbPrivPart(DerValue encoding) throws Asn1Exception, IOException {
init(encoding);
}
/**
* Initializes an EncKrbPrivPart object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
private void init(DerValue encoding) throws Asn1Exception, IOException {
DerValue der, subDer;
if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x1C)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x00) {
userData = subDer.getData().getOctetString();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
timestamp = KerberosTime.parse(der.getData(), (byte) 0x01, true);
if ((der.getData().peekByte() & 0x1F) == 0x02) {
subDer = der.getData().getDerValue();
usec = new Integer(subDer.getData().getBigInteger().intValue());
} else {
usec = null;
}
if ((der.getData().peekByte() & 0x1F) == 0x03) {
subDer = der.getData().getDerValue();
seqNumber = new Integer(subDer.getData().getBigInteger().intValue());
} else {
seqNumber = null;
}
sAddress = HostAddress.parse(der.getData(), (byte) 0x04, false);
if (der.getData().available() > 0) {
rAddress = HostAddress.parse(der.getData(), (byte) 0x05, true);
}
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an EncKrbPrivPart object.
* @return byte array of encoded EncKrbPrivPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream temp = new DerOutputStream();
DerOutputStream bytes = new DerOutputStream();
temp.putOctetString(userData);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp);
if (timestamp != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), timestamp.asn1Encode());
}
if (usec != null) {
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(usec.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x02), temp);
}
if (seqNumber != null) {
temp = new DerOutputStream();
// encode as an unsigned integer (UInt32)
temp.putInteger(BigInteger.valueOf(seqNumber.longValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x03), temp);
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x04), sAddress.asn1Encode());
if (rAddress != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x05), rAddress.asn1Encode());
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) 0x1C), temp);
return bytes.toByteArray();
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.io.IOException;
public class EncTGSRepPart extends EncKDCRepPart {
public EncTGSRepPart(
EncryptionKey new_key,
LastReq new_lastReq,
int new_nonce,
KerberosTime new_keyExpiration,
TicketFlags new_flags,
KerberosTime new_authtime,
KerberosTime new_starttime,
KerberosTime new_endtime,
KerberosTime new_renewTill,
PrincipalName new_sname,
HostAddresses new_caddr,
PAData[] new_pAData) {
super(
new_key,
new_lastReq,
new_nonce,
new_keyExpiration,
new_flags,
new_authtime,
new_starttime,
new_endtime,
new_renewTill,
new_sname,
new_caddr,
new_pAData,
Krb5.KRB_ENC_TGS_REP_PART);
}
public EncTGSRepPart(byte[] data) throws Asn1Exception,
IOException, KrbException {
init(new DerValue(data));
}
public EncTGSRepPart(DerValue encoding) throws Asn1Exception,
IOException, KrbException {
init(encoding);
}
private void init(DerValue encoding) throws Asn1Exception,
IOException, KrbException {
init(encoding, Krb5.KRB_ENC_TGS_REP_PART);
}
public byte[] asn1Encode() throws Asn1Exception,
IOException {
return asn1Encode(Krb5.KRB_ENC_TGS_REP_PART);
}
}

View File

@@ -0,0 +1,220 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.io.*;
/**
* Implements the ASN.1 EncTicketPart type.
*
* <pre>{@code
* EncTicketPart ::= [APPLICATION 3] SEQUENCE {
* flags [0] TicketFlags,
* key [1] EncryptionKey,
* crealm [2] Realm,
* cname [3] PrincipalName,
* transited [4] TransitedEncoding,
* authtime [5] KerberosTime,
* starttime [6] KerberosTime OPTIONAL,
* endtime [7] KerberosTime,
* renew-till [8] KerberosTime OPTIONAL,
* caddr [9] HostAddresses OPTIONAL,
* authorization-data [10] AuthorizationData OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class EncTicketPart {
public TicketFlags flags;
public EncryptionKey key;
public PrincipalName cname;
public TransitedEncoding transited;
public KerberosTime authtime;
public KerberosTime starttime; //optional
public KerberosTime endtime;
public KerberosTime renewTill; //optional
public HostAddresses caddr; //optional
public AuthorizationData authorizationData; //optional
public EncTicketPart(
TicketFlags new_flags,
EncryptionKey new_key,
PrincipalName new_cname,
TransitedEncoding new_transited,
KerberosTime new_authtime,
KerberosTime new_starttime,
KerberosTime new_endtime,
KerberosTime new_renewTill,
HostAddresses new_caddr,
AuthorizationData new_authorizationData) {
flags = new_flags;
key = new_key;
cname = new_cname;
transited = new_transited;
authtime = new_authtime;
starttime = new_starttime;
endtime = new_endtime;
renewTill = new_renewTill;
caddr = new_caddr;
authorizationData = new_authorizationData;
}
public EncTicketPart(byte[] data)
throws Asn1Exception, KrbException, IOException {
init(new DerValue(data));
}
public EncTicketPart(DerValue encoding)
throws Asn1Exception, KrbException, IOException {
init(encoding);
}
/**
* Initializes an EncTicketPart object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private static String getHexBytes(byte[] bytes, int len)
throws IOException {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < len; i++) {
int b1 = (bytes[i] >> 4) & 0x0f;
int b2 = bytes[i] & 0x0f;
sb.append(Integer.toHexString(b1));
sb.append(Integer.toHexString(b2));
sb.append(' ');
}
return sb.toString();
}
private void init(DerValue encoding)
throws Asn1Exception, IOException, RealmException {
DerValue der, subDer;
renewTill = null;
caddr = null;
authorizationData = null;
if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x03)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
flags = TicketFlags.parse(der.getData(), (byte) 0x00, false);
key = EncryptionKey.parse(der.getData(), (byte) 0x01, false);
Realm crealm = Realm.parse(der.getData(), (byte) 0x02, false);
cname = PrincipalName.parse(der.getData(), (byte) 0x03, false, crealm);
transited = TransitedEncoding.parse(der.getData(), (byte) 0x04, false);
authtime = KerberosTime.parse(der.getData(), (byte) 0x05, false);
starttime = KerberosTime.parse(der.getData(), (byte) 0x06, true);
endtime = KerberosTime.parse(der.getData(), (byte) 0x07, false);
if (der.getData().available() > 0) {
renewTill = KerberosTime.parse(der.getData(), (byte) 0x08, true);
}
if (der.getData().available() > 0) {
caddr = HostAddresses.parse(der.getData(), (byte) 0x09, true);
}
if (der.getData().available() > 0) {
authorizationData = AuthorizationData.parse(der.getData(), (byte) 0x0A, true);
}
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an EncTicketPart object.
* @return byte array of encoded EncTicketPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), flags.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), key.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), cname.getRealm().asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), cname.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x04), transited.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x05), authtime.asn1Encode());
if (starttime != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x06), starttime.asn1Encode());
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x07), endtime.asn1Encode());
if (renewTill != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x08), renewTill.asn1Encode());
}
if (caddr != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x09), caddr.asn1Encode());
}
if (authorizationData != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x0A), authorizationData.asn1Encode());
}
temp.write(DerValue.tag_Sequence, bytes);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION,
true, (byte) 0x03), temp);
return bytes.toByteArray();
}
}

View File

@@ -0,0 +1,306 @@
/*
* Copyright (c) 2000, 2006, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Config;
import sun.security.krb5.Asn1Exception;
import sun.security.util.*;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.io.IOException;
import java.util.Arrays;
/**
* Implements the ASN.1 HostAddress type.
*
* <pre>{@code
* HostAddress ::= SEQUENCE {
* addr-type [0] Int32,
* address [1] OCTET STRING
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class HostAddress implements Cloneable {
int addrType;
byte[] address = null;
private static InetAddress localInetAddress; //caches local inet address
private static final boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
private volatile int hashCode = 0;
private HostAddress(int dummy) {}
public Object clone() {
HostAddress new_hostAddress = new HostAddress(0);
new_hostAddress.addrType = addrType;
if (address != null) {
new_hostAddress.address = address.clone();
}
return new_hostAddress;
}
public int hashCode() {
if (hashCode == 0) {
int result = 17;
result = 37*result + addrType;
if (address != null) {
for (int i=0; i < address.length; i++) {
result = 37*result + address[i];
}
}
hashCode = result;
}
return hashCode;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof HostAddress)) {
return false;
}
HostAddress h = (HostAddress)obj;
if (addrType != h.addrType ||
(address != null && h.address == null) ||
(address == null && h.address != null))
return false;
if (address != null && h.address != null) {
if (address.length != h.address.length)
return false;
for (int i = 0; i < address.length; i++)
if (address[i] != h.address[i])
return false;
}
return true;
}
private static synchronized InetAddress getLocalInetAddress()
throws UnknownHostException {
if (localInetAddress == null) {
localInetAddress = InetAddress.getLocalHost();
}
if (localInetAddress == null) {
throw new UnknownHostException();
}
return (localInetAddress);
}
/**
* Gets the InetAddress of this HostAddress.
* @return the IP address for this specified host.
* @exception UnknownHostException if no IP address for the host could be found.
*
*/
public InetAddress getInetAddress() throws UnknownHostException {
// the type of internet addresses is 2.
if (addrType == Krb5.ADDRTYPE_INET ||
addrType == Krb5.ADDRTYPE_INET6) {
return (InetAddress.getByAddress(address));
} else {
// if it is other type (ISO address, XNS address, etc)
return null;
}
}
private int getAddrType(InetAddress inetAddress) {
int addressType = 0;
if (inetAddress instanceof Inet4Address)
addressType = Krb5.ADDRTYPE_INET;
else if (inetAddress instanceof Inet6Address)
addressType = Krb5.ADDRTYPE_INET6;
return (addressType);
}
// implicit default not in Config.java
public HostAddress() throws UnknownHostException {
InetAddress inetAddress = getLocalInetAddress();
addrType = getAddrType(inetAddress);
address = inetAddress.getAddress();
}
/**
* Creates a HostAddress from the specified address and address type.
*
* @param new_addrType the value of the address type which matches the defined
* address family constants in the Berkeley Standard
* Distributions of Unix.
* @param new_address network address.
* @exception KrbApErrException if address type and address length do not match defined value.
*
*/
public HostAddress(int new_addrType, byte[] new_address)
throws KrbApErrException, UnknownHostException {
switch(new_addrType) {
case Krb5.ADDRTYPE_INET: //Internet address
if (new_address.length != 4)
throw new KrbApErrException(0, "Invalid Internet address");
break;
case Krb5.ADDRTYPE_CHAOS:
if (new_address.length != 2) //CHAOSnet address
throw new KrbApErrException(0, "Invalid CHAOSnet address");
break;
case Krb5.ADDRTYPE_ISO: // ISO address
break;
case Krb5.ADDRTYPE_IPX: // XNS address
if (new_address.length != 6)
throw new KrbApErrException(0, "Invalid XNS address");
break;
case Krb5.ADDRTYPE_APPLETALK: //AppleTalk DDP address
if (new_address.length != 3)
throw new KrbApErrException(0, "Invalid DDP address");
break;
case Krb5.ADDRTYPE_DECNET: //DECnet Phase IV address
if (new_address.length != 2)
throw new KrbApErrException(0, "Invalid DECnet Phase IV address");
break;
case Krb5.ADDRTYPE_INET6: //Internet IPv6 address
if (new_address.length != 16)
throw new KrbApErrException(0, "Invalid Internet IPv6 address");
break;
}
addrType = new_addrType;
if (new_address != null) {
address = new_address.clone();
}
if (DEBUG) {
if (addrType == Krb5.ADDRTYPE_INET ||
addrType == Krb5.ADDRTYPE_INET6) {
System.out.println("Host address is " +
InetAddress.getByAddress(address));
}
}
}
public HostAddress(InetAddress inetAddress) {
addrType = getAddrType(inetAddress);
address = inetAddress.getAddress();
}
/**
* Constructs a host address from a single DER-encoded value.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public HostAddress(DerValue encoding) throws Asn1Exception, IOException {
DerValue der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x00) {
addrType = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x01) {
address = der.getData().getOctetString();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes a HostAddress object.
* @return a byte array of encoded HostAddress object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(this.addrType);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
temp = new DerOutputStream();
temp.putOctetString(address);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Parses (unmarshal) a host address from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @exception IOException if an I/O error occurs while reading encoded data.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional
* @return an instance of HostAddress.
*
*/
public static HostAddress parse(DerInputStream data, byte explicitTag,
boolean optional)
throws Asn1Exception, IOException{
if ((optional) &&
(((byte)data.peekByte() & (byte)0x1F) != explicitTag)) {
return null;
}
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
else {
DerValue subDer = der.getData().getDerValue();
return new HostAddress(subDer);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Arrays.toString(address));
sb.append('(').append(addrType).append(')');
return sb.toString();
}
}

View File

@@ -0,0 +1,346 @@
/*
* Copyright (c) 2000, 2011, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Config;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.KrbException;
import sun.security.krb5.Asn1Exception;
import sun.security.util.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import sun.security.krb5.internal.ccache.CCacheOutputStream;
/**
* Implements the ASN.1 HostAddresses type.
*
* <pre>{@code
* HostAddresses -- NOTE: subtly different from rfc1510,
* -- but has a value mapping and encodes the same
* ::= SEQUENCE OF HostAddress
*
* HostAddress ::= SEQUENCE {
* addr-type [0] Int32,
* address [1] OCTET STRING
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class HostAddresses implements Cloneable {
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
private HostAddress[] addresses = null;
private volatile int hashCode = 0;
public HostAddresses(HostAddress[] new_addresses) throws IOException {
if (new_addresses != null) {
addresses = new HostAddress[new_addresses.length];
for (int i = 0; i < new_addresses.length; i++) {
if (new_addresses[i] == null) {
throw new IOException("Cannot create a HostAddress");
} else {
addresses[i] = (HostAddress)new_addresses[i].clone();
}
}
}
}
public HostAddresses() throws UnknownHostException {
addresses = new HostAddress[1];
addresses[0] = new HostAddress();
}
private HostAddresses(int dummy) {}
public HostAddresses(PrincipalName serverPrincipal)
throws UnknownHostException, KrbException {
String[] components = serverPrincipal.getNameStrings();
if (serverPrincipal.getNameType() != PrincipalName.KRB_NT_SRV_HST ||
components.length < 2)
throw new KrbException(Krb5.KRB_ERR_GENERIC, "Bad name");
String host = components[1];
InetAddress addr[] = InetAddress.getAllByName(host);
HostAddress hAddrs[] = new HostAddress[addr.length];
for (int i = 0; i < addr.length; i++) {
hAddrs[i] = new HostAddress(addr[i]);
}
addresses = hAddrs;
}
public Object clone() {
HostAddresses new_hostAddresses = new HostAddresses(0);
if (addresses != null) {
new_hostAddresses.addresses = new HostAddress[addresses.length];
for (int i = 0; i < addresses.length; i++) {
new_hostAddresses.addresses[i] =
(HostAddress)addresses[i].clone();
}
}
return new_hostAddresses;
}
public boolean inList(HostAddress addr) {
if (addresses != null) {
for (int i = 0; i < addresses.length; i++)
if (addresses[i].equals(addr))
return true;
}
return false;
}
public int hashCode() {
if (hashCode == 0) {
int result = 17;
if (addresses != null) {
for (int i=0; i < addresses.length; i++) {
result = 37*result + addresses[i].hashCode();
}
}
hashCode = result;
}
return hashCode;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof HostAddresses)) {
return false;
}
HostAddresses addrs = (HostAddresses)obj;
if ((addresses == null && addrs.addresses != null) ||
(addresses != null && addrs.addresses == null))
return false;
if (addresses != null && addrs.addresses != null) {
if (addresses.length != addrs.addresses.length)
return false;
for (int i = 0; i < addresses.length; i++)
if (!addresses[i].equals(addrs.addresses[i]))
return false;
}
return true;
}
/**
* Constructs a new <code>HostAddresses</code> object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an
* ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading
* encoded data.
*/
public HostAddresses(DerValue encoding)
throws Asn1Exception, IOException {
Vector<HostAddress> tempAddresses = new Vector<>();
DerValue der = null;
while (encoding.getData().available() > 0) {
der = encoding.getData().getDerValue();
tempAddresses.addElement(new HostAddress(der));
}
if (tempAddresses.size() > 0) {
addresses = new HostAddress[tempAddresses.size()];
tempAddresses.copyInto(addresses);
}
}
/**
* Encodes a <code>HostAddresses</code> object.
* @return byte array of encoded <code>HostAddresses</code> object.
* @exception Asn1Exception if an error occurs while decoding an
* ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading
* encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
if (addresses != null && addresses.length > 0) {
for (int i = 0; i < addresses.length; i++)
bytes.write(addresses[i].asn1Encode());
}
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Parse (unmarshal) a <code>HostAddresses</code> from a DER input stream.
* This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception if an Asn1Exception occurs.
* @param data the Der input stream value, which contains one or more
* marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional.
* @return an instance of <code>HostAddresses</code>.
*/
public static HostAddresses parse(DerInputStream data,
byte explicitTag, boolean optional)
throws Asn1Exception, IOException {
if ((optional) &&
(((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
} else {
DerValue subDer = der.getData().getDerValue();
return new HostAddresses(subDer);
}
}
/**
* Writes data field values in <code>HostAddresses</code> in FCC
* format to a <code>CCacheOutputStream</code>.
*
* @param cos a <code>CCacheOutputStream</code> to be written to.
* @exception IOException if an I/O exception occurs.
* @see sun.security.krb5.internal.ccache.CCacheOutputStream
*/
public void writeAddrs(CCacheOutputStream cos) throws IOException {
if (addresses == null || addresses.length == 0) {
cos.write32(0);
return;
}
cos.write32(addresses.length);
for (int i = 0; i < addresses.length; i++) {
cos.write16(addresses[i].addrType);
cos.write32(addresses[i].address.length);
cos.write(addresses[i].address, 0,
addresses[i].address.length);
}
}
public InetAddress[] getInetAddresses() {
if (addresses == null || addresses.length == 0)
return null;
ArrayList<InetAddress> ipAddrs = new ArrayList<>(addresses.length);
for (int i = 0; i < addresses.length; i++) {
try {
if ((addresses[i].addrType == Krb5.ADDRTYPE_INET) ||
(addresses[i].addrType == Krb5.ADDRTYPE_INET6)) {
ipAddrs.add(addresses[i].getInetAddress());
}
} catch (java.net.UnknownHostException e) {
// Should not happen since IP address given
return null;
}
}
InetAddress[] retVal = new InetAddress[ipAddrs.size()];
return ipAddrs.toArray(retVal);
}
/**
* Returns all the IP addresses of the local host.
*/
public static HostAddresses getLocalAddresses() throws IOException
{
Set<InetAddress> all = new LinkedHashSet<>();
try {
if (DEBUG) {
System.out.println(">>> KrbKdcReq local addresses are:");
}
String extra = Config.getInstance().getAll(
"libdefaults", "extra_addresses");
if (extra != null) {
for (String s: extra.split("\\s+")) {
all.add(InetAddress.getByName(s));
if (DEBUG) {
System.out.println(" extra_addresses: "
+ InetAddress.getByName(s));
}
}
}
for (NetworkInterface ni:
Collections.list(NetworkInterface.getNetworkInterfaces())) {
if (DEBUG) {
System.out.println(" NetworkInterface " + ni + ":");
System.out.println(" "
+ Collections.list(ni.getInetAddresses()));
}
all.addAll(Collections.list(ni.getInetAddresses()));
}
return new HostAddresses(all.toArray(new InetAddress[all.size()]));
} catch (Exception exc) {
throw new IOException(exc.toString());
}
}
/**
* Creates a new HostAddresses instance from the supplied list
* of InetAddresses.
*/
public HostAddresses(InetAddress[] inetAddresses)
{
if (inetAddresses == null)
{
addresses = null;
return;
}
addresses = new HostAddress[inetAddresses.length];
for (int i = 0; i < inetAddresses.length; i++)
addresses[i] = new HostAddress(inetAddresses[i]);
}
@Override
public String toString() {
return Arrays.toString(addresses);
}
}

View File

@@ -0,0 +1,332 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Config;
import sun.security.krb5.KrbException;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.internal.util.KerberosFlags;
import sun.security.util.*;
import java.io.IOException;
/**
* Implements the ASN.1 KDCOptions type.
*
* <pre>{@code
* KDCOptions ::= KerberosFlags
* -- reserved(0),
* -- forwardable(1),
* -- forwarded(2),
* -- proxiable(3),
* -- proxy(4),
* -- allow-postdate(5),
* -- postdated(6),
* -- unused7(7),
* -- renewable(8),
* -- unused9(9),
* -- unused10(10),
* -- opt-hardware-auth(11),
* -- unused12(12),
* -- unused13(13),
* -- 15 is reserved for canonicalize
* -- unused15(15),
* -- 26 was unused in 1510
* -- disable-transited-check(26),
* -- renewable-ok(27),
* -- enc-tkt-in-skey(28),
* -- renew(30),
* -- validate(31)
*
* KerberosFlags ::= BIT STRING (SIZE (32..MAX))
* -- minimum number of bits shall be sent,
* -- but no fewer than 32
*
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*
* <p>
* This class appears as data field in the initial request(KRB_AS_REQ)
* or subsequent request(KRB_TGS_REQ) to the KDC and indicates the flags
* that the client wants to set on the tickets.
*
* The optional bits are:
* <UL>
* <LI>KDCOptions.RESERVED
* <LI>KDCOptions.FORWARDABLE
* <LI>KDCOptions.FORWARDED
* <LI>KDCOptions.PROXIABLE
* <LI>KDCOptions.PROXY
* <LI>KDCOptions.ALLOW_POSTDATE
* <LI>KDCOptions.POSTDATED
* <LI>KDCOptions.RENEWABLE
* <LI>KDCOptions.RENEWABLE_OK
* <LI>KDCOptions.ENC_TKT_IN_SKEY
* <LI>KDCOptions.RENEW
* <LI>KDCOptions.VALIDATE
* </UL>
* <p> Various checks must be made before honoring an option. The restrictions
* on the use of some options are as follows:
* <ol>
* <li> FORWARDABLE, FORWARDED, PROXIABLE, RENEWABLE options may be set in
* subsequent request only if the ticket_granting ticket on which it is based has
* the same options (FORWARDABLE, FORWARDED, PROXIABLE, RENEWABLE) set.
* <li> ALLOW_POSTDATE may be set in subsequent request only if the
* ticket-granting ticket on which it is based also has its MAY_POSTDATE flag set.
* <li> POSTDATED may be set in subsequent request only if the
* ticket-granting ticket on which it is based also has its MAY_POSTDATE flag set.
* <li> RENEWABLE or RENEW may be set in subsequent request only if the
* ticket-granting ticket on which it is based also has its RENEWABLE flag set.
* <li> POXY may be set in subsequent request only if the ticket-granting ticket
* on which it is based also has its PROXIABLE flag set, and the address(es) of
* the host from which the resulting ticket is to be valid should be included
* in the addresses field of the request.
* <li>FORWARDED, PROXY, ENC_TKT_IN_SKEY, RENEW, VALIDATE are used only in
* subsequent requests.
* </ol>
*/
public class KDCOptions extends KerberosFlags {
private static final int KDC_OPT_PROXIABLE = 0x10000000;
private static final int KDC_OPT_RENEWABLE_OK = 0x00000010;
private static final int KDC_OPT_FORWARDABLE = 0x40000000;
// KDC Options
public static final int RESERVED = 0;
public static final int FORWARDABLE = 1;
public static final int FORWARDED = 2;
public static final int PROXIABLE = 3;
public static final int PROXY = 4;
public static final int ALLOW_POSTDATE = 5;
public static final int POSTDATED = 6;
public static final int UNUSED7 = 7;
public static final int RENEWABLE = 8;
public static final int UNUSED9 = 9;
public static final int UNUSED10 = 10;
public static final int UNUSED11 = 11;
public static final int CNAME_IN_ADDL_TKT = 14;
public static final int CANONICALIZE = 15;
public static final int RENEWABLE_OK = 27;
public static final int ENC_TKT_IN_SKEY = 28;
public static final int RENEW = 30;
public static final int VALIDATE = 31;
private static final String[] names = {
"RESERVED", //0
"FORWARDABLE", //1;
"FORWARDED", //2;
"PROXIABLE", //3;
"PROXY", //4;
"ALLOW_POSTDATE", //5;
"POSTDATED", //6;
"UNUSED7", //7;
"RENEWABLE", //8;
"UNUSED9", //9;
"UNUSED10", //10;
"UNUSED11", //11;
null,null,
"CNAME_IN_ADDL_TKT",//14;
"CANONICALIZE", //15;
null,null,null,null,null,null,null,null,null,null,null,
"RENEWABLE_OK", //27;
"ENC_TKT_IN_SKEY", //28;
null,
"RENEW", //30;
"VALIDATE", //31;
};
private boolean DEBUG = Krb5.DEBUG;
public static KDCOptions with(int... flags) {
KDCOptions options = new KDCOptions();
for (int flag: flags) {
options.set(flag, true);
}
return options;
}
public KDCOptions() {
super(Krb5.KDC_OPTS_MAX + 1);
setDefault();
}
public KDCOptions(int size, byte[] data) throws Asn1Exception {
super(size, data);
if ((size > data.length * BITS_PER_UNIT) || (size > Krb5.KDC_OPTS_MAX + 1))
throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH);
}
/**
* Constructs a KDCOptions from the specified bit settings.
*
* @param data the bits to be set for the KDCOptions.
* @exception Asn1Exception if an error occurs while decoding an ASN1
* encoded data.
*
*/
public KDCOptions(boolean[] data) throws Asn1Exception {
super(data);
if (data.length > Krb5.KDC_OPTS_MAX + 1) {
throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH);
}
}
public KDCOptions(DerValue encoding) throws Asn1Exception, IOException {
this(encoding.getUnalignedBitString(true).toBooleanArray());
}
/**
* Constructs a KDCOptions from the passed bit settings.
*
* @param options the bits to be set for the KDCOptions.
*
*/
public KDCOptions(byte[] options) {
super(options.length * BITS_PER_UNIT, options);
}
/**
* Parse (unmarshal) a KDCOptions from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @param data the Der input stream value, which contains one or more
* marshaled value.
* @param explicitTag tag number.
* @param optional indicate if this data field is optional
* @return an instance of KDCOptions.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public static KDCOptions parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
} else {
DerValue subDer = der.getData().getDerValue();
return new KDCOptions(subDer);
}
}
/**
* Sets the value(true/false) for one of the <code>KDCOptions</code>.
*
* @param option an option bit.
* @param value true if the option is selected, false if the option is not selected.
* @exception ArrayIndexOutOfBoundsException if array index out of bound occurs.
* @see sun.security.krb5.internal.Krb5
*/
public void set(int option, boolean value) throws ArrayIndexOutOfBoundsException {
super.set(option, value);
}
/**
* Gets the value(true/false) for one of the <code>KDCOptions</code>.
*
* @param option an option bit.
* @return value true if the option is selected, false if the option is not selected.
* @exception ArrayIndexOutOfBoundsException if array index out of bound occurs.
* @see sun.security.krb5.internal.Krb5
*/
public boolean get(int option) throws ArrayIndexOutOfBoundsException {
return super.get(option);
}
@Override public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("KDCOptions: ");
for (int i=0; i<Krb5.KDC_OPTS_MAX+1; i++) {
if (get(i)) {
if (names[i] != null) {
sb.append(names[i]).append(",");
} else {
sb.append(i).append(",");
}
}
}
return sb.toString();
}
private void setDefault() {
try {
Config config = Config.getInstance();
// If key not present, returns Integer.MIN_VALUE, which is
// almost all zero.
int options = config.getIntValue("libdefaults",
"kdc_default_options");
if ((options & KDC_OPT_RENEWABLE_OK) == KDC_OPT_RENEWABLE_OK) {
set(RENEWABLE_OK, true);
} else {
if (config.getBooleanObject("libdefaults", "renewable") == Boolean.TRUE) {
set(RENEWABLE_OK, true);
}
}
if ((options & KDC_OPT_PROXIABLE) == KDC_OPT_PROXIABLE) {
set(PROXIABLE, true);
} else {
if (config.getBooleanObject("libdefaults", "proxiable") == Boolean.TRUE) {
set(PROXIABLE, true);
}
}
if ((options & KDC_OPT_FORWARDABLE) == KDC_OPT_FORWARDABLE) {
set(FORWARDABLE, true);
} else {
if (config.getBooleanObject("libdefaults", "forwardable") == Boolean.TRUE) {
set(FORWARDABLE, true);
}
}
} catch (KrbException e) {
if (DEBUG) {
System.out.println("Exception in getting default values for " +
"KDC Options from the configuration ");
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,223 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 KDC-REP type.
*
* <pre>{@code
* KDC-REP ::= SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --),
* padata [2] SEQUENCE OF PA-DATA OPTIONAL
* -- NOTE: not empty --,
* crealm [3] Realm,
* cname [4] PrincipalName,
* ticket [5] Ticket,
* enc-part [6] EncryptedData
* -- EncASRepPart or EncTGSRepPart,
* -- as appropriate
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KDCRep {
public PrincipalName cname;
public Ticket ticket;
public EncryptedData encPart;
public EncKDCRepPart encKDCRepPart; //not part of ASN.1 encoding
private int pvno;
private int msgType;
public PAData[] pAData = null; //optional
private boolean DEBUG = Krb5.DEBUG;
public KDCRep(
PAData[] new_pAData,
PrincipalName new_cname,
Ticket new_ticket,
EncryptedData new_encPart,
int req_type) throws IOException {
pvno = Krb5.PVNO;
msgType = req_type;
if (new_pAData != null) {
pAData = new PAData[new_pAData.length];
for (int i = 0; i < new_pAData.length; i++) {
if (new_pAData[i] == null) {
throw new IOException("Cannot create a KDCRep");
} else {
pAData[i] = (PAData) new_pAData[i].clone();
}
}
}
cname = new_cname;
ticket = new_ticket;
encPart = new_encPart;
}
public KDCRep() {
}
public KDCRep(byte[] data, int req_type) throws Asn1Exception,
KrbApErrException, RealmException, IOException {
init(new DerValue(data), req_type);
}
public KDCRep(DerValue encoding, int req_type) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding, req_type);
}
/*
// Not used? Don't know what keyusage to use here %%%
public void decrypt(EncryptionKey key) throws Asn1Exception,
IOException, KrbException, RealmException {
encKDCRepPart = new EncKDCRepPart(encPart.decrypt(key), msgType);
}
*/
/**
* Initializes an KDCRep object.
*
* @param encoding a single DER-encoded value.
* @param req_type reply message type.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while constructing
* a Realm object from DER-encoded data.
* @exception KrbApErrException if the value read from the DER-encoded
* data stream does not match the pre-defined value.
*
*/
protected void init(DerValue encoding, int req_type)
throws Asn1Exception, RealmException, IOException,
KrbApErrException {
DerValue der, subDer;
if ((encoding.getTag() & 0x1F) != req_type) {
if (DEBUG) {
System.out.println(">>> KDCRep: init() " +
"encoding tag is " +
encoding.getTag() +
" req type is " + req_type);
}
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x00) {
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x01) {
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != req_type) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if ((der.getData().peekByte() & 0x1F) == 0x02) {
subDer = der.getData().getDerValue();
DerValue[] padata = subDer.getData().getSequence(1);
pAData = new PAData[padata.length];
for (int i = 0; i < padata.length; i++) {
pAData[i] = new PAData(padata[i]);
}
} else {
pAData = null;
}
Realm crealm = Realm.parse(der.getData(), (byte) 0x03, false);
cname = PrincipalName.parse(der.getData(), (byte) 0x04, false, crealm);
ticket = Ticket.parse(der.getData(), (byte) 0x05, false);
encPart = EncryptedData.parse(der.getData(), (byte) 0x06, false);
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes this object to a byte array.
* @return byte array of encoded APReq object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), temp);
if (pAData != null && pAData.length > 0) {
DerOutputStream padata_stream = new DerOutputStream();
for (int i = 0; i < pAData.length; i++) {
padata_stream.write(pAData[i].asn1Encode());
}
temp = new DerOutputStream();
temp.write(DerValue.tag_SequenceOf, padata_stream);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), temp);
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), cname.getRealm().asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x04), cname.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x05), ticket.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x06), encPart.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
}

View File

@@ -0,0 +1,199 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import java.util.Vector;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 KRB_KDC_REQ type.
*
* <pre>{@code
* KDC-REQ ::= SEQUENCE {
* -- NOTE: first tag is [1], not [0]
* pvno [1] INTEGER (5) ,
* msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --),
* padata [3] SEQUENCE OF PA-DATA OPTIONAL
* -- NOTE: not empty --,
* req-body [4] KDC-REQ-BODY
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KDCReq {
public KDCReqBody reqBody;
public PAData[] pAData = null; //optional
private int pvno;
private int msgType;
public KDCReq(PAData[] new_pAData, KDCReqBody new_reqBody,
int req_type) throws IOException {
pvno = Krb5.PVNO;
msgType = req_type;
if (new_pAData != null) {
pAData = new PAData[new_pAData.length];
for (int i = 0; i < new_pAData.length; i++) {
if (new_pAData[i] == null) {
throw new IOException("Cannot create a KDCRep");
} else {
pAData[i] = (PAData) new_pAData[i].clone();
}
}
}
reqBody = new_reqBody;
}
public KDCReq() {
}
public KDCReq(byte[] data, int req_type) throws Asn1Exception,
IOException, KrbException {
init(new DerValue(data), req_type);
}
/**
* Creates an KDCReq object from a DerValue object and asn1 type.
*
* @param der a DER value of an KDCReq object.
* @param req_type a encoded asn1 type value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbErrException
*/
public KDCReq(DerValue der, int req_type) throws Asn1Exception,
IOException, KrbException {
init(der, req_type);
}
/**
* Initializes a KDCReq object from a DerValue. The DER encoding
* must be in the format specified by the KRB_KDC_REQ ASN.1 notation.
*
* @param encoding a DER-encoded KDCReq object.
* @param req_type an int indicating whether it's KRB_AS_REQ or KRB_TGS_REQ type
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbException if an error occurs while constructing a Realm object,
* or a Krb object from DER-encoded data.
*/
protected void init(DerValue encoding, int req_type) throws Asn1Exception,
IOException, KrbException {
DerValue der, subDer;
BigInteger bint;
if ((encoding.getTag() & 0x1F) != req_type) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x01F) == 0x01) {
bint = subDer.getData().getBigInteger();
this.pvno = bint.intValue();
if (this.pvno != Krb5.PVNO) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x01F) == 0x02) {
bint = subDer.getData().getBigInteger();
this.msgType = bint.intValue();
if (this.msgType != req_type) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
pAData = PAData.parseSequence(der.getData(), (byte) 0x03, true);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x01F) == 0x04) {
DerValue subsubDer = subDer.getData().getDerValue();
reqBody = new KDCReqBody(subsubDer, msgType);
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes this object to a byte array.
*
* @return an byte array of encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream temp, bytes, out;
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), temp);
if (pAData != null && pAData.length > 0) {
temp = new DerOutputStream();
for (int i = 0; i < pAData.length; i++) {
temp.write(pAData[i].asn1Encode());
}
bytes = new DerOutputStream();
bytes.write(DerValue.tag_SequenceOf, temp);
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), bytes);
}
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x04), reqBody.asn1Encode(msgType));
bytes = new DerOutputStream();
bytes.write(DerValue.tag_Sequence, out);
out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
true, (byte) msgType), bytes);
return out.toByteArray();
}
public byte[] asn1EncodeReqBody() throws Asn1Exception, IOException {
return reqBody.asn1Encode(msgType);
}
}

View File

@@ -0,0 +1,282 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 KDC-REQ-BODY type.
*
* <pre>{@code
* KDC-REQ-BODY ::= SEQUENCE {
* kdc-options [0] KDCOptions,
* cname [1] PrincipalName OPTIONAL
* -- Used only in AS-REQ --,
* realm [2] Realm
* -- Server's realm
* -- Also client's in AS-REQ --,
* sname [3] PrincipalName OPTIONAL,
* from [4] KerberosTime OPTIONAL,
* till [5] KerberosTime,
* rtime [6] KerberosTime OPTIONAL,
* nonce [7] UInt32,
* etype [8] SEQUENCE OF Int32 -- EncryptionType
* -- in preference order --,
* addresses [9] HostAddresses OPTIONAL,
* enc-authorization-data [10] EncryptedData OPTIONAL
* -- AuthorizationData --,
* additional-tickets [11] SEQUENCE OF Ticket OPTIONAL
* -- NOTE: not empty
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KDCReqBody {
public KDCOptions kdcOptions;
public PrincipalName cname; //optional in ASReq only
public PrincipalName sname; //optional
public KerberosTime from; //optional
public KerberosTime till;
public KerberosTime rtime; //optional
public HostAddresses addresses; //optional
private int nonce;
private int[] eType = null; //a sequence; not optional
private EncryptedData encAuthorizationData; //optional
private Ticket[] additionalTickets; //optional
public KDCReqBody(
KDCOptions new_kdcOptions,
PrincipalName new_cname, //optional in ASReq only
PrincipalName new_sname, //optional
KerberosTime new_from, //optional
KerberosTime new_till,
KerberosTime new_rtime, //optional
int new_nonce,
int[] new_eType, //a sequence; not optional
HostAddresses new_addresses, //optional
EncryptedData new_encAuthorizationData, //optional
Ticket[] new_additionalTickets //optional
) throws IOException {
kdcOptions = new_kdcOptions;
cname = new_cname;
sname = new_sname;
from = new_from;
till = new_till;
rtime = new_rtime;
nonce = new_nonce;
if (new_eType != null) {
eType = new_eType.clone();
}
addresses = new_addresses;
encAuthorizationData = new_encAuthorizationData;
if (new_additionalTickets != null) {
additionalTickets = new Ticket[new_additionalTickets.length];
for (int i = 0; i < new_additionalTickets.length; i++) {
if (new_additionalTickets[i] == null) {
throw new IOException("Cannot create a KDCReqBody");
} else {
additionalTickets[i] = (Ticket)new_additionalTickets[i].clone();
}
}
}
}
/**
* Constructs a KDCReqBody object.
* @param encoding a DER-encoded data.
* @param msgType an int indicating whether it's KRB_AS_REQ or KRB_TGS_REQ type.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while constructing a Realm object from the encoded data.
*
*/
public KDCReqBody(DerValue encoding, int msgType)
throws Asn1Exception, RealmException, KrbException, IOException {
DerValue der, subDer;
addresses = null;
encAuthorizationData = null;
additionalTickets = null;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
kdcOptions = KDCOptions.parse(encoding.getData(), (byte)0x00, false);
// cname only appears in AS-REQ and it shares the realm field with
// sname. This is the only place where realm comes after the name.
// We first give cname a fake realm and reassign it the correct
// realm after the realm field is read.
cname = PrincipalName.parse(encoding.getData(), (byte)0x01, true,
new Realm("PLACEHOLDER"));
if ((msgType != Krb5.KRB_AS_REQ) && (cname != null)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
Realm realm = Realm.parse(encoding.getData(), (byte)0x02, false);
if (cname != null) {
cname = new PrincipalName(
cname.getNameType(), cname.getNameStrings(), realm);
}
sname = PrincipalName.parse(encoding.getData(), (byte)0x03, true, realm);
from = KerberosTime.parse(encoding.getData(), (byte)0x04, true);
till = KerberosTime.parse(encoding.getData(), (byte)0x05, false);
rtime = KerberosTime.parse(encoding.getData(), (byte)0x06, true);
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x07) {
nonce = der.getData().getBigInteger().intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
Vector<Integer> v = new Vector<>();
if ((der.getTag() & (byte)0x1F) == (byte)0x08) {
subDer = der.getData().getDerValue();
if (subDer.getTag() == DerValue.tag_SequenceOf) {
while(subDer.getData().available() > 0) {
v.addElement(subDer.getData().getBigInteger().intValue());
}
eType = new int[v.size()];
for (int i = 0; i < v.size(); i++) {
eType[i] = v.elementAt(i);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (encoding.getData().available() > 0) {
addresses = HostAddresses.parse(encoding.getData(), (byte)0x09, true);
}
if (encoding.getData().available() > 0) {
encAuthorizationData = EncryptedData.parse(encoding.getData(), (byte)0x0A, true);
}
if (encoding.getData().available() > 0) {
Vector<Ticket> tempTickets = new Vector<>();
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x0B) {
subDer = der.getData().getDerValue();
if (subDer.getTag() == DerValue.tag_SequenceOf) {
while (subDer.getData().available() > 0) {
tempTickets.addElement(new Ticket(subDer.getData().getDerValue()));
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (tempTickets.size() > 0) {
additionalTickets = new Ticket[tempTickets.size()];
tempTickets.copyInto(additionalTickets);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
if (encoding.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes this object to an OutputStream.
*
* @return an byte array of encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*
*/
public byte[] asn1Encode(int msgType) throws Asn1Exception, IOException {
Vector<DerValue> v = new Vector<>();
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), kdcOptions.asn1Encode()));
if (msgType == Krb5.KRB_AS_REQ) {
if (cname != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), cname.asn1Encode()));
}
}
if (sname != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), sname.getRealm().asn1Encode()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), sname.asn1Encode()));
} else if (cname != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), cname.getRealm().asn1Encode()));
}
if (from != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), from.asn1Encode()));
}
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x05), till.asn1Encode()));
if (rtime != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x06), rtime.asn1Encode()));
}
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(nonce));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), temp.toByteArray()));
//revisit, if empty eType sequences are allowed
temp = new DerOutputStream();
for (int i = 0; i < eType.length; i++) {
temp.putInteger(BigInteger.valueOf(eType[i]));
}
DerOutputStream eTypetemp = new DerOutputStream();
eTypetemp.write(DerValue.tag_SequenceOf, temp);
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x08), eTypetemp.toByteArray()));
if (addresses != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x09), addresses.asn1Encode()));
}
if (encAuthorizationData != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), encAuthorizationData.asn1Encode()));
}
if (additionalTickets != null && additionalTickets.length > 0) {
temp = new DerOutputStream();
for (int i = 0; i < additionalTickets.length; i++) {
temp.write(additionalTickets[i].asn1Encode());
}
DerOutputStream ticketsTemp = new DerOutputStream();
ticketsTemp.write(DerValue.tag_SequenceOf, temp);
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0B), ticketsTemp.toByteArray()));
}
DerValue der[] = new DerValue[v.size()];
v.copyInto(der);
temp = new DerOutputStream();
temp.putSequence(der);
return temp.toByteArray();
}
public int getNonce() {
return nonce;
}
}

View File

@@ -0,0 +1,189 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.RealmException;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 Authenticator type.
*
* <pre>{@code
* KRB-CRED ::= [APPLICATION 22] SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (22),
* tickets [2] SEQUENCE OF Ticket,
* enc-part [3] EncryptedData -- EncKrbCredPart
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KRBCred {
public Ticket[] tickets = null;
public EncryptedData encPart;
private int pvno;
private int msgType;
public KRBCred(Ticket[] new_tickets, EncryptedData new_encPart) throws IOException {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_CRED;
if (new_tickets != null) {
tickets = new Ticket[new_tickets.length];
for (int i = 0; i < new_tickets.length; i++) {
if (new_tickets[i] == null) {
throw new IOException("Cannot create a KRBCred");
} else {
tickets[i] = (Ticket) new_tickets[i].clone();
}
}
}
encPart = new_encPart;
}
public KRBCred(byte[] data) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(new DerValue(data));
}
public KRBCred(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding);
}
/**
* Initializes an KRBCred object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data
* stream does not match the pre-defined value.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private void init(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x16)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
DerValue der, subDer;
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x00) {
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x01) {
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != Krb5.KRB_CRED) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x02) {
DerValue subsubDer = subDer.getData().getDerValue();
if (subsubDer.getTag() != DerValue.tag_SequenceOf) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
Vector<Ticket> v = new Vector<>();
while (subsubDer.getData().available() > 0) {
v.addElement(new Ticket(subsubDer.getData().getDerValue()));
}
if (v.size() > 0) {
tickets = new Ticket[v.size()];
v.copyInto(tickets);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
encPart = EncryptedData.parse(der.getData(), (byte) 0x03, false);
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Encodes an KRBCred object.
* @return the data of encoded EncAPRepPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream temp, bytes, out;
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), temp);
temp = new DerOutputStream();
for (int i = 0; i < tickets.length; i++) {
temp.write(tickets[i].asn1Encode());
}
bytes = new DerOutputStream();
bytes.write(DerValue.tag_SequenceOf, temp);
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), bytes);
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), encPart.asn1Encode());
bytes = new DerOutputStream();
bytes.write(DerValue.tag_Sequence, out);
out = new DerOutputStream();
out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
true, (byte) 0x16), bytes);
return out.toByteArray();
}
}

View File

@@ -0,0 +1,532 @@
/*
* Copyright (c) 2000, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import java.io.ObjectOutputStream;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.Checksum;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.Realm;
import sun.security.krb5.RealmException;
import sun.security.util.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import sun.security.krb5.internal.util.KerberosString;
/**
* Implements the ASN.1 KRBError type.
*
* <pre>{@code
* KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (30),
* ctime [2] KerberosTime OPTIONAL,
* cusec [3] Microseconds OPTIONAL,
* stime [4] KerberosTime,
* susec [5] Microseconds,
* error-code [6] Int32,
* crealm [7] Realm OPTIONAL,
* cname [8] PrincipalName OPTIONAL,
* realm [9] Realm -- service realm --,
* sname [10] PrincipalName -- service name --,
* e-text [11] KerberosString OPTIONAL,
* e-data [12] OCTET STRING OPTIONAL
* }
*
* METHOD-DATA ::= SEQUENCE OF PA-DATA
*
* TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
* data-type [0] Int32,
* data-value [1] OCTET STRING OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KRBError implements java.io.Serializable {
static final long serialVersionUID = 3643809337475284503L;
private int pvno;
private int msgType;
private KerberosTime cTime; //optional
private Integer cuSec; //optional
private KerberosTime sTime;
private Integer suSec;
private int errorCode;
private Realm crealm; //optional
private PrincipalName cname; //optional
private PrincipalName sname;
private String eText; //optional
private byte[] eData; //optional
private Checksum eCksum; //optional
private PAData[] pa; // PA-DATA in eData
private static boolean DEBUG = Krb5.DEBUG;
private void readObject(ObjectInputStream is)
throws IOException, ClassNotFoundException {
try {
init(new DerValue((byte[])is.readObject()));
parseEData(eData);
} catch (Exception e) {
throw new IOException(e);
}
}
private void writeObject(ObjectOutputStream os)
throws IOException {
try {
os.writeObject(asn1Encode());
} catch (Exception e) {
throw new IOException(e);
}
}
public KRBError(
APOptions new_apOptions,
KerberosTime new_cTime,
Integer new_cuSec,
KerberosTime new_sTime,
Integer new_suSec,
int new_errorCode,
PrincipalName new_cname,
PrincipalName new_sname,
String new_eText,
byte[] new_eData
) throws IOException, Asn1Exception {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_ERROR;
cTime = new_cTime;
cuSec = new_cuSec;
sTime = new_sTime;
suSec = new_suSec;
errorCode = new_errorCode;
crealm = new_cname != null ? new_cname.getRealm() : null;
cname = new_cname;
sname = new_sname;
eText = new_eText;
eData = new_eData;
parseEData(eData);
}
public KRBError(
APOptions new_apOptions,
KerberosTime new_cTime,
Integer new_cuSec,
KerberosTime new_sTime,
Integer new_suSec,
int new_errorCode,
PrincipalName new_cname,
PrincipalName new_sname,
String new_eText,
byte[] new_eData,
Checksum new_eCksum
) throws IOException, Asn1Exception {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_ERROR;
cTime = new_cTime;
cuSec = new_cuSec;
sTime = new_sTime;
suSec = new_suSec;
errorCode = new_errorCode;
crealm = new_cname != null ? new_cname.getRealm() : null;
cname = new_cname;
sname = new_sname;
eText = new_eText;
eData = new_eData;
eCksum = new_eCksum;
parseEData(eData);
}
public KRBError(byte[] data) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(new DerValue(data));
parseEData(eData);
}
public KRBError(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding);
showDebug();
parseEData(eData);
}
/*
* Attention:
*
* According to RFC 4120, e-data field in a KRB-ERROR message is
* a METHOD-DATA when errorCode is KDC_ERR_PREAUTH_REQUIRED,
* and application-specific otherwise (The RFC suggests using
* TYPED-DATA).
*
* Hence, the ideal procedure to parse e-data should look like:
*
* if (errorCode is KDC_ERR_PREAUTH_REQUIRED) {
* parse as METHOD-DATA
* } else {
* try parsing as TYPED-DATA
* }
*
* Unfortunately, we know that some implementations also use the
* METHOD-DATA format for errorcode KDC_ERR_PREAUTH_FAILED, and
* do not use the TYPED-DATA for other errorcodes (say,
* KDC_ERR_CLIENT_REVOKED).
*/
// parse the edata field
private void parseEData(byte[] data) throws IOException {
if (data == null) {
return;
}
// We need to parse eData as METHOD-DATA for both errorcodes.
if (errorCode == Krb5.KDC_ERR_PREAUTH_REQUIRED
|| errorCode == Krb5.KDC_ERR_PREAUTH_FAILED) {
try {
// RFC 4120 does not guarantee that eData is METHOD-DATA when
// errorCode is KDC_ERR_PREAUTH_FAILED. Therefore, the parse
// may fail.
parsePAData(data);
} catch (Exception e) {
if (DEBUG) {
System.out.println("Unable to parse eData field of KRB-ERROR:\n" +
new sun.misc.HexDumpEncoder().encodeBuffer(data));
}
IOException ioe = new IOException(
"Unable to parse eData field of KRB-ERROR");
ioe.initCause(e);
throw ioe;
}
} else {
if (DEBUG) {
System.out.println("Unknown eData field of KRB-ERROR:\n" +
new sun.misc.HexDumpEncoder().encodeBuffer(data));
}
}
}
/**
* Try parsing the data as a sequence of PA-DATA.
* @param data the data block
*/
private void parsePAData(byte[] data)
throws IOException, Asn1Exception {
DerValue derPA = new DerValue(data);
List<PAData> paList = new ArrayList<>();
while (derPA.data.available() > 0) {
// read the PA-DATA
DerValue tmp = derPA.data.getDerValue();
PAData pa_data = new PAData(tmp);
paList.add(pa_data);
if (DEBUG) {
System.out.println(pa_data);
}
}
pa = paList.toArray(new PAData[paList.size()]);
}
public final Realm getClientRealm() {
return crealm;
}
public final KerberosTime getServerTime() {
return sTime;
}
public final KerberosTime getClientTime() {
return cTime;
}
public final Integer getServerMicroSeconds() {
return suSec;
}
public final Integer getClientMicroSeconds() {
return cuSec;
}
public final int getErrorCode() {
return errorCode;
}
// access pre-auth info
public final PAData[] getPA() {
return pa;
}
public final String getErrorString() {
return eText;
}
/**
* Initializes a KRBError object.
* @param encoding a DER-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data
* stream does not match the pre-defined value.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private void init(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
DerValue der, subDer;
if (((encoding.getTag() & (byte)0x1F) != (byte)0x1E)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte)0x1F) == (byte)0x00) {
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO)
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte)0x1F) == (byte)0x01) {
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != Krb5.KRB_ERROR) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
cTime = KerberosTime.parse(der.getData(), (byte)0x02, true);
if ((der.getData().peekByte() & 0x1F) == 0x03) {
subDer = der.getData().getDerValue();
cuSec = new Integer(subDer.getData().getBigInteger().intValue());
}
else cuSec = null;
sTime = KerberosTime.parse(der.getData(), (byte)0x04, false);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte)0x1F) == (byte)0x05) {
suSec = new Integer (subDer.getData().getBigInteger().intValue());
}
else throw new Asn1Exception(Krb5.ASN1_BAD_ID);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte)0x1F) == (byte)0x06) {
errorCode = subDer.getData().getBigInteger().intValue();
}
else throw new Asn1Exception(Krb5.ASN1_BAD_ID);
crealm = Realm.parse(der.getData(), (byte)0x07, true);
cname = PrincipalName.parse(der.getData(), (byte)0x08, true, crealm);
Realm realm = Realm.parse(der.getData(), (byte)0x09, false);
sname = PrincipalName.parse(der.getData(), (byte)0x0A, false, realm);
eText = null;
eData = null;
eCksum = null;
if (der.getData().available() >0) {
if ((der.getData().peekByte() & 0x1F) == 0x0B) {
subDer = der.getData().getDerValue();
eText = new KerberosString(subDer.getData().getDerValue())
.toString();
}
}
if (der.getData().available() >0) {
if ((der.getData().peekByte() & 0x1F) == 0x0C) {
subDer = der.getData().getDerValue();
eData = subDer.getData().getOctetString();
}
}
if (der.getData().available() >0) {
eCksum = Checksum.parse(der.getData(), (byte)0x0D, true);
}
if (der.getData().available() >0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* For debug use only
*/
private void showDebug() {
if (DEBUG) {
System.out.println(">>>KRBError:");
if (cTime != null)
System.out.println("\t cTime is " + cTime.toDate().toString() + " " + cTime.toDate().getTime());
if (cuSec != null) {
System.out.println("\t cuSec is " + cuSec.intValue());
}
System.out.println("\t sTime is " + sTime.toDate().toString
() + " " + sTime.toDate().getTime());
System.out.println("\t suSec is " + suSec);
System.out.println("\t error code is " + errorCode);
System.out.println("\t error Message is " + Krb5.getErrorMessage(errorCode));
if (crealm != null) {
System.out.println("\t crealm is " + crealm.toString());
}
if (cname != null) {
System.out.println("\t cname is " + cname.toString());
}
if (sname != null) {
System.out.println("\t sname is " + sname.toString());
}
if (eData != null) {
System.out.println("\t eData provided.");
}
if (eCksum != null) {
System.out.println("\t checksum provided.");
}
System.out.println("\t msgType is " + msgType);
}
}
/**
* Encodes an KRBError object.
* @return the byte array of encoded KRBError object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream temp = new DerOutputStream();
DerOutputStream bytes = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
if (cTime != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), cTime.asn1Encode());
}
if (cuSec != null) {
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(cuSec.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), temp);
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), sTime.asn1Encode());
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(suSec.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x05), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(errorCode));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x06), temp);
if (crealm != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), crealm.asn1Encode());
}
if (cname != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x08), cname.asn1Encode());
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x09), sname.getRealm().asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), sname.asn1Encode());
if (eText != null) {
temp = new DerOutputStream();
temp.putDerValue(new KerberosString(eText).toDerValue());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0B), temp);
}
if (eData != null) {
temp = new DerOutputStream();
temp.putOctetString(eData);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0C), temp);
}
if (eCksum != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0D), eCksum.asn1Encode());
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte)0x1E), temp);
return bytes.toByteArray();
}
@Override public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof KRBError)) {
return false;
}
KRBError other = (KRBError)obj;
return pvno == other.pvno &&
msgType == other.msgType &&
isEqual(cTime, other.cTime) &&
isEqual(cuSec, other.cuSec) &&
isEqual(sTime, other.sTime) &&
isEqual(suSec, other.suSec) &&
errorCode == other.errorCode &&
isEqual(crealm, other.crealm) &&
isEqual(cname, other.cname) &&
isEqual(sname, other.sname) &&
isEqual(eText, other.eText) &&
java.util.Arrays.equals(eData, other.eData) &&
isEqual(eCksum, other.eCksum);
}
private static boolean isEqual(Object a, Object b) {
return (a == null)?(b == null):(a.equals(b));
}
@Override public int hashCode() {
int result = 17;
result = 37 * result + pvno;
result = 37 * result + msgType;
if (cTime != null) result = 37 * result + cTime.hashCode();
if (cuSec != null) result = 37 * result + cuSec.hashCode();
if (sTime != null) result = 37 * result + sTime.hashCode();
if (suSec != null) result = 37 * result + suSec.hashCode();
result = 37 * result + errorCode;
if (crealm != null) result = 37 * result + crealm.hashCode();
if (cname != null) result = 37 * result + cname.hashCode();
if (sname != null) result = 37 * result + sname.hashCode();
if (eText != null) result = 37 * result + eText.hashCode();
result = 37 * result + Arrays.hashCode(eData);
if (eCksum != null) result = 37 * result + eCksum.hashCode();
return result;
}
}

View File

@@ -0,0 +1,143 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 KRB-PRIV type.
*
* <pre>{@code
* KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (21),
* -- NOTE: there is no [2] tag
* enc-part [3] EncryptedData -- EncKrbPrivPart
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KRBPriv {
public int pvno;
public int msgType;
public EncryptedData encPart;
public KRBPriv(EncryptedData new_encPart) {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_PRIV;
encPart = new_encPart;
}
public KRBPriv(byte[] data) throws Asn1Exception,
KrbApErrException, IOException {
init(new DerValue(data));
}
public KRBPriv(DerValue encoding) throws Asn1Exception,
KrbApErrException, IOException {
init(encoding);
}
/**
* Initializes an KRBPriv object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data
* stream does not match the pre-defined value.
*/
private void init(DerValue encoding) throws Asn1Exception,
KrbApErrException, IOException {
DerValue der, subDer;
if (((encoding.getTag() & (byte)0x1F) != (byte)0x15)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true))
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x00) {
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x01) {
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != Krb5.KRB_PRIV)
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
encPart = EncryptedData.parse(der.getData(), (byte)0x03, false);
if (der.getData().available() >0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes an KRBPriv object.
* @return byte array of encoded EncAPRepPart object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream temp, bytes;
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), encPart.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte)0x15), temp);
return bytes.toByteArray();
}
}

View File

@@ -0,0 +1,146 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Checksum;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.RealmException;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 KRBSafe type.
*
* <pre>{@code
* KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (20),
* safe-body [2] KRB-SAFE-BODY,
* cksum [3] Checksum
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specifications available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KRBSafe {
public int pvno;
public int msgType;
public KRBSafeBody safeBody;
public Checksum cksum;
public KRBSafe(KRBSafeBody new_safeBody, Checksum new_cksum) {
pvno = Krb5.PVNO;
msgType = Krb5.KRB_SAFE;
safeBody = new_safeBody;
cksum = new_cksum;
}
public KRBSafe(byte[] data) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(new DerValue(data));
}
public KRBSafe(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding);
}
/**
* Initializes an KRBSafe object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while parsing a Realm object.
* @exception KrbApErrException if the value read from the DER-encoded data
* stream does not match the pre-defined value.
*/
private void init(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
DerValue der, subDer;
if (((encoding.getTag() & (byte)0x1F) != (byte)0x14)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true))
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x00) {
pvno = subDer.getData().getBigInteger().intValue();
if (pvno != Krb5.PVNO)
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & 0x1F) == 0x01) {
msgType = subDer.getData().getBigInteger().intValue();
if (msgType != Krb5.KRB_SAFE)
throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE);
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
safeBody = KRBSafeBody.parse(der.getData(), (byte)0x02, false);
cksum = Checksum.parse(der.getData(), (byte)0x03, false);
if (der.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes an KRBSafe object.
* @return byte array of encoded KRBSafe object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream temp = new DerOutputStream();
DerOutputStream bytes = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pvno));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(msgType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), safeBody.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), cksum.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte)0x14), temp);
return bytes.toByteArray();
}
}

View File

@@ -0,0 +1,177 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 KRBSafeBody type.
*
* <pre>{@code
* KRB-SAFE-BODY ::= SEQUENCE {
* user-data [0] OCTET STRING,
* timestamp [1] KerberosTime OPTIONAL,
* usec [2] Microseconds OPTIONAL,
* seq-number [3] UInt32 OPTIONAL,
* s-address [4] HostAddress,
* r-address [5] HostAddress OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KRBSafeBody {
public byte[] userData = null;
public KerberosTime timestamp; //optional
public Integer usec; //optional
public Integer seqNumber; //optional
public HostAddress sAddress;
public HostAddress rAddress; //optional
public KRBSafeBody(
byte[] new_userData,
KerberosTime new_timestamp,
Integer new_usec,
Integer new_seqNumber,
HostAddress new_sAddress,
HostAddress new_rAddress
) {
if (new_userData != null) {
userData = new_userData.clone();
}
timestamp = new_timestamp;
usec = new_usec;
seqNumber = new_seqNumber;
sAddress = new_sAddress;
rAddress = new_rAddress;
}
/**
* Constructs a KRBSafeBody object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public KRBSafeBody(DerValue encoding) throws Asn1Exception, IOException {
DerValue der;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
userData = der.getData().getOctetString();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
timestamp = KerberosTime.parse(encoding.getData(), (byte)0x01, true);
if ((encoding.getData().peekByte() & 0x1F) == 0x02) {
der = encoding.getData().getDerValue();
usec = new Integer(der.getData().getBigInteger().intValue());
}
if ((encoding.getData().peekByte() & 0x1F) == 0x03) {
der = encoding.getData().getDerValue();
seqNumber = new Integer(der.getData().getBigInteger().intValue());
}
sAddress = HostAddress.parse(encoding.getData(), (byte)0x04, false);
if (encoding.getData().available() > 0)
rAddress = HostAddress.parse(encoding.getData(), (byte)0x05, true);
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes an KRBSafeBody object.
* @return the byte array of encoded KRBSafeBody object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putOctetString(userData);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
if (timestamp != null)
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), timestamp.asn1Encode());
if (usec != null) {
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(usec.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), temp);
}
if (seqNumber != null) {
temp = new DerOutputStream();
// encode as an unsigned integer (UInt32)
temp.putInteger(BigInteger.valueOf(seqNumber.longValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), temp);
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), sAddress.asn1Encode());
if (rAddress != null)
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Parse (unmarshal) a KRBSafeBody from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional
* @return an instance of KRBSafeBody.
*
*/
public static KRBSafeBody parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F))
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
else {
DerValue subDer = der.getData().getDerValue();
return new KRBSafeBody(subDer);
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2000, 2004, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
public class KdcErrException extends sun.security.krb5.KrbException {
private static final long serialVersionUID = -8788186031117310306L;
public KdcErrException(int i) {
super(i);
}
public KdcErrException(int i, String s) {
super(i, s);
}
}

View File

@@ -0,0 +1,315 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.Config;
import sun.security.krb5.KrbException;
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import java.io.IOException;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* Implements the ASN.1 KerberosTime type. This is an immutable class.
*
* {@code KerberosTime ::= GeneralizedTime} -- with no fractional seconds
*
* The timestamps used in Kerberos are encoded as GeneralizedTimes. A
* KerberosTime value shall not include any fractional portions of the
* seconds. As required by the DER, it further shall not include any
* separators, and it shall specify the UTC time zone (Z).
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*
* The implementation also includes the microseconds info so that the
* same class can be used as a precise timestamp in Authenticator etc.
*/
public class KerberosTime {
private final long kerberosTime; // milliseconds since epoch, Date.getTime()
private final int microSeconds; // last 3 digits of the real microsecond
// The time when this class is loaded. Used in setNow()
private static long initMilli = System.currentTimeMillis();
private static long initMicro = System.nanoTime() / 1000;
private static boolean DEBUG = Krb5.DEBUG;
// Do not make this public. It's a little confusing that micro
// is only the last 3 digits of microsecond.
private KerberosTime(long time, int micro) {
kerberosTime = time;
microSeconds = micro;
}
/**
* Creates a KerberosTime object from milliseconds since epoch.
*/
public KerberosTime(long time) {
this(time, 0);
}
// This constructor is used in the native code
// src/windows/native/sun/security/krb5/NativeCreds.c
public KerberosTime(String time) throws Asn1Exception {
this(toKerberosTime(time), 0);
}
private static long toKerberosTime(String time) throws Asn1Exception {
// ASN.1 GeneralizedTime format:
// "19700101000000Z"
// | | | | | | |
// 0 4 6 8 | | |
// 10 | |
// 12 |
// 14
if (time.length() != 15)
throw new Asn1Exception(Krb5.ASN1_BAD_TIMEFORMAT);
if (time.charAt(14) != 'Z')
throw new Asn1Exception(Krb5.ASN1_BAD_TIMEFORMAT);
int year = Integer.parseInt(time.substring(0, 4));
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.clear(); // so that millisecond is zero
calendar.set(year,
Integer.parseInt(time.substring(4, 6)) - 1,
Integer.parseInt(time.substring(6, 8)),
Integer.parseInt(time.substring(8, 10)),
Integer.parseInt(time.substring(10, 12)),
Integer.parseInt(time.substring(12, 14)));
return calendar.getTimeInMillis();
}
/**
* Creates a KerberosTime object from a Date object.
*/
public KerberosTime(Date time) {
this(time.getTime(), 0);
}
/**
* Creates a KerberosTime object from an Instant object
*/
public KerberosTime(Instant instant) {
this(instant.getEpochSecond()*1000 + instant.getNano()/1000000L,
instant.getNano()/1000%1000);
}
/**
* Creates a KerberosTime object for now. It uses System.nanoTime()
* to get a more precise time than "new Date()".
*/
public static KerberosTime now() {
long newMilli = System.currentTimeMillis();
long newMicro = System.nanoTime() / 1000;
long microElapsed = newMicro - initMicro;
long calcMilli = initMilli + microElapsed/1000;
if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
if (DEBUG) {
System.out.println("System time adjusted");
}
initMilli = newMilli;
initMicro = newMicro;
return new KerberosTime(newMilli, 0);
} else {
return new KerberosTime(calcMilli, (int)(microElapsed % 1000));
}
}
/**
* Returns a string representation of KerberosTime object.
* @return a string representation of this object.
*/
public String toGeneralizedTimeString() {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.clear();
calendar.setTimeInMillis(kerberosTime);
return String.format("%04d%02d%02d%02d%02d%02dZ",
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DAY_OF_MONTH),
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND));
}
/**
* Encodes this object to a byte array.
* @return a byte array of encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream out = new DerOutputStream();
out.putGeneralizedTime(this.toDate());
return out.toByteArray();
}
public long getTime() {
return kerberosTime;
}
public Date toDate() {
return new Date(kerberosTime);
}
public int getMicroSeconds() {
Long temp_long = new Long((kerberosTime % 1000L) * 1000L);
return temp_long.intValue() + microSeconds;
}
/**
* Returns a new KerberosTime object with the original seconds
* and the given microseconds.
*/
public KerberosTime withMicroSeconds(int usec) {
return new KerberosTime(
kerberosTime - kerberosTime%1000L + usec/1000L,
usec%1000);
}
private boolean inClockSkew(int clockSkew) {
return java.lang.Math.abs(kerberosTime - System.currentTimeMillis())
<= clockSkew * 1000L;
}
public boolean inClockSkew() {
return inClockSkew(getDefaultSkew());
}
public boolean greaterThanWRTClockSkew(KerberosTime time, int clockSkew) {
if ((kerberosTime - time.kerberosTime) > clockSkew * 1000L)
return true;
return false;
}
public boolean greaterThanWRTClockSkew(KerberosTime time) {
return greaterThanWRTClockSkew(time, getDefaultSkew());
}
public boolean greaterThan(KerberosTime time) {
return kerberosTime > time.kerberosTime ||
kerberosTime == time.kerberosTime &&
microSeconds > time.microSeconds;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof KerberosTime)) {
return false;
}
return kerberosTime == ((KerberosTime)obj).kerberosTime &&
microSeconds == ((KerberosTime)obj).microSeconds;
}
public int hashCode() {
int result = 37 * 17 + (int)(kerberosTime ^ (kerberosTime >>> 32));
return result * 17 + microSeconds;
}
public boolean isZero() {
return kerberosTime == 0 && microSeconds == 0;
}
public int getSeconds() {
Long temp_long = new Long(kerberosTime / 1000L);
return temp_long.intValue();
}
/**
* Parse (unmarshal) a kerberostime from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @param data the Der input stream value, which contains
* one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional
* @return an instance of KerberosTime.
*
*/
public static KerberosTime parse(
DerInputStream data, byte explicitTag, boolean optional)
throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F)!= explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
else {
DerValue subDer = der.getData().getDerValue();
Date temp = subDer.getGeneralizedTime();
return new KerberosTime(temp.getTime(), 0);
}
}
public static int getDefaultSkew() {
int tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
try {
if ((tdiff = Config.getInstance().getIntValue(
"libdefaults", "clockskew"))
== Integer.MIN_VALUE) { //value is not defined
tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
}
} catch (KrbException e) {
if (DEBUG) {
System.out.println("Exception in getting clockskew from " +
"Configuration " +
"using default value " +
e.getMessage());
}
}
return tdiff;
}
public String toString() {
return toGeneralizedTimeString();
}
}

View File

@@ -0,0 +1,399 @@
/*
* Copyright (c) 2000, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import java.util.Hashtable;
// Constants and other defined values from RFC 4120
public class Krb5 {
//Recommended KDC values
public static final int DEFAULT_ALLOWABLE_CLOCKSKEW = 5 * 60; //5 minutes
public static final int DEFAULT_MINIMUM_LIFETIME = 5 * 60; //5 minutes
public static final int DEFAULT_MAXIMUM_RENEWABLE_LIFETIME = 7 * 24 * 60 * 60; //1 week
public static final int DEFAULT_MAXIMUM_TICKET_LIFETIME = 24 * 60 * 60; //1 day
public static final boolean DEFAULT_FORWARDABLE_ALLOWED = true;
public static final boolean DEFAULT_PROXIABLE_ALLOWED = true;
public static final boolean DEFAULT_POSTDATE_ALLOWED = true;
public static final boolean DEFAULT_RENEWABLE_ALLOWED = true;
public static final boolean AP_EMPTY_ADDRESSES_ALLOWED = true;
//AP_REQ Options
public static final int AP_OPTS_RESERVED = 0;
public static final int AP_OPTS_USE_SESSION_KEY = 1;
public static final int AP_OPTS_MUTUAL_REQUIRED = 2;
public static final int AP_OPTS_MAX = 31;
//Ticket Flags
public static final int TKT_OPTS_RESERVED = 0;
public static final int TKT_OPTS_FORWARDABLE = 1;
public static final int TKT_OPTS_FORWARDED = 2;
public static final int TKT_OPTS_PROXIABLE = 3;
public static final int TKT_OPTS_PROXY = 4;
public static final int TKT_OPTS_MAY_POSTDATE = 5;
public static final int TKT_OPTS_POSTDATED = 6;
public static final int TKT_OPTS_INVALID = 7;
public static final int TKT_OPTS_RENEWABLE = 8;
public static final int TKT_OPTS_INITIAL = 9;
public static final int TKT_OPTS_PRE_AUTHENT = 10;
public static final int TKT_OPTS_HW_AUTHENT = 11;
public static final int TKT_OPTS_DELEGATE = 13;
public static final int TKT_OPTS_ENC_PA_REP = 15;
public static final int TKT_OPTS_MAX = 31;
// KDC Options
// (option values defined in KDCOptions.java)
public static final int KDC_OPTS_MAX = 31;
// KerberosFlags
public static final int KRB_FLAGS_MAX = 31;
//Last Request types
public static final int LRTYPE_NONE = 0;
public static final int LRTYPE_TIME_OF_INITIAL_TGT = 1;
public static final int LRTYPE_TIME_OF_INITIAL_REQ = 2;
public static final int LRTYPE_TIME_OF_NEWEST_TGT = 3;
public static final int LRTYPE_TIME_OF_LAST_RENEWAL = 4;
public static final int LRTYPE_TIME_OF_LAST_REQ = 5;
//Host address lengths
public static final int ADDR_LEN_INET = 4;
public static final int ADDR_LEN_CHAOS = 2;
public static final int ADDR_LEN_OSI = 0; //means variable
public static final int ADDR_LEN_XNS = 6;
public static final int ADDR_LEN_APPLETALK = 3;
public static final int ADDR_LEN_DECNET = 2;
//Host address types
public static final int ADDRTYPE_UNIX = 1; // Local
public static final int ADDRTYPE_INET = 2; // Internet
public static final int ADDRTYPE_IMPLINK = 3; // Arpanet
public static final int ADDRTYPE_PUP = 4; // PUP
public static final int ADDRTYPE_CHAOS = 5; // CHAOS
public static final int ADDRTYPE_XNS = 6; // XEROX Network Services
public static final int ADDRTYPE_IPX = 6; // IPX
public static final int ADDRTYPE_ISO = 7; // ISO
public static final int ADDRTYPE_ECMA = 8; // European Computer Manufacturers
public static final int ADDRTYPE_DATAKIT = 9; // Datakit
public static final int ADDRTYPE_CCITT = 10; // CCITT
public static final int ADDRTYPE_SNA = 11; // SNA
public static final int ADDRTYPE_DECNET = 12; // DECnet
public static final int ADDRTYPE_DLI = 13; // Direct Data Link Interface
public static final int ADDRTYPE_LAT = 14; // LAT
public static final int ADDRTYPE_HYLINK = 15; // NSC Hyperchannel
public static final int ADDRTYPE_APPLETALK = 16; // AppleTalk
public static final int ADDRTYPE_NETBIOS = 17; // NetBios
public static final int ADDRTYPE_VOICEVIEW = 18; // VoiceView
public static final int ADDRTYPE_FIREFOX = 19; // Firefox
public static final int ADDRTYPE_BAN = 21; // Banyan
public static final int ADDRTYPE_ATM = 22; // ATM
public static final int ADDRTYPE_INET6 = 24; // Internet Protocol V6
//IP Transport UDP Port for KDC Messages
public static final int KDC_INET_DEFAULT_PORT = 88;
// number of retries before giving up
public static final int KDC_RETRY_LIMIT = 3;
public static final int KDC_DEFAULT_UDP_PREF_LIMIT = 1465;
public static final int KDC_HARD_UDP_LIMIT = 32700;
//OSI authentication mechanism OID
//public static final int[] OSI_AUTH_MECH_TYPE = { /*iso*/ 1, /*org*/ 3,
// /*dod*/ 5, /*internet*/ 1, /*security*/ 5, /*kerberosv5*/ 2 };
//Protocol constants and associated values
//Key Types
public static final int KEYTYPE_NULL = 0;
public static final int KEYTYPE_DES = 1;
public static final int KEYTYPE_DES3 = 2;
public static final int KEYTYPE_AES = 3;
public static final int KEYTYPE_ARCFOUR_HMAC = 4;
//----------------------------------------+-----------------
// padata type |padata-type value
//----------------------------------------+-----------------
public static final int PA_TGS_REQ = 1;
public static final int PA_ENC_TIMESTAMP = 2;
public static final int PA_PW_SALT = 3;
// new preauth types
public static final int PA_ETYPE_INFO = 11;
public static final int PA_ETYPE_INFO2 = 19;
// S4U2user info
public static final int PA_FOR_USER = 129;
public static final int PA_PAC_OPTIONS = 167;
// FAST (RFC 6806)
public static final int PA_REQ_ENC_PA_REP = 149;
//-------------------------------+-------------
//authorization data type |ad-type value
//-------------------------------+-------------
//reserved values 0-63
public static final int OSF_DCE = 64;
public static final int SESAME = 65;
//----------------------------------------------+-----------------
//alternate authentication type |method-type value
//----------------------------------------------+-----------------
// reserved values 0-63
public static final int ATT_CHALLENGE_RESPONSE = 64;
//--------------------------------------------+-------------
//transited encoding type |tr-type value
//--------------------------------------------+-------------
public static final int DOMAIN_X500_COMPRESS = 1;
// reserved values all others
//----------------------------+-------+-----------------------------------------
// Label |Value |Meaning
//----------------------------+-------+-----------------------------------------
public static final int PVNO = 5; // current Kerberos protocol version number
public static final int AUTHNETICATOR_VNO = 5; // current authenticator version number
public static final int TICKET_VNO = 5; // current ticket version number
//message types
// there are several message sub-components not included here
public static final int KRB_AS_REQ = 10; //Request for initial authentication
public static final int KRB_AS_REP = 11; //Response to KRB_AS_REQ request
public static final int KRB_TGS_REQ = 12; //Request for authentication based on TGT
public static final int KRB_TGS_REP = 13; //Response to KRB_TGS_REQ request
public static final int KRB_AP_REQ = 14; //application request to server
public static final int KRB_AP_REP = 15; //Response to KRB_AP_REQ_MUTUAL
public static final int KRB_SAFE = 20; //Safe (checksummed) application message
public static final int KRB_PRIV = 21; //Private (encrypted) application message
public static final int KRB_CRED = 22; //Private (encrypted) message to forward credentials
public static final int KRB_ERROR = 30; //Error response
//message component types
public static final int KRB_TKT = 1; //Ticket
public static final int KRB_AUTHENTICATOR = 2; //Authenticator
public static final int KRB_ENC_TKT_PART = 3; //Encrypted ticket part
public static final int KRB_ENC_AS_REP_PART = 25; //Encrypted initial authentication part
public static final int KRB_ENC_TGS_REP_PART = 26; //Encrypted TGS request part
public static final int KRB_ENC_AP_REP_PART = 27; //Encrypted application request part
public static final int KRB_ENC_KRB_PRIV_PART = 28; //Encrypted application message part
public static final int KRB_ENC_KRB_CRED_PART = 29; //Encrypted credentials forward part
//error codes
public static final int KDC_ERR_NONE = 0; //No error
public static final int KDC_ERR_NAME_EXP = 1; //Client's entry in database expired
public static final int KDC_ERR_SERVICE_EXP = 2; //Server's entry in database has expired
public static final int KDC_ERR_BAD_PVNO = 3; //Requested protocol version number not supported
public static final int KDC_ERR_C_OLD_MAST_KVNO = 4; //Client's key encrypted in old master key
public static final int KDC_ERR_S_OLD_MAST_KVNO = 5; //Server's key encrypted in old master key
public static final int KDC_ERR_C_PRINCIPAL_UNKNOWN = 6; //Client not found in Kerberos database
public static final int KDC_ERR_S_PRINCIPAL_UNKNOWN = 7; //Server not found in Kerberos database
public static final int KDC_ERR_PRINCIPAL_NOT_UNIQUE = 8; //Multiple principal entries in database
public static final int KDC_ERR_NULL_KEY = 9; //The client or server has a null key
public static final int KDC_ERR_CANNOT_POSTDATE = 10; //Ticket not eligible for postdating
public static final int KDC_ERR_NEVER_VALID = 11; //Requested start time is later than end time
public static final int KDC_ERR_POLICY = 12; //KDC policy rejects request
public static final int KDC_ERR_BADOPTION = 13; //KDC cannot accommodate requested option
public static final int KDC_ERR_ETYPE_NOSUPP = 14; //KDC has no support for encryption type
public static final int KDC_ERR_SUMTYPE_NOSUPP = 15; //KDC has no support for checksum type
public static final int KDC_ERR_PADATA_TYPE_NOSUPP = 16; //KDC has no support for padata type
public static final int KDC_ERR_TRTYPE_NOSUPP = 17; //KDC has no support for transited type
public static final int KDC_ERR_CLIENT_REVOKED = 18; //Clients credentials have been revoked
public static final int KDC_ERR_SERVICE_REVOKED = 19; //Credentials for server have been revoked
public static final int KDC_ERR_TGT_REVOKED = 20; //TGT has been revoked
public static final int KDC_ERR_CLIENT_NOTYET = 21; //Client not yet valid - try again later
public static final int KDC_ERR_SERVICE_NOTYET = 22; //Server not yet valid - try again later
public static final int KDC_ERR_KEY_EXPIRED = 23; //Password has expired - change password to reset
public static final int KDC_ERR_PREAUTH_FAILED = 24; //Pre-authentication information was invalid
public static final int KDC_ERR_PREAUTH_REQUIRED = 25; //Additional pre-authentication required
public static final int KRB_AP_ERR_BAD_INTEGRITY = 31; //Integrity check on decrypted field failed
public static final int KRB_AP_ERR_TKT_EXPIRED = 32; //Ticket expired
public static final int KRB_AP_ERR_TKT_NYV = 33; //Ticket not yet valid
public static final int KRB_AP_ERR_REPEAT = 34; //Request is a replay
public static final int KRB_AP_ERR_NOT_US = 35; //The ticket isn't for us
public static final int KRB_AP_ERR_BADMATCH = 36; //Ticket and authenticator don't match
public static final int KRB_AP_ERR_SKEW = 37; //Clock skew too great
public static final int KRB_AP_ERR_BADADDR = 38; //Incorrect net address
public static final int KRB_AP_ERR_BADVERSION = 39; //Protocol version mismatch
public static final int KRB_AP_ERR_MSG_TYPE = 40; //Invalid msg type
public static final int KRB_AP_ERR_MODIFIED = 41; //Message stream modified
public static final int KRB_AP_ERR_BADORDER = 42; //Message out of order
public static final int KRB_AP_ERR_BADKEYVER = 44; //Specified version of key is not available
public static final int KRB_AP_ERR_NOKEY = 45; //Service key not available
public static final int KRB_AP_ERR_MUT_FAIL = 46; //Mutual authentication failed
public static final int KRB_AP_ERR_BADDIRECTION = 47; //Incorrect message direction
public static final int KRB_AP_ERR_METHOD = 48; //Alternative authentication method required
public static final int KRB_AP_ERR_BADSEQ = 49; //Incorrect sequence number in message
public static final int KRB_AP_ERR_INAPP_CKSUM = 50; //Inappropriate type of checksum in message
public static final int KRB_ERR_RESPONSE_TOO_BIG = 52; //Response too big for UDP, retry with TCP
public static final int KRB_ERR_GENERIC = 60; //Generic error (description in e-text)
public static final int KRB_ERR_FIELD_TOOLONG = 61; //Field is too long for this implementation
public static final int KRB_ERR_WRONG_REALM = 68; //Wrong realm
public static final int KRB_CRYPTO_NOT_SUPPORT = 100; //Client does not support this crypto type
public static final int KRB_AP_ERR_NOREALM = 62;
public static final int KRB_AP_ERR_GEN_CRED = 63;
// public static final int KRB_AP_ERR_CKSUM_NOKEY =101; //Lack of the key to generate the checksum
// error codes specific to this implementation
public static final int KRB_AP_ERR_REQ_OPTIONS = 101; //Invalid TGS_REQ
public static final int API_INVALID_ARG = 400; //Invalid argument
public static final int BITSTRING_SIZE_INVALID = 500; //BitString size does not match input byte array
public static final int BITSTRING_INDEX_OUT_OF_BOUNDS = 501; //BitString bit index does not fall within size
public static final int BITSTRING_BAD_LENGTH = 502; //BitString length is wrong for the expected type
public static final int REALM_ILLCHAR = 600; //Illegal character in realm name; one of: '/', ':', '\0'
public static final int REALM_NULL = 601; //Null realm name
public static final int ASN1_BAD_TIMEFORMAT = 900; //Input not in GeneralizedTime format
public static final int ASN1_MISSING_FIELD = 901; //Structure is missing a required field
public static final int ASN1_MISPLACED_FIELD = 902; //Unexpected field number
public static final int ASN1_TYPE_MISMATCH = 903; //Type numbers are inconsistent
public static final int ASN1_OVERFLOW = 904; //Value too large
public static final int ASN1_OVERRUN = 905; //Encoding ended unexpectedly
public static final int ASN1_BAD_ID = 906; //Identifier doesn't match expected value
public static final int ASN1_BAD_LENGTH = 907; //Length doesn't match expected value
public static final int ASN1_BAD_FORMAT = 908; //Badly-formatted encoding
public static final int ASN1_PARSE_ERROR = 909; //Parse error
public static final int ASN1_BAD_CLASS = 910; //Bad class number
public static final int ASN1_BAD_TYPE = 911; //Bad type number
public static final int ASN1_BAD_TAG = 912; //Bad tag number
public static final int ASN1_UNSUPPORTED_TYPE = 913; //Unsupported ASN.1 type encountered
public static final int ASN1_CANNOT_ENCODE = 914; //Encoding failed due to invalid parameter(s)
private static Hashtable<Integer,String> errMsgList;
public static String getErrorMessage(int i) {
return errMsgList.get(i);
}
public static final boolean DEBUG =
java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
static {
errMsgList = new Hashtable<Integer,String> ();
errMsgList.put(KDC_ERR_NONE, "No error");
errMsgList.put(KDC_ERR_NAME_EXP, "Client's entry in database expired");
errMsgList.put(KDC_ERR_SERVICE_EXP, "Server's entry in database has expired");
errMsgList.put(KDC_ERR_BAD_PVNO, "Requested protocol version number not supported");
errMsgList.put(KDC_ERR_C_OLD_MAST_KVNO, "Client's key encrypted in old master key");
errMsgList.put(KDC_ERR_S_OLD_MAST_KVNO, "Server's key encrypted in old master key");
errMsgList.put(KDC_ERR_C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database");
errMsgList.put(KDC_ERR_S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database");
errMsgList.put(KDC_ERR_PRINCIPAL_NOT_UNIQUE, "Multiple principal entries in database");
errMsgList.put(KDC_ERR_NULL_KEY, "The client or server has a null key");
errMsgList.put(KDC_ERR_CANNOT_POSTDATE, "Ticket not eligible for postdating");
errMsgList.put(KDC_ERR_NEVER_VALID, "Requested start time is later than end time");
errMsgList.put(KDC_ERR_POLICY, "KDC policy rejects request");
errMsgList.put(KDC_ERR_BADOPTION, "KDC cannot accommodate requested option");
errMsgList.put(KDC_ERR_ETYPE_NOSUPP, "KDC has no support for encryption type");
errMsgList.put(KDC_ERR_SUMTYPE_NOSUPP, "KDC has no support for checksum type");
errMsgList.put(KDC_ERR_PADATA_TYPE_NOSUPP, "KDC has no support for padata type");
errMsgList.put(KDC_ERR_TRTYPE_NOSUPP, "KDC has no support for transited type");
errMsgList.put(KDC_ERR_CLIENT_REVOKED, "Clients credentials have been revoked");
errMsgList.put(KDC_ERR_SERVICE_REVOKED, "Credentials for server have been revoked");
errMsgList.put(KDC_ERR_TGT_REVOKED, "TGT has been revoked");
errMsgList.put(KDC_ERR_CLIENT_NOTYET, "Client not yet valid - try again later");
errMsgList.put(KDC_ERR_SERVICE_NOTYET, "Server not yet valid - try again later");
errMsgList.put(KDC_ERR_KEY_EXPIRED, "Password has expired - change password to reset");
errMsgList.put(KDC_ERR_PREAUTH_FAILED, "Pre-authentication information was invalid");
errMsgList.put(KDC_ERR_PREAUTH_REQUIRED, "Additional pre-authentication required");
errMsgList.put(KRB_AP_ERR_BAD_INTEGRITY, "Integrity check on decrypted field failed");
errMsgList.put(KRB_AP_ERR_TKT_EXPIRED, "Ticket expired");
errMsgList.put(KRB_AP_ERR_TKT_NYV, "Ticket not yet valid");
errMsgList.put(KRB_AP_ERR_REPEAT, "Request is a replay");
errMsgList.put(KRB_AP_ERR_NOT_US, "The ticket isn't for us");
errMsgList.put(KRB_AP_ERR_BADMATCH, "Ticket and authenticator don't match");
errMsgList.put(KRB_AP_ERR_SKEW, "Clock skew too great");
errMsgList.put(KRB_AP_ERR_BADADDR, "Incorrect net address");
errMsgList.put(KRB_AP_ERR_BADVERSION, "Protocol version mismatch");
errMsgList.put(KRB_AP_ERR_MSG_TYPE, "Invalid msg type");
errMsgList.put(KRB_AP_ERR_MODIFIED, "Message stream modified");
errMsgList.put(KRB_AP_ERR_BADORDER, "Message out of order");
errMsgList.put(KRB_AP_ERR_BADKEYVER, "Specified version of key is not available");
errMsgList.put(KRB_AP_ERR_NOKEY, "Service key not available");
errMsgList.put(KRB_AP_ERR_MUT_FAIL, "Mutual authentication failed");
errMsgList.put(KRB_AP_ERR_BADDIRECTION, "Incorrect message direction");
errMsgList.put(KRB_AP_ERR_METHOD, "Alternative authentication method required");
errMsgList.put(KRB_AP_ERR_BADSEQ, "Incorrect sequence number in message");
errMsgList.put(KRB_AP_ERR_INAPP_CKSUM, "Inappropriate type of checksum in message");
errMsgList.put(KRB_ERR_RESPONSE_TOO_BIG, "Response too big for UDP, retry with TCP");
errMsgList.put(KRB_ERR_GENERIC, "Generic error (description in e-text)");
errMsgList.put(KRB_ERR_FIELD_TOOLONG, "Field is too long for this implementation");
errMsgList.put(KRB_AP_ERR_NOREALM, "Realm name not available"); //used in setDefaultCreds() in sun.security.krb5.Credentials
// error messages specific to this implementation
errMsgList.put(API_INVALID_ARG, "Invalid argument");
errMsgList.put(BITSTRING_SIZE_INVALID, "BitString size does not match input byte array");
errMsgList.put(BITSTRING_INDEX_OUT_OF_BOUNDS, "BitString bit index does not fall within size");
errMsgList.put(BITSTRING_BAD_LENGTH, "BitString length is wrong for the expected type");
errMsgList.put(REALM_ILLCHAR, "Illegal character in realm name; one of: '/', ':', '\0'");
errMsgList.put(REALM_NULL, "Null realm name");
errMsgList.put(ASN1_BAD_TIMEFORMAT, "Input not in GeneralizedTime format");
errMsgList.put(ASN1_MISSING_FIELD, "Structure is missing a required field");
errMsgList.put(ASN1_MISPLACED_FIELD, "Unexpected field number");
errMsgList.put(ASN1_TYPE_MISMATCH, "Type numbers are inconsistent");
errMsgList.put(ASN1_OVERFLOW, "Value too large");
errMsgList.put(ASN1_OVERRUN, "Encoding ended unexpectedly");
errMsgList.put(ASN1_BAD_ID, "Identifier doesn't match expected value");
errMsgList.put(ASN1_BAD_LENGTH, "Length doesn't match expected value");
errMsgList.put(ASN1_BAD_FORMAT, "Badly-formatted encoding");
errMsgList.put(ASN1_PARSE_ERROR, "Parse error");
errMsgList.put(ASN1_BAD_CLASS, "Bad class number");
errMsgList.put(ASN1_BAD_TYPE, "Bad type number");
errMsgList.put(ASN1_BAD_TAG, "Bad tag number");
errMsgList.put(ASN1_UNSUPPORTED_TYPE, "Unsupported ASN.1 type encountered");
errMsgList.put(ASN1_CANNOT_ENCODE, "Encoding failed due to invalid parameter(s)");
errMsgList.put(KRB_CRYPTO_NOT_SUPPORT, "Client has no support for crypto type");
errMsgList.put(KRB_AP_ERR_REQ_OPTIONS, "Invalid option setting in ticket request.");
errMsgList.put(KRB_AP_ERR_GEN_CRED, "Fail to create credential.");
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2000, 2003, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
public class KrbApErrException extends sun.security.krb5.KrbException {
private static final long serialVersionUID = 7545264413323118315L;
public KrbApErrException(int i) {
super(i);
}
public KrbApErrException(int i, String s) {
super(i, s);
}
}

View File

@@ -0,0 +1,201 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
/**
* Implements the ASN.1 KrbCredInfo type.
*
* <pre>{@code
* KrbCredInfo ::= SEQUENCE {
* key [0] EncryptionKey,
* prealm [1] Realm OPTIONAL,
* pname [2] PrincipalName OPTIONAL,
* flags [3] TicketFlags OPTIONAL,
* authtime [4] KerberosTime OPTIONAL,
* starttime [5] KerberosTime OPTIONAL,
* endtime [6] KerberosTime OPTIONAL,
* renew-till [7] KerberosTime OPTIONAL,
* srealm [8] Realm OPTIONAL,
* sname [9] PrincipalName OPTIONAL,
* caddr [10] HostAddresses OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class KrbCredInfo {
public EncryptionKey key;
public PrincipalName pname; //optional
public TicketFlags flags; //optional
public KerberosTime authtime; //optional
public KerberosTime starttime; //optional
public KerberosTime endtime; //optional
public KerberosTime renewTill; //optional
public PrincipalName sname; //optional
public HostAddresses caddr; //optional
private KrbCredInfo() {
}
public KrbCredInfo(
EncryptionKey new_key,
PrincipalName new_pname,
TicketFlags new_flags,
KerberosTime new_authtime,
KerberosTime new_starttime,
KerberosTime new_endtime,
KerberosTime new_renewTill,
PrincipalName new_sname,
HostAddresses new_caddr
) {
key = new_key;
pname = new_pname;
flags = new_flags;
authtime = new_authtime;
starttime = new_starttime;
endtime = new_endtime;
renewTill = new_renewTill;
sname = new_sname;
caddr = new_caddr;
}
/**
* Constructs a KrbCredInfo object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
public KrbCredInfo(DerValue encoding)
throws Asn1Exception, IOException, RealmException{
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
pname = null;
flags = null;
authtime = null;
starttime = null;
endtime = null;
renewTill = null;
sname = null;
caddr = null;
key = EncryptionKey.parse(encoding.getData(), (byte)0x00, false);
Realm prealm = null, srealm = null;
if (encoding.getData().available() > 0)
prealm = Realm.parse(encoding.getData(), (byte)0x01, true);
if (encoding.getData().available() > 0)
pname = PrincipalName.parse(encoding.getData(), (byte)0x02, true, prealm);
if (encoding.getData().available() > 0)
flags = TicketFlags.parse(encoding.getData(), (byte)0x03, true);
if (encoding.getData().available() > 0)
authtime = KerberosTime.parse(encoding.getData(), (byte)0x04, true);
if (encoding.getData().available() > 0)
starttime = KerberosTime.parse(encoding.getData(), (byte)0x05, true);
if (encoding.getData().available() > 0)
endtime = KerberosTime.parse(encoding.getData(), (byte)0x06, true);
if (encoding.getData().available() > 0)
renewTill = KerberosTime.parse(encoding.getData(), (byte)0x07, true);
if (encoding.getData().available() > 0)
srealm = Realm.parse(encoding.getData(), (byte)0x08, true);
if (encoding.getData().available() > 0)
sname = PrincipalName.parse(encoding.getData(), (byte)0x09, true, srealm);
if (encoding.getData().available() > 0)
caddr = HostAddresses.parse(encoding.getData(), (byte)0x0A, true);
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes an KrbCredInfo object.
* @return the byte array of encoded KrbCredInfo object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
Vector<DerValue> v = new Vector<>();
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), key.asn1Encode()));
if (pname != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), pname.getRealm().asn1Encode()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), pname.asn1Encode()));
}
if (flags != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), flags.asn1Encode()));
if (authtime != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), authtime.asn1Encode()));
if (starttime != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x05), starttime.asn1Encode()));
if (endtime != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x06), endtime.asn1Encode()));
if (renewTill != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), renewTill.asn1Encode()));
if (sname != null) {
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x08), sname.getRealm().asn1Encode()));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x09), sname.asn1Encode()));
}
if (caddr != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), caddr.asn1Encode()));
DerValue der[] = new DerValue[v.size()];
v.copyInto(der);
DerOutputStream out = new DerOutputStream();
out.putSequence(der);
return out.toByteArray();
}
public Object clone() {
KrbCredInfo kcred = new KrbCredInfo();
kcred.key = (EncryptionKey)key.clone();
// optional fields
if (pname != null)
kcred.pname = (PrincipalName)pname.clone();
if (flags != null)
kcred.flags = (TicketFlags)flags.clone();
kcred.authtime = authtime;
kcred.starttime = starttime;
kcred.endtime = endtime;
kcred.renewTill = renewTill;
if (sname != null)
kcred.sname = (PrincipalName)sname.clone();
if (caddr != null)
kcred.caddr = (HostAddresses)caddr.clone();
return kcred;
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
public class KrbErrException extends sun.security.krb5.KrbException {
private static final long serialVersionUID = 2186533836785448317L;
public KrbErrException(int i) {
super(i);
}
public KrbErrException(int i, String s) {
super(i, s);
}
}

View File

@@ -0,0 +1,137 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.util.Vector;
import java.io.IOException;
/**
* Implements the ASN.1 LastReq type.
*
* <pre>{@code
* LastReq ::= SEQUENCE OF SEQUENCE {
* lr-type [0] Int32,
* lr-value [1] KerberosTime
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class LastReq {
private LastReqEntry[] entry = null;
public LastReq(LastReqEntry[] entries) throws IOException {
if (entries != null) {
entry = new LastReqEntry[entries.length];
for (int i = 0; i < entries.length; i++) {
if (entries[i] == null) {
throw new IOException("Cannot create a LastReqEntry");
} else {
entry[i] = (LastReqEntry)entries[i].clone();
}
}
}
}
/**
* Constructs a LastReq object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public LastReq(DerValue encoding) throws Asn1Exception, IOException {
Vector<LastReqEntry> v= new Vector<>();
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
while (encoding.getData().available() > 0) {
v.addElement(new LastReqEntry(encoding.getData().getDerValue()));
}
if (v.size() > 0) {
entry = new LastReqEntry[v.size()];
v.copyInto(entry);
}
}
/**
* Encodes an LastReq object.
* @return the byte array of encoded LastReq object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
if (entry != null && entry.length > 0) {
DerOutputStream temp = new DerOutputStream();
for (int i = 0; i < entry.length; i++)
temp.write(entry[i].asn1Encode());
bytes.write(DerValue.tag_Sequence, temp);
return bytes.toByteArray();
}
return null;
}
/**
* Parse (unmarshal) a last request from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional
* @return an instance of LastReq.
*
*/
public static LastReq parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
else {
DerValue subDer = der.getData().getDerValue();
return new LastReq(subDer);
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
public class LastReqEntry {
private int lrType;
private KerberosTime lrValue;
private LastReqEntry() {
}
public LastReqEntry(int Type, KerberosTime time){
lrType = Type;
lrValue = time;
// XXX check the type and time.
}
/**
* Constructs a LastReqEntry object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public LastReqEntry(DerValue encoding) throws Asn1Exception, IOException {
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
DerValue der;
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00){
lrType = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
lrValue = KerberosTime.parse(encoding.getData(), (byte)0x01, false);
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes an LastReqEntry object.
* @return the byte array of encoded LastReqEntry object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(lrType);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), lrValue.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
public Object clone() {
LastReqEntry newEntry = new LastReqEntry();
newEntry.lrType = lrType;
newEntry.lrValue = lrValue;
return newEntry;
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2000, 2007, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Confounder;
public class LocalSeqNumber implements SeqNumber {
private int lastSeqNumber;
public LocalSeqNumber() {
randInit();
}
public LocalSeqNumber(int start) {
init(start);
}
public LocalSeqNumber(Integer start) {
init(start.intValue());
}
public synchronized void randInit() {
/*
* Sequence numbers fall in the range 0 through 2^32 - 1 and wrap
* to zero following the value 2^32 - 1.
* Previous implementations used signed sequence numbers.
* Workaround implementation incompatibilities by not generating
* initial sequence numbers greater than 2^30, as done
* in MIT distribution.
*/
// get the random confounder
byte[] data = Confounder.bytes(4);
data[0] = (byte)(data[0] & 0x3f);
int result = ((data[3] & 0xff) |
((data[2] & 0xff) << 8) |
((data[1] & 0xff) << 16) |
((data[0] & 0xff) << 24));
if (result == 0) {
result = 1;
}
lastSeqNumber = result;
}
public synchronized void init(int start) {
lastSeqNumber = start;
}
public synchronized int current() {
return lastSeqNumber;
}
public synchronized int next() {
return lastSeqNumber + 1;
}
public synchronized int step() {
return ++lastSeqNumber;
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import java.io.IOException;
/**
* Implements the ASN.1 KDCOptions type.
*
* <pre>{@code
* KDCOptions ::= KerberosFlags
* -- reserved(0),
* -- forwardable(1),
* -- forwarded(2),
* -- proxiable(3),
* -- proxy(4),
* -- allow-postdate(5),
* -- postdated(6),
* -- unused7(7),
* -- renewable(8),
* -- unused9(9),
* -- unused10(10),
* -- opt-hardware-auth(11),
* -- unused12(12),
* -- unused13(13),
* -- 15 is reserved for canonicalize
* -- unused15(15),
* -- 26 was unused in 1510
* -- disable-transited-check(26),
* -- renewable-ok(27),
* -- enc-tkt-in-skey(28),
* -- renew(30),
* -- validate(31)
*
* KerberosFlags ::= BIT STRING (SIZE (32..MAX))
* -- minimum number of bits shall be sent,
* -- but no fewer than 32
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class LoginOptions extends KDCOptions {
// Login Options
public static final int RESERVED = 0;
public static final int FORWARDABLE = 1;
public static final int PROXIABLE = 3;
public static final int ALLOW_POSTDATE = 5;
public static final int RENEWABLE = 8;
public static final int RENEWABLE_OK = 27;
public static final int ENC_TKT_IN_SKEY = 28;
public static final int RENEW = 30;
public static final int VALIDATE = 31;
public static final int MAX = 31;
}

View File

@@ -0,0 +1,111 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 EncKrbPrivPart type.
*
* <pre>{@code
* METHOD-DATA ::= SEQUENCE {
* method-type[0] INTEGER,
* method-data[1] OCTET STRING OPTIONAL
* }
* }</pre>
*/
public class MethodData {
private int methodType;
private byte[] methodData = null; //optional
public MethodData(int type, byte[] data) {
methodType = type;
if (data != null) {
methodData = data.clone();
}
}
/**
* Constructs a MethodData object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public MethodData(DerValue encoding) throws Asn1Exception, IOException {
DerValue der;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
BigInteger bint = der.getData().getBigInteger();
methodType = bint.intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
if (encoding.getData().available() > 0) {
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x01) {
methodData = der.getData().getOctetString();
}
else throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes an MethodData object.
* @return the byte array of encoded MethodData object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(methodType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
if (methodData != null) {
temp = new DerOutputStream();
temp.putOctetString(methodData);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright (c) 2000, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.misc.IOUtils;
import java.io.*;
import java.net.*;
public abstract class NetClient implements AutoCloseable {
public static NetClient getInstance(String protocol, String hostname, int port,
int timeout) throws IOException {
if (protocol.equals("TCP")) {
return new TCPClient(hostname, port, timeout);
} else {
return new UDPClient(hostname, port, timeout);
}
}
abstract public void send(byte[] data) throws IOException;
abstract public byte[] receive() throws IOException;
abstract public void close() throws IOException;
}
class TCPClient extends NetClient {
private Socket tcpSocket;
private BufferedOutputStream out;
private BufferedInputStream in;
TCPClient(String hostname, int port, int timeout)
throws IOException {
tcpSocket = new Socket();
tcpSocket.connect(new InetSocketAddress(hostname, port), timeout);
out = new BufferedOutputStream(tcpSocket.getOutputStream());
in = new BufferedInputStream(tcpSocket.getInputStream());
tcpSocket.setSoTimeout(timeout);
}
@Override
public void send(byte[] data) throws IOException {
byte[] lenField = new byte[4];
intToNetworkByteOrder(data.length, lenField, 0, 4);
out.write(lenField);
out.write(data);
out.flush();
}
@Override
public byte[] receive() throws IOException {
byte[] lenField = new byte[4];
int count = readFully(lenField, 4);
if (count != 4) {
if (Krb5.DEBUG) {
System.out.println(
">>>DEBUG: TCPClient could not read length field");
}
return null;
}
int len = networkByteOrderToInt(lenField, 0, 4);
if (Krb5.DEBUG) {
System.out.println(
">>>DEBUG: TCPClient reading " + len + " bytes");
}
if (len <= 0) {
if (Krb5.DEBUG) {
System.out.println(
">>>DEBUG: TCPClient zero or negative length field: "+len);
}
return null;
}
try {
return IOUtils.readExactlyNBytes(in, len);
} catch (IOException ioe) {
if (Krb5.DEBUG) {
System.out.println(
">>>DEBUG: TCPClient could not read complete packet (" +
len + "/" + count + ")");
}
return null;
}
}
@Override
public void close() throws IOException {
tcpSocket.close();
}
/**
* Read requested number of bytes before returning.
* @return The number of bytes actually read; -1 if none read
*/
private int readFully(byte[] inBuf, int total) throws IOException {
int count, pos = 0;
while (total > 0) {
count = in.read(inBuf, pos, total);
if (count == -1) {
return (pos == 0? -1 : pos);
}
pos += count;
total -= count;
}
return pos;
}
/**
* Returns the integer represented by 4 bytes in network byte order.
*/
private static int networkByteOrderToInt(byte[] buf, int start,
int count) {
if (count > 4) {
throw new IllegalArgumentException(
"Cannot handle more than 4 bytes");
}
int answer = 0;
for (int i = 0; i < count; i++) {
answer <<= 8;
answer |= ((int)buf[start+i] & 0xff);
}
return answer;
}
/**
* Encodes an integer into 4 bytes in network byte order in the buffer
* supplied.
*/
private static void intToNetworkByteOrder(int num, byte[] buf,
int start, int count) {
if (count > 4) {
throw new IllegalArgumentException(
"Cannot handle more than 4 bytes");
}
for (int i = count-1; i >= 0; i--) {
buf[start+i] = (byte)(num & 0xff);
num >>>= 8;
}
}
}
class UDPClient extends NetClient {
InetAddress iaddr;
int iport;
int bufSize = 65507;
DatagramSocket dgSocket;
DatagramPacket dgPacketIn;
UDPClient(String hostname, int port, int timeout)
throws UnknownHostException, SocketException {
iaddr = InetAddress.getByName(hostname);
iport = port;
dgSocket = new DatagramSocket();
dgSocket.setSoTimeout(timeout);
dgSocket.connect(iaddr, iport);
}
@Override
public void send(byte[] data) throws IOException {
DatagramPacket dgPacketOut = new DatagramPacket(data, data.length,
iaddr, iport);
dgSocket.send(dgPacketOut);
}
@Override
public byte[] receive() throws IOException {
byte ibuf[] = new byte[bufSize];
dgPacketIn = new DatagramPacket(ibuf, ibuf.length);
try {
dgSocket.receive(dgPacketIn);
}
catch (SocketException e) {
if (e instanceof PortUnreachableException) {
throw e;
}
dgSocket.receive(dgPacketIn);
}
byte[] data = new byte[dgPacketIn.getLength()];
System.arraycopy(dgPacketIn.getData(), 0, data, 0,
dgPacketIn.getLength());
return data;
}
@Override
public void close() {
dgSocket.close();
}
}

View File

@@ -0,0 +1,367 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.internal.crypto.EType;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
import java.util.Vector;
import sun.security.krb5.internal.util.KerberosString;
/**
* Implements the ASN.1 PA-DATA type.
*
* <pre>{@code
* PA-DATA ::= SEQUENCE {
* -- NOTE: first tag is [1], not [0]
* padata-type [1] Int32,
* padata-value [2] OCTET STRING -- might be encoded AP-REQ
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class PAData {
private int pADataType;
private byte[] pADataValue = null;
private static final byte TAG_PATYPE = 1;
private static final byte TAG_PAVALUE = 2;
private PAData() {
}
public PAData(int new_pADataType, byte[] new_pADataValue) {
pADataType = new_pADataType;
if (new_pADataValue != null) {
pADataValue = new_pADataValue.clone();
}
}
public Object clone() {
PAData new_pAData = new PAData();
new_pAData.pADataType = pADataType;
if (pADataValue != null) {
new_pAData.pADataValue = new byte[pADataValue.length];
System.arraycopy(pADataValue, 0, new_pAData.pADataValue,
0, pADataValue.length);
}
return new_pAData;
}
/**
* Constructs a PAData object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public PAData(DerValue encoding) throws Asn1Exception, IOException {
DerValue der = null;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x01) {
this.pADataType = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x02) {
this.pADataValue = der.getData().getOctetString();
}
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes this object to an OutputStream.
*
* @return byte array of the encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception Asn1Exception on encoding errors.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(pADataType);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_PATYPE), temp);
temp = new DerOutputStream();
temp.putOctetString(pADataValue);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_PAVALUE), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
// accessor methods
public int getType() {
return pADataType;
}
public byte[] getValue() {
return ((pADataValue == null) ? null : pADataValue.clone());
}
/**
* Parse (unmarshal) a PAData from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception if an Asn1Exception occurs.
* @param data the Der input stream value, which contains one or more
* marshaled values.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional.
* @return an array of PAData.
*/
public static PAData[] parseSequence(DerInputStream data,
byte explicitTag, boolean optional)
throws Asn1Exception, IOException {
if ((optional) &&
(((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue subDer = data.getDerValue();
DerValue subsubDer = subDer.getData().getDerValue();
if (subsubDer.getTag() != DerValue.tag_SequenceOf) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
Vector<PAData> v = new Vector<>();
while (subsubDer.getData().available() > 0) {
v.addElement(new PAData(subsubDer.getData().getDerValue()));
}
if (v.size() > 0) {
PAData[] pas = new PAData[v.size()];
v.copyInto(pas);
return pas;
}
return null;
}
/**
* Gets the preferred etype from the PAData array.
* <ol>
* <li>ETYPE-INFO2-ENTRY with unknown s2kparams ignored</li>
* <li>ETYPE-INFO2 preferred to ETYPE-INFO</li>
* <li>Multiple entries for same etype in one PA-DATA, use the first one.</li>
* <li>Multiple PA-DATA with same type, choose the last one.</li>
* </ol>
* (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined).
*
* @return the etype, or defaultEType if not enough info
* @throws Asn1Exception|IOException if there is an encoding error
*/
public static int getPreferredEType(PAData[] pas, int defaultEType)
throws IOException, Asn1Exception {
if (pas == null) return defaultEType;
DerValue d = null, d2 = null;
for (PAData p: pas) {
if (p.getValue() == null) continue;
switch (p.getType()) {
case Krb5.PA_ETYPE_INFO:
d = new DerValue(p.getValue());
break;
case Krb5.PA_ETYPE_INFO2:
d2 = new DerValue(p.getValue());
break;
}
}
if (d2 != null) {
while (d2.data.available() > 0) {
DerValue value = d2.data.getDerValue();
ETypeInfo2 tmp = new ETypeInfo2(value);
if (EType.isNewer(tmp.getEType()) || tmp.getParams() == null) {
// we don't support non-null s2kparams for old etypes
return tmp.getEType();
}
}
}
if (d != null) {
while (d.data.available() > 0) {
DerValue value = d.data.getDerValue();
ETypeInfo tmp = new ETypeInfo(value);
return tmp.getEType();
}
}
return defaultEType;
}
/**
* A place to store a pair of salt and s2kparams.
* An empty salt is changed to null, to be interoperable
* with Windows 2000 server. This is in fact not correct.
*/
public static class SaltAndParams {
public final String salt;
public final byte[] params;
public SaltAndParams(String s, byte[] p) {
if (s != null && s.isEmpty()) s = null;
this.salt = s;
this.params = p;
}
}
/**
* Fetches salt and s2kparams value for eType in a series of PA-DATAs.
* 1. ETYPE-INFO2-ENTRY with unknown s2kparams ignored
* 2. PA-ETYPE-INFO2 preferred to PA-ETYPE-INFO preferred to PA-PW-SALT.
* 3. multiple entries for same etype in one PA-DATA, use the first one.
* 4. Multiple PA-DATA with same type, choose the last one
* (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined).
* @return salt and s2kparams. can be null if not found
*/
public static SaltAndParams getSaltAndParams(int eType, PAData[] pas)
throws Asn1Exception, IOException {
if (pas == null) return null;
DerValue d = null, d2 = null;
String paPwSalt = null;
for (PAData p: pas) {
if (p.getValue() == null) continue;
switch (p.getType()) {
case Krb5.PA_PW_SALT:
paPwSalt = new String(p.getValue(),
KerberosString.MSNAME?"UTF8":"8859_1");
break;
case Krb5.PA_ETYPE_INFO:
d = new DerValue(p.getValue());
break;
case Krb5.PA_ETYPE_INFO2:
d2 = new DerValue(p.getValue());
break;
}
}
if (d2 != null) {
while (d2.data.available() > 0) {
DerValue value = d2.data.getDerValue();
ETypeInfo2 tmp = new ETypeInfo2(value);
if (tmp.getEType() == eType &&
(EType.isNewer(eType) || tmp.getParams() == null)) {
// we don't support non-null s2kparams for old etypes
return new SaltAndParams(tmp.getSalt(), tmp.getParams());
}
}
}
if (d != null) {
while (d.data.available() > 0) {
DerValue value = d.data.getDerValue();
ETypeInfo tmp = new ETypeInfo(value);
if (tmp.getEType() == eType) {
return new SaltAndParams(tmp.getSalt(), null);
}
}
}
if (paPwSalt != null) {
return new SaltAndParams(paPwSalt, null);
}
return null;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append(">>>Pre-Authentication Data:\n\t PA-DATA type = ")
.append(pADataType).append('\n');
switch(pADataType) {
case Krb5.PA_ENC_TIMESTAMP:
sb.append("\t PA-ENC-TIMESTAMP");
break;
case Krb5.PA_ETYPE_INFO:
if (pADataValue != null) {
try {
DerValue der = new DerValue(pADataValue);
while (der.data.available() > 0) {
DerValue value = der.data.getDerValue();
ETypeInfo info = new ETypeInfo(value);
sb.append("\t PA-ETYPE-INFO etype = ")
.append(info.getEType())
.append(", salt = ")
.append(info.getSalt())
.append('\n');
}
} catch (IOException|Asn1Exception e) {
sb.append("\t <Unparseable PA-ETYPE-INFO>\n");
}
}
break;
case Krb5.PA_ETYPE_INFO2:
if (pADataValue != null) {
try {
DerValue der = new DerValue(pADataValue);
while (der.data.available() > 0) {
DerValue value = der.data.getDerValue();
ETypeInfo2 info2 = new ETypeInfo2(value);
sb.append("\t PA-ETYPE-INFO2 etype = ")
.append(info2.getEType())
.append(", salt = ")
.append(info2.getSalt())
.append(", s2kparams = ");
byte[] s2kparams = info2.getParams();
if (s2kparams == null) {
sb.append("null\n");
} else if (s2kparams.length == 0) {
sb.append("empty\n");
} else {
sb.append(new sun.misc.HexDumpEncoder()
.encodeBuffer(s2kparams));
}
}
} catch (IOException|Asn1Exception e) {
sb.append("\t <Unparseable PA-ETYPE-INFO>\n");
}
}
break;
case Krb5.PA_FOR_USER:
sb.append("\t PA-FOR-USER\n");
break;
default:
// Unknown Pre-auth type
break;
}
return sb.toString();
}
}

View File

@@ -0,0 +1,116 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 PAEncTSEnc type.
*
* <pre>{@code
* PA-ENC-TS-ENC ::= SEQUENCE {
* patimestamp [0] KerberosTime -- client's time --,
* pausec [1] Microseconds OPTIONAL
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class PAEncTSEnc {
public KerberosTime pATimeStamp;
public Integer pAUSec; //optional
public PAEncTSEnc(
KerberosTime new_pATimeStamp,
Integer new_pAUSec
) {
pATimeStamp = new_pATimeStamp;
pAUSec = new_pAUSec;
}
public PAEncTSEnc() {
KerberosTime now = KerberosTime.now();
pATimeStamp = now;
pAUSec = new Integer(now.getMicroSeconds());
}
/**
* Constructs a PAEncTSEnc object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public PAEncTSEnc(DerValue encoding) throws Asn1Exception, IOException {
DerValue der;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
pATimeStamp = KerberosTime.parse(encoding.getData(), (byte)0x00, false);
if (encoding.getData().available() > 0) {
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x01) {
pAUSec = new Integer(der.getData().getBigInteger().intValue());
}
else throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes a PAEncTSEnc object.
* @return the byte array of encoded PAEncTSEnc object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), pATimeStamp.asn1Encode());
if (pAUSec != null) {
temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(pAUSec.intValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
}
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2012, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import sun.security.krb5.*;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.krb5.internal.util.KerberosString;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
/**
* Implements the ASN.1 PA-FOR-USER type.
*
* <pre>{@code
* padata-type ::= PA-FOR-USER
* -- value 129
* padata-value ::= EncryptedData
* -- PA-FOR-USER-ENC
* PA-FOR-USER-ENC ::= SEQUENCE {
* userName[0] PrincipalName,
* userRealm[1] Realm,
* cksum[2] Checksum,
* auth-package[3] KerberosString
* }
* }</pre>
*
* <p>
* This definition reflects MS-SFU.
*/
public class PAForUserEnc {
final public PrincipalName name;
final private EncryptionKey key;
final public static String AUTH_PACKAGE = "Kerberos";
public PAForUserEnc(PrincipalName name, EncryptionKey key) {
this.name = name;
this.key = key;
}
/**
* Constructs a PA-FOR-USER object from a DER encoding.
* @param encoding the input object
* @param key the key to verify the checksum inside encoding
* @throws KrbException if the verification fails.
* Note: this method is now only used by test KDC, therefore
* the verification is ignored (at the moment).
*/
public PAForUserEnc(DerValue encoding, EncryptionKey key)
throws Asn1Exception, KrbException, IOException {
DerValue der = null;
this.key = key;
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
// Realm after name? Quite abnormal.
PrincipalName tmpName = null;
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
try {
tmpName = new PrincipalName(der.getData().getDerValue(),
new Realm("PLACEHOLDER"));
} catch (RealmException re) {
// Impossible
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x01) {
try {
Realm realm = new Realm(der.getData().getDerValue());
name = new PrincipalName(
tmpName.getNameType(), tmpName.getNameStrings(), realm);
} catch (RealmException re) {
throw new IOException(re);
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x02) {
// Deal with the checksum
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x03) {
String authPackage = new KerberosString(der.getData().getDerValue()).toString();
if (!authPackage.equalsIgnoreCase(AUTH_PACKAGE)) {
throw new IOException("Incorrect auth-package");
}
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (encoding.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), name.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), name.getRealm().asn1Encode());
try {
// MS-SFU 2.2.1: use hmac-md5 checksum regardless of key type
Checksum cks = new Checksum(
Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR,
getS4UByteArray(),
key,
KeyUsage.KU_PA_FOR_USER_ENC_CKSUM);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), cks.asn1Encode());
} catch (KrbException ke) {
throw new IOException(ke);
}
DerOutputStream temp = new DerOutputStream();
temp.putDerValue(new KerberosString(AUTH_PACKAGE).toDerValue());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Returns S4UByteArray, the block to calculate checksum inside a
* PA-FOR-USER-ENC data structure. It includes:
* 1. userName.name-type encoded as a 4-byte integer in little endian
* byte order
* 2. all string values in the sequence of strings contained in the
* userName.name-string field
* 3. the string value of the userRealm field
* 4. the string value of auth-package field
*/
public byte[] getS4UByteArray() {
try {
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ba.write(new byte[4]);
for (String s: name.getNameStrings()) {
ba.write(s.getBytes("UTF-8"));
}
ba.write(name.getRealm().toString().getBytes("UTF-8"));
ba.write(AUTH_PACKAGE.getBytes("UTF-8"));
byte[] output = ba.toByteArray();
int pnType = name.getNameType();
output[0] = (byte)(pnType & 0xff);
output[1] = (byte)((pnType>>8) & 0xff);
output[2] = (byte)((pnType>>16) & 0xff);
output[3] = (byte)((pnType>>24) & 0xff);
return output;
} catch (IOException ioe) {
// not possible
throw new AssertionError("Cannot write ByteArrayOutputStream", ioe);
}
}
public PrincipalName getName() {
return name;
}
public String toString() {
return "PA-FOR-USER: " + name;
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 2019, Red Hat, Inc.
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal;
import java.io.IOException;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.internal.util.KerberosFlags;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
/**
* Implements the ASN.1 PA-PAC-OPTIONS type.
*
* <pre>{@code
* PA-PAC-OPTIONS ::= SEQUENCE {
* KerberosFlags
* -- Claims (0)
* -- Branch Aware (1)
* -- Forward to Full DC (2)
* }
* Note: KerberosFlags ::= BIT STRING (SIZE (32..MAX))
* -- minimum number of bits shall be sent, but no fewer than 32
*
* PA-PAC-OPTIONS ::= KerberosFlags
* -- resource-based constrained delegation (3)
* }</pre>
*
* This definition reflects MS-KILE (section 2.2.10)
* and MS-SFU (section 2.2.5).
*/
public class PaPacOptions {
private static final int CLAIMS = 0;
private static final int BRANCH_AWARE = 1;
private static final int FORWARD_TO_FULL_DC = 2;
private static final int RESOURCE_BASED_CONSTRAINED_DELEGATION = 3;
private KerberosFlags flags;
public PaPacOptions() {
this.flags = new KerberosFlags(Krb5.AP_OPTS_MAX + 1);
}
/**
* Constructs a PA-PAC-OPTIONS object from a DER encoding.
* @param encoding the ASN.1 encoded input
* @throws Asn1Exception if invalid DER
* @throws IOException if there is an error reading the DER value
*/
public PaPacOptions(DerValue encoding) throws Asn1Exception, IOException {
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
DerValue der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
flags = new KDCOptions(
der.getData().getDerValue());
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Setter for the claims flag
* @param value whether the claims flag is set or not
* @return the same PaPacOptions instance
*/
public PaPacOptions setClaims(boolean value) {
flags.set(CLAIMS, value);
return this;
}
/**
* Getter for the claims flag
* @return the claims flag value
*/
public boolean getClaims() {
return flags.get(CLAIMS);
}
/**
* Setter for the branch-aware flag
* @param value whether the branch-aware flag is set or not
* @return the same PaPacOptions instance
*/
public PaPacOptions setBranchAware(boolean value) {
flags.set(BRANCH_AWARE, value);
return this;
}
/**
* Getter for the branch-aware flag
* @return the branch-aware flag value
*/
public boolean getBranchAware() {
return flags.get(BRANCH_AWARE);
}
/**
* Setter for the forward-to-full-DC flag
* @param value whether the forward-to-full-DC flag is set or not
* @return the same PaPacOptions instance
*/
public PaPacOptions setForwardToFullDC(boolean value) {
flags.set(FORWARD_TO_FULL_DC, value);
return this;
}
/**
* Getter for the forward-to-full-DC flag
* @return the forward-to-full-DC flag value
*/
public boolean getForwardToFullDC() {
return flags.get(FORWARD_TO_FULL_DC);
}
/**
* Setter for the resource-based-constrained-delegation flag
* @param value whether the resource-based-constrained-delegation
* is set or not
* @return the same PaPacOptions instance
*/
public PaPacOptions setResourceBasedConstrainedDelegation(boolean value) {
flags.set(RESOURCE_BASED_CONSTRAINED_DELEGATION, value);
return this;
}
/**
* Getter for the resource-based-constrained-delegation flag
* @return the resource-based-constrained-delegation flag value
*/
public boolean getResourceBasedConstrainedDelegation() {
return flags.get(RESOURCE_BASED_CONSTRAINED_DELEGATION);
}
/**
* Encodes this PaPacOptions instance.
* @return an ASN.1 encoded PaPacOptions byte array
* @throws IOException if an I/O error occurs while encoding this
* PaPacOptions instance
*/
public byte[] asn1Encode() throws IOException {
byte[] bytes = null;
try(DerOutputStream temp = new DerOutputStream()) {
temp.write(
DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00),
flags.asn1Encode());
bytes = temp.toByteArray();
}
try(DerOutputStream temp = new DerOutputStream()) {
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
}
@Override
public String toString() {
return flags.toString();
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 2019, 2021, Red Hat, Inc.
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import sun.security.krb5.Credentials;
import sun.security.krb5.PrincipalName;
/*
* ReferralsCache class implements a cache scheme for referral TGTs as
* described in RFC 6806 - 10. Caching Information. The goal is to optimize
* resources (such as network traffic) when a client requests credentials for a
* service principal to a given KDC. If a referral TGT was previously received,
* cached information is used instead of issuing a new query. Once a referral
* TGT expires, the corresponding referral entry in the cache is removed.
*/
final class ReferralsCache {
private static Map<ReferralCacheKey, Map<String, ReferralCacheEntry>>
referralsMap = new HashMap<>();
static private final class ReferralCacheKey {
private PrincipalName cname;
private PrincipalName sname;
private PrincipalName user; // S4U2Self only
private byte[] userSvcTicketEnc; // S4U2Proxy only
ReferralCacheKey (PrincipalName cname, PrincipalName sname,
PrincipalName user, Ticket userSvcTicket) {
this.cname = cname;
this.sname = sname;
this.user = user;
if (userSvcTicket != null && userSvcTicket.encPart != null) {
byte[] userSvcTicketEnc = userSvcTicket.encPart.getBytes();
if (userSvcTicketEnc.length > 0) {
this.userSvcTicketEnc = userSvcTicketEnc;
}
}
}
public boolean equals(Object other) {
if (!(other instanceof ReferralCacheKey))
return false;
ReferralCacheKey that = (ReferralCacheKey)other;
return cname.equals(that.cname) &&
sname.equals(that.sname) &&
Objects.equals(user, that.user) &&
Arrays.equals(userSvcTicketEnc, that.userSvcTicketEnc);
}
public int hashCode() {
return cname.hashCode() + sname.hashCode() +
Objects.hashCode(user) +
Arrays.hashCode(userSvcTicketEnc);
}
}
static final class ReferralCacheEntry {
private final Credentials creds;
private final String toRealm;
ReferralCacheEntry(Credentials creds, String toRealm) {
this.creds = creds;
this.toRealm = toRealm;
}
Credentials getCreds() {
return creds;
}
String getToRealm() {
return toRealm;
}
}
/*
* Add a new referral entry to the cache, including: client principal,
* service principal, user principal (S4U2Self only), client service
* ticket (S4U2Proxy only), source KDC realm, destination KDC realm and
* referral TGT.
*
* If a loop is generated when adding the new referral, the first hop is
* automatically removed. For example, let's assume that adding a
* REALM-3.COM -> REALM-1.COM referral generates the following loop:
* REALM-1.COM -> REALM-2.COM -> REALM-3.COM -> REALM-1.COM. Then,
* REALM-1.COM -> REALM-2.COM referral entry is removed from the cache.
*/
static synchronized void put(PrincipalName cname, PrincipalName service,
PrincipalName user, Ticket[] userSvcTickets, String fromRealm,
String toRealm, Credentials creds) {
Ticket userSvcTicket = (userSvcTickets != null ?
userSvcTickets[0] : null);
ReferralCacheKey k = new ReferralCacheKey(cname, service,
user, userSvcTicket);
pruneExpired(k);
if (creds.getEndTime().before(new Date())) {
return;
}
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
if (entries == null) {
entries = new HashMap<String, ReferralCacheEntry>();
referralsMap.put(k, entries);
}
entries.remove(fromRealm);
ReferralCacheEntry newEntry = new ReferralCacheEntry(creds, toRealm);
entries.put(fromRealm, newEntry);
// Remove loops within the cache
ReferralCacheEntry current = newEntry;
List<ReferralCacheEntry> seen = new LinkedList<>();
while (current != null) {
if (seen.contains(current)) {
// Loop found. Remove the first referral to cut the loop.
entries.remove(newEntry.getToRealm());
break;
}
seen.add(current);
current = entries.get(current.getToRealm());
}
}
/*
* Obtain a referral entry from the cache given a client principal,
* a service principal, a user principal (S4U2Self only), a client
* service ticket (S4U2Proxy only) and a source KDC realm.
*/
static synchronized ReferralCacheEntry get(PrincipalName cname,
PrincipalName service, PrincipalName user,
Ticket[] userSvcTickets, String fromRealm) {
Ticket userSvcTicket = (userSvcTickets != null ?
userSvcTickets[0] : null);
ReferralCacheKey k = new ReferralCacheKey(cname, service,
user, userSvcTicket);
pruneExpired(k);
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
if (entries != null) {
ReferralCacheEntry toRef = entries.get(fromRealm);
if (toRef != null) {
return toRef;
}
}
return null;
}
/*
* Remove referral entries from the cache when referral TGTs expire.
*/
private static void pruneExpired(ReferralCacheKey k) {
Date now = new Date();
Map<String, ReferralCacheEntry> entries = referralsMap.get(k);
if (entries != null) {
for (Entry<String, ReferralCacheEntry> mapEntry :
entries.entrySet()) {
if (mapEntry.getValue().getCreds().getEndTime().before(now)) {
entries.remove(mapEntry.getKey());
}
}
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal;
import sun.security.action.GetPropertyAction;
import sun.security.krb5.internal.rcache.AuthTimeWithHash;
import sun.security.krb5.internal.rcache.MemoryCache;
import sun.security.krb5.internal.rcache.DflCache;
import java.security.AccessController;
/**
* Models the replay cache of an acceptor as described in
* RFC 4120 3.2.3.
* @since 1.8
*/
public abstract class ReplayCache {
public static ReplayCache getInstance(String type) {
if (type == null) {
return new MemoryCache();
} else if (type.equals("dfl") || type.startsWith("dfl:")) {
return new DflCache(type);
} else if (type.equals("none")) {
return new ReplayCache() {
@Override
public void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
throws KrbApErrException {
// no check at all
}
};
} else {
throw new IllegalArgumentException("Unknown type: " + type);
}
}
public static ReplayCache getInstance() {
String type = AccessController.doPrivileged(
new GetPropertyAction("sun.security.krb5.rcache"));
return getInstance(type);
}
/**
* Accepts or rejects an AuthTime.
* @param currTime the current time
* @param time AuthTimeWithHash object calculated from authenticator
* @throws KrbApErrException if the authenticator is a replay
*/
public abstract void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
throws KrbApErrException;
}

View File

@@ -0,0 +1,40 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.KrbCryptoException;
public interface SeqNumber {
public void randInit();
public void init(int start);
public int current();
public int next();
public int step();
}

View File

@@ -0,0 +1,68 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.Realm;
import sun.security.krb5.RealmException;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.util.*;
import java.io.IOException;
public class TGSRep extends KDCRep {
public TGSRep(
PAData[] new_pAData,
PrincipalName new_cname,
Ticket new_ticket,
EncryptedData new_encPart
) throws IOException {
super(new_pAData, new_cname, new_ticket,
new_encPart, Krb5.KRB_TGS_REP);
}
public TGSRep(byte[] data) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(new DerValue(data));
}
public TGSRep(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding);
}
private void init(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding, Krb5.KRB_TGS_REP);
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.*;
import sun.security.util.*;
import java.io.IOException;
public class TGSReq extends KDCReq {
public TGSReq(PAData[] new_pAData, KDCReqBody new_reqBody) throws IOException {
super(new_pAData, new_reqBody, Krb5.KRB_TGS_REQ);
}
public TGSReq(byte[] data) throws Asn1Exception,
IOException, KrbException {
init(new DerValue(data));
}
public TGSReq(DerValue encoding) throws Asn1Exception,
IOException, KrbException {
init(encoding);
}
private void init(DerValue encoding) throws Asn1Exception,
IOException, KrbException {
init(encoding, Krb5.KRB_TGS_REQ);
}
}

View File

@@ -0,0 +1,176 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.Realm;
import sun.security.krb5.RealmException;
import sun.security.util.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 Ticket type.
*
* <pre>{@code
* Ticket ::= [APPLICATION 1] SEQUENCE {
* tkt-vno [0] INTEGER (5),
* realm [1] Realm,
* sname [2] PrincipalName,
* enc-part [3] EncryptedData -- EncTicketPart
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class Ticket implements Cloneable {
public int tkt_vno;
public PrincipalName sname;
public EncryptedData encPart;
private Ticket() {
}
public Object clone() {
Ticket new_ticket = new Ticket();
new_ticket.sname = (PrincipalName)sname.clone();
new_ticket.encPart = (EncryptedData)encPart.clone();
new_ticket.tkt_vno = tkt_vno;
return new_ticket;
}
public Ticket(
PrincipalName new_sname,
EncryptedData new_encPart
) {
tkt_vno = Krb5.TICKET_VNO;
sname = new_sname;
encPart = new_encPart;
}
public Ticket(byte[] data) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(new DerValue(data));
}
public Ticket(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
init(encoding);
}
/**
* Initializes a Ticket object.
* @param encoding a single DER-encoded value.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
* @exception KrbApErrException if the value read from the DER-encoded data stream does not match the pre-defined value.
* @exception RealmException if an error occurs while parsing a Realm object.
*/
private void init(DerValue encoding) throws Asn1Exception,
RealmException, KrbApErrException, IOException {
DerValue der;
DerValue subDer;
if (((encoding.getTag() & (byte)0x1F) != Krb5.KRB_TKT)
|| (encoding.isApplication() != true)
|| (encoding.isConstructed() != true))
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if (der.getTag() != DerValue.tag_Sequence)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
subDer = der.getData().getDerValue();
if ((subDer.getTag() & (byte)0x1F) != (byte)0x00)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
tkt_vno = subDer.getData().getBigInteger().intValue();
if (tkt_vno != Krb5.TICKET_VNO)
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION);
Realm srealm = Realm.parse(der.getData(), (byte)0x01, false);
sname = PrincipalName.parse(der.getData(), (byte)0x02, false, srealm);
encPart = EncryptedData.parse(der.getData(), (byte)0x03, false);
if (der.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes a Ticket object.
* @return byte array of encoded ticket object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
DerValue der[] = new DerValue[4];
temp.putInteger(BigInteger.valueOf(tkt_vno));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), sname.getRealm().asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), sname.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), encPart.asn1Encode());
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
DerOutputStream ticket = new DerOutputStream();
ticket.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte)0x01), temp);
return ticket.toByteArray();
}
/**
* Parse (unmarshal) a Ticket from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicate if this data field is optional
* @return an instance of Ticket.
*/
public static Ticket parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException, RealmException, KrbApErrException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F)!= explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
else {
DerValue subDer = der.getData().getDerValue();
return new Ticket(subDer);
}
}
}

View File

@@ -0,0 +1,194 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.internal.util.KerberosFlags;
import sun.security.util.*;
import java.io.IOException;
/**
* Implements the ASN.1TicketFlags type.
*
* TicketFlags ::= BIT STRING
* {
* reserved(0),
* forwardable(1),
* forwarded(2),
* proxiable(3),
* proxy(4),
* may-postdate(5),
* postdated(6),
* invalid(7),
* renewable(8),
* initial(9),
* pre-authent(10),
* hw-authent(11),
* enc-pa-rep(15)
* }
*/
public class TicketFlags extends KerberosFlags {
public TicketFlags() {
super(Krb5.TKT_OPTS_MAX + 1);
}
public TicketFlags (boolean[] flags) throws Asn1Exception {
super(flags);
if (flags.length > Krb5.TKT_OPTS_MAX + 1) {
throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH);
}
}
public TicketFlags(int size, byte[] data) throws Asn1Exception {
super(size, data);
if ((size > data.length * BITS_PER_UNIT) || (size > Krb5.TKT_OPTS_MAX + 1))
throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH);
}
public TicketFlags(DerValue encoding) throws IOException, Asn1Exception {
this(encoding.getUnalignedBitString(true).toBooleanArray());
}
/**
* Parse (unmarshal) a ticket flag from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicate if this data field is optional
* @return an instance of TicketFlags.
*
*/
public static TicketFlags parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
else {
DerValue subDer = der.getData().getDerValue();
return new TicketFlags(subDer);
}
}
public Object clone() {
try {
return new TicketFlags(this.toBooleanArray());
}
catch (Exception e) {
return null;
}
}
public boolean match(LoginOptions options) {
boolean matched = false;
//We currently only consider if forwardable renewable and proxiable are match
if (this.get(Krb5.TKT_OPTS_FORWARDABLE) == (options.get(KDCOptions.FORWARDABLE))) {
if (this.get(Krb5.TKT_OPTS_PROXIABLE) == (options.get(KDCOptions.PROXIABLE))) {
if (this.get(Krb5.TKT_OPTS_RENEWABLE) == (options.get(KDCOptions.RENEWABLE))) {
matched = true;
}
}
}
return matched;
}
public boolean match(TicketFlags flags) {
boolean matched = true;
for (int i = 0; i <= Krb5.TKT_OPTS_MAX; i++) {
if (this.get(i) != flags.get(i)) {
return false;
}
}
return matched;
}
/**
* Returns the string representative of ticket flags.
*/
public String toString() {
StringBuffer sb = new StringBuffer();
boolean[] flags = toBooleanArray();
for (int i = 0; i < flags.length; i++) {
if (flags[i] == true) {
switch (i) {
case 0:
sb.append("RESERVED;");
break;
case 1:
sb.append("FORWARDABLE;");
break;
case 2:
sb.append("FORWARDED;");
break;
case 3:
sb.append("PROXIABLE;");
break;
case 4:
sb.append("PROXY;");
break;
case 5:
sb.append("MAY-POSTDATE;");
break;
case 6:
sb.append("POSTDATED;");
break;
case 7:
sb.append("INVALID;");
break;
case 8:
sb.append("RENEWABLE;");
break;
case 9:
sb.append("INITIAL;");
break;
case 10:
sb.append("PRE-AUTHENT;");
break;
case 11:
sb.append("HW-AUTHENT;");
break;
case 15:
sb.append("ENC-PA-REP;");
break;
}
}
}
String result = sb.toString();
if (result.length() > 0) {
result = result.substring(0, result.length() - 1);
}
return result;
}
}

View File

@@ -0,0 +1,136 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
import java.math.BigInteger;
/**
* Implements the ASN.1 TransitedEncoding type.
*
* <pre>{@code
* TransitedEncoding ::= SEQUENCE {
* tr-type [0] Int32 -- must be registered --,
* contents [1] OCTET STRING
* }
* }</pre>
*
* <p>
* This definition reflects the Network Working Group RFC 4120
* specification available at
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
public class TransitedEncoding {
public int trType;
public byte[] contents;
public TransitedEncoding(int type, byte[] cont) {
trType = type;
contents = cont;
}
/**
* Constructs a TransitedEncoding object.
* @param encoding a Der-encoded data.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public TransitedEncoding(DerValue encoding) throws Asn1Exception, IOException {
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
DerValue der;
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x00) {
trType = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x1F) == 0x01) {
contents = der.getData().getOctetString();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
if (der.getData().available() > 0)
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
/**
* Encodes a TransitedEncoding object.
* @return the byte array of the encoded TransitedEncoding object.
* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(trType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
temp = new DerOutputStream();
temp.putOctetString(contents);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Parse (unmarshal) a TransitedEncoding object from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
* @param data the Der input stream value, which contains one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicate if this data field is optional
* @return an instance of TransitedEncoding.
*
*/
public static TransitedEncoding parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag))
return null;
DerValue der = data.getDerValue();
if (explicitTag != (der.getTag() & (byte)0x1F)) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
else {
DerValue subDer = der.getData().getDerValue();
return new TransitedEncoding(subDer);
}
}
}

View File

@@ -0,0 +1,416 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import sun.misc.IOUtils;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.util.KrbDataInputStream;
/**
* This class extends KrbDataInputStream. It is used for parsing FCC-format
* data from file to memory.
*
* @author Yanni Zhang
*
*/
public class CCacheInputStream extends KrbDataInputStream implements FileCCacheConstants {
/*
* FCC version 2 contains type information for principals. FCC
* version 1 does not.
*
* FCC version 3 contains keyblock encryption type information, and is
* architecture independent. Previous versions are not.
*
* The code will accept version 1, 2, and 3 ccaches, and depending
* what KRB5_FCC_DEFAULT_FVNO is set to, it will create version 1, 2,
* or 3 FCC caches.
*
* The default credentials cache should be type 3 for now (see
* init_ctx.c).
*/
/* V4 of the credentials cache format allows for header tags */
private static boolean DEBUG = Krb5.DEBUG;
public CCacheInputStream(InputStream is){
super(is);
}
/* Read tag field introduced in KRB5_FCC_FVNO_4 */
// this needs to be public for Kinit.
public Tag readTag() throws IOException {
char[] buf = new char[1024];
int len;
int tag = -1;
int taglen;
Integer time_offset = null;
Integer usec_offset = null;
len = read(2);
if (len < 0) {
throw new IOException("stop.");
}
if (len > buf.length) {
throw new IOException("Invalid tag length.");
}
while (len > 0) {
tag = read(2);
taglen = read(2);
switch (tag) {
case FCC_TAG_DELTATIME:
time_offset = new Integer(read(4));
usec_offset = new Integer(read(4));
break;
default:
}
len = len - (4 + taglen);
}
return new Tag(len, tag, time_offset, usec_offset);
}
/*
* In file-based credential cache, the realm name is stored as part of
* principal name at the first place.
*/
// made public for KinitOptions to call directly
public PrincipalName readPrincipal(int version) throws IOException, RealmException {
int type, length, namelength, kret;
String[] pname = null;
String realm;
/* Read principal type */
if (version == KRB5_FCC_FVNO_1) {
type = KRB5_NT_UNKNOWN;
} else {
type = read(4);
}
length = readLength4();
List<String> result = new ArrayList<String>();
/*
* DCE includes the principal's realm in the count; the new format
* does not.
*/
if (version == KRB5_FCC_FVNO_1)
length--;
for (int i = 0; i <= length; i++) {
namelength = readLength4();
byte[] bytes = IOUtils.readExactlyNBytes(this, namelength);
result.add(new String(bytes));
}
if (result.isEmpty()) {
throw new IOException("No realm or principal");
}
if (isRealm(result.get(0))) {
realm = result.remove(0);
if (result.isEmpty()) {
throw new IOException("No principal name components");
}
return new PrincipalName(
type,
result.toArray(new String[result.size()]),
new Realm(realm));
}
try {
return new PrincipalName(
type,
result.toArray(new String[result.size()]),
Realm.getDefault());
} catch (RealmException re) {
return null;
}
}
/*
* In practice, a realm is named by uppercasing the DNS domain name. we currently
* rely on this to determine if the string within the principal identifier is realm
* name.
*
*/
boolean isRealm(String str) {
try {
Realm r = new Realm(str);
}
catch (Exception e) {
return false;
}
StringTokenizer st = new StringTokenizer(str, ".");
String s;
while (st.hasMoreTokens()) {
s = st.nextToken();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) >= 141) {
return false;
}
}
}
return true;
}
EncryptionKey readKey(int version) throws IOException {
int keyType, keyLen;
keyType = read(2);
if (version == KRB5_FCC_FVNO_3)
read(2); /* keytype recorded twice in fvno 3 */
keyLen = readLength4();
byte[] bytes = IOUtils.readExactlyNBytes(this, keyLen);
return new EncryptionKey(bytes, keyType, new Integer(version));
}
long[] readTimes() throws IOException {
long[] times = new long[4];
times[0] = (long)read(4) * 1000;
times[1] = (long)read(4) * 1000;
times[2] = (long)read(4) * 1000;
times[3] = (long)read(4) * 1000;
return times;
}
boolean readskey() throws IOException {
if (read() == 0) {
return false;
}
else return true;
}
HostAddress[] readAddr() throws IOException, KrbApErrException {
int numAddrs, addrType, addrLength;
numAddrs = readLength4();
if (numAddrs > 0) {
List<HostAddress> addrs = new ArrayList<>();
for (int i = 0; i < numAddrs; i++) {
addrType = read(2);
addrLength = readLength4();
if (!(addrLength == 4 || addrLength == 16)) {
if (DEBUG) {
System.out.println("Incorrect address format.");
}
return null;
}
byte[] result = new byte[addrLength];
for (int j = 0; j < addrLength; j++)
result[j] = (byte)read(1);
addrs.add(new HostAddress(addrType, result));
}
return addrs.toArray(new HostAddress[addrs.size()]);
}
return null;
}
AuthorizationDataEntry[] readAuth() throws IOException {
int num, adtype, adlength;
num = readLength4();
if (num > 0) {
List<AuthorizationDataEntry> auData = new ArrayList<>();
byte[] data = null;
for (int i = 0; i < num; i++) {
adtype = read(2);
adlength = readLength4();
data = IOUtils.readExactlyNBytes(this, adlength);
auData.add(new AuthorizationDataEntry(adtype, data));
}
return auData.toArray(new AuthorizationDataEntry[auData.size()]);
}
else return null;
}
byte[] readData() throws IOException {
int length;
length = readLength4();
if (length == 0) {
return null;
} else {
return IOUtils.readExactlyNBytes(this, length);
}
}
boolean[] readFlags() throws IOException {
boolean[] flags = new boolean[Krb5.TKT_OPTS_MAX+1];
int ticketFlags;
ticketFlags = read(4);
if ((ticketFlags & 0x40000000) == TKT_FLG_FORWARDABLE)
flags[1] = true;
if ((ticketFlags & 0x20000000) == TKT_FLG_FORWARDED)
flags[2] = true;
if ((ticketFlags & 0x10000000) == TKT_FLG_PROXIABLE)
flags[3] = true;
if ((ticketFlags & 0x08000000) == TKT_FLG_PROXY)
flags[4] = true;
if ((ticketFlags & 0x04000000) == TKT_FLG_MAY_POSTDATE)
flags[5] = true;
if ((ticketFlags & 0x02000000) == TKT_FLG_POSTDATED)
flags[6] = true;
if ((ticketFlags & 0x01000000) == TKT_FLG_INVALID)
flags[7] = true;
if ((ticketFlags & 0x00800000) == TKT_FLG_RENEWABLE)
flags[8] = true;
if ((ticketFlags & 0x00400000) == TKT_FLG_INITIAL)
flags[9] = true;
if ((ticketFlags & 0x00200000) == TKT_FLG_PRE_AUTH)
flags[10] = true;
if ((ticketFlags & 0x00100000) == TKT_FLG_HW_AUTH)
flags[11] = true;
if (DEBUG) {
String msg = ">>> CCacheInputStream: readFlags() ";
if (flags[1] == true) {
msg += " FORWARDABLE;";
}
if (flags[2] == true) {
msg += " FORWARDED;";
}
if (flags[3] == true) {
msg += " PROXIABLE;";
}
if (flags[4] == true) {
msg += " PROXY;";
}
if (flags[5] == true) {
msg += " MAY_POSTDATE;";
}
if (flags[6] == true) {
msg += " POSTDATED;";
}
if (flags[7] == true) {
msg += " INVALID;";
}
if (flags[8] == true) {
msg += " RENEWABLE;";
}
if (flags[9] == true) {
msg += " INITIAL;";
}
if (flags[10] == true) {
msg += " PRE_AUTH;";
}
if (flags[11] == true) {
msg += " HW_AUTH;";
}
System.out.println(msg);
}
return flags;
}
/**
* Reads the next cred or config entry in stream.
* @return the next cred or config entry, null if data unparseable.
*
* When data is unparseable, this method makes sure the correct number of
* bytes are consumed so it's safe to start reading the next element.
*/
Object readCred(int version) throws IOException,RealmException, KrbApErrException, Asn1Exception {
PrincipalName cpname = null;
try {
cpname = readPrincipal(version);
} catch (Exception e) {
// Do not return here. All data for this cred should be fully
// consumed so that we can read the next one.
}
if (DEBUG) {
System.out.println(">>>DEBUG <CCacheInputStream> client principal is " + cpname);
}
PrincipalName spname = null;
try {
spname = readPrincipal(version);
} catch (Exception e) {
// same as above
}
if (DEBUG) {
System.out.println(">>>DEBUG <CCacheInputStream> server principal is " + spname);
}
EncryptionKey key = readKey(version);
if (DEBUG) {
System.out.println(">>>DEBUG <CCacheInputStream> key type: " + key.getEType());
}
long times[] = readTimes();
KerberosTime authtime = new KerberosTime(times[0]);
KerberosTime starttime =
(times[1]==0) ? null : new KerberosTime(times[1]);
KerberosTime endtime = new KerberosTime(times[2]);
KerberosTime renewTill =
(times[3]==0) ? null : new KerberosTime(times[3]);
if (DEBUG) {
System.out.println(">>>DEBUG <CCacheInputStream> auth time: " + authtime.toDate().toString());
System.out.println(">>>DEBUG <CCacheInputStream> start time: " +
((starttime==null)?"null":starttime.toDate().toString()));
System.out.println(">>>DEBUG <CCacheInputStream> end time: " + endtime.toDate().toString());
System.out.println(">>>DEBUG <CCacheInputStream> renew_till time: " +
((renewTill==null)?"null":renewTill.toDate().toString()));
}
boolean skey = readskey();
boolean flags[] = readFlags();
TicketFlags tFlags = new TicketFlags(flags);
HostAddress addr[] = readAddr();
HostAddresses addrs = null;
if (addr != null) {
addrs = new HostAddresses(addr);
}
AuthorizationDataEntry[] auDataEntry = readAuth();
AuthorizationData auData = null;
if (auDataEntry != null) {
auData = new AuthorizationData(auDataEntry);
}
byte[] ticketData = readData();
byte[] ticketData2 = readData();
// Skip this cred if either cpname or spname isn't created.
if (cpname == null || spname == null) {
return null;
}
try {
if (spname.getRealmString().equals("X-CACHECONF:")) {
String[] nameParts = spname.getNameStrings();
if (nameParts[0].equals("krb5_ccache_conf_data")) {
return new CredentialsCache.ConfigEntry(nameParts[1],
nameParts.length > 2 ? new PrincipalName(nameParts[2]) : null,
ticketData);
}
}
return new Credentials(cpname, spname, key, authtime, starttime,
endtime, renewTill, skey, tFlags,
addrs, auData,
ticketData != null ? new Ticket(ticketData) : null,
ticketData2 != null ? new Ticket(ticketData2) : null);
} catch (Exception e) { // If any of new Ticket(*) fails.
if (DEBUG) {
e.printStackTrace(System.out);
}
return null;
}
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
import java.io.IOException;
import java.io.OutputStream;
import sun.security.krb5.internal.util.KrbDataOutputStream;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
/**
* This class implements a buffered output stream. It provides functions to write FCC-format data to a disk file.
*
* @author Yanni Zhang
*
*/
public class CCacheOutputStream extends KrbDataOutputStream implements FileCCacheConstants {
public CCacheOutputStream(OutputStream os) {
super(os);
}
public void writeHeader(PrincipalName p, int version) throws IOException {
write((version & 0xff00) >> 8);
write(version & 0x00ff);
p.writePrincipal(this);
}
/**
* Writes a credentials in FCC format to this cache output stream.
*
* @param creds the credentials to be written to the output stream.
* @exception IOException if an I/O exception occurs.
* @exception Asn1Exception if an Asn1Exception occurs.
*/
/*For object data fields which themselves have multiple data fields, such as PrincipalName, EncryptionKey
HostAddresses, AuthorizationData, I created corresponding write methods (writePrincipal,
writeKey,...) in each class, since converting the object into FCC format data stream
should be encapsulated in object itself.
*/
public void addCreds(Credentials creds) throws IOException, Asn1Exception {
creds.cname.writePrincipal(this);
creds.sname.writePrincipal(this);
creds.key.writeKey(this);
write32((int)(creds.authtime.getTime()/1000));
if (creds.starttime != null)
write32((int)(creds.starttime.getTime()/1000));
else write32(0);
write32((int)(creds.endtime.getTime()/1000));
if (creds.renewTill != null)
write32((int)(creds.renewTill.getTime()/1000));
else write32(0);
if (creds.isEncInSKey) {
write8(1);
}
else write8(0);
writeFlags(creds.flags);
if (creds.caddr == null)
write32(0);
else
creds.caddr.writeAddrs(this);
if (creds.authorizationData == null) {
write32(0);
}
else
creds.authorizationData.writeAuth(this);
writeTicket(creds.ticket);
writeTicket(creds.secondTicket);
}
public void addConfigEntry(PrincipalName cname, CredentialsCache.ConfigEntry e)
throws IOException {
cname.writePrincipal(this);
e.getSName().writePrincipal(this);
write16(0); write16(0); write32(0);
write32(0); write32(0); write32(0); write32(0);
write8(0);
write32(0);
write32(0);
write32(0);
write32(e.getData().length);
write(e.getData());
write32(0);
}
void writeTicket(Ticket t) throws IOException, Asn1Exception {
if (t == null) {
write32(0);
}
else {
byte[] bytes = t.asn1Encode();
write32(bytes.length);
write(bytes, 0, bytes.length);
}
}
void writeFlags(TicketFlags flags) throws IOException {
int tFlags = 0;
boolean[] f = flags.toBooleanArray();
if (f[1] == true) {
tFlags |= TKT_FLG_FORWARDABLE;
}
if (f[2] == true) {
tFlags |= TKT_FLG_FORWARDED;
}
if (f[3] == true) {
tFlags |= TKT_FLG_PROXIABLE;
}
if (f[4] == true) {
tFlags |= TKT_FLG_PROXY;
}
if (f[5] == true) {
tFlags |= TKT_FLG_MAY_POSTDATE;
}
if (f[6] == true) {
tFlags |= TKT_FLG_POSTDATED;
}
if (f[7] == true) {
tFlags |= TKT_FLG_INVALID;
}
if (f[8] == true) {
tFlags |= TKT_FLG_RENEWABLE;
}
if (f[9] == true) {
tFlags |= TKT_FLG_INITIAL;
}
if (f[10] == true) {
tFlags |= TKT_FLG_PRE_AUTH;
}
if (f[11] == true) {
tFlags |= TKT_FLG_HW_AUTH;
}
write32(tFlags);
}
}

View File

@@ -0,0 +1,235 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
public class Credentials {
PrincipalName cname;
PrincipalName sname;
EncryptionKey key;
KerberosTime authtime;
KerberosTime starttime;//optional
KerberosTime endtime;
KerberosTime renewTill; //optional
HostAddresses caddr; //optional; for proxied tickets only
AuthorizationData authorizationData; //optional, not being actually used
public boolean isEncInSKey; // true if ticket is encrypted in another ticket's skey
TicketFlags flags;
Ticket ticket;
Ticket secondTicket; //optional
private boolean DEBUG = Krb5.DEBUG;
public Credentials(
PrincipalName new_cname,
PrincipalName new_sname,
EncryptionKey new_key,
KerberosTime new_authtime,
KerberosTime new_starttime,
KerberosTime new_endtime,
KerberosTime new_renewTill,
boolean new_isEncInSKey,
TicketFlags new_flags,
HostAddresses new_caddr,
AuthorizationData new_authData,
Ticket new_ticket,
Ticket new_secondTicket) {
cname = (PrincipalName) new_cname.clone();
sname = (PrincipalName) new_sname.clone();
key = (EncryptionKey) new_key.clone();
authtime = new_authtime;
starttime = new_starttime;
endtime = new_endtime;
renewTill = new_renewTill;
if (new_caddr != null) {
caddr = (HostAddresses) new_caddr.clone();
}
if (new_authData != null) {
authorizationData = (AuthorizationData) new_authData.clone();
}
isEncInSKey = new_isEncInSKey;
flags = (TicketFlags) new_flags.clone();
ticket = (Ticket) (new_ticket.clone());
if (new_secondTicket != null) {
secondTicket = (Ticket) new_secondTicket.clone();
}
}
public Credentials(
KDCRep kdcRep,
Ticket new_secondTicket,
AuthorizationData new_authorizationData,
boolean new_isEncInSKey) {
if (kdcRep.encKDCRepPart == null) //can't store while encrypted
{
return;
}
cname = (PrincipalName) kdcRep.cname.clone();
ticket = (Ticket) kdcRep.ticket.clone();
key = (EncryptionKey) kdcRep.encKDCRepPart.key.clone();
flags = (TicketFlags) kdcRep.encKDCRepPart.flags.clone();
authtime = kdcRep.encKDCRepPart.authtime;
starttime = kdcRep.encKDCRepPart.starttime;
endtime = kdcRep.encKDCRepPart.endtime;
renewTill = kdcRep.encKDCRepPart.renewTill;
sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone();
caddr = (HostAddresses) kdcRep.encKDCRepPart.caddr.clone();
secondTicket = (Ticket) new_secondTicket.clone();
authorizationData =
(AuthorizationData) new_authorizationData.clone();
isEncInSKey = new_isEncInSKey;
}
public Credentials(KDCRep kdcRep) {
this(kdcRep, null);
}
public Credentials(KDCRep kdcRep, Ticket new_ticket) {
sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone();
cname = (PrincipalName) kdcRep.cname.clone();
key = (EncryptionKey) kdcRep.encKDCRepPart.key.clone();
authtime = kdcRep.encKDCRepPart.authtime;
starttime = kdcRep.encKDCRepPart.starttime;
endtime = kdcRep.encKDCRepPart.endtime;
renewTill = kdcRep.encKDCRepPart.renewTill;
// if (kdcRep.msgType == Krb5.KRB_AS_REP) {
// isEncInSKey = false;
// secondTicket = null;
// }
flags = kdcRep.encKDCRepPart.flags;
if (kdcRep.encKDCRepPart.caddr != null) {
caddr = (HostAddresses) kdcRep.encKDCRepPart.caddr.clone();
} else {
caddr = null;
}
ticket = (Ticket) kdcRep.ticket.clone();
if (new_ticket != null) {
secondTicket = (Ticket) new_ticket.clone();
isEncInSKey = true;
} else {
secondTicket = null;
isEncInSKey = false;
}
}
/**
* Checks if this credential is expired
*/
public boolean isValid() {
boolean valid = true;
if (endtime.getTime() < System.currentTimeMillis()) {
valid = false;
} else if (starttime != null) {
if (starttime.getTime() > System.currentTimeMillis()) {
valid = false;
}
} else {
if (authtime.getTime() > System.currentTimeMillis()) {
valid = false;
}
}
return valid;
}
public PrincipalName getServicePrincipal() throws RealmException {
return sname;
}
public Ticket getTicket() throws RealmException {
return ticket;
}
public PrincipalName getServicePrincipal2() throws RealmException {
return secondTicket == null ? null : secondTicket.sname;
}
public PrincipalName getClientPrincipal() throws RealmException {
return cname;
}
public sun.security.krb5.Credentials setKrbCreds() {
// Note: We will not pass authorizationData to s.s.k.Credentials. The
// field in that class will be passed to Krb5Context as the return
// value of ExtendedGSSContext.inquireSecContext(KRB5_GET_AUTHZ_DATA),
// which is documented as the authData in the service ticket. That
// is on the acceptor side.
//
// This class is for the initiator side. Also, authdata inside a ccache
// is most likely to be the one in Authenticator in PA-TGS-REQ encoded
// in TGS-REQ, therefore only stored with a service ticket. Currently
// in Java, we only reads TGTs.
return new sun.security.krb5.Credentials(ticket, cname, null, sname,
null, key, flags, authtime, starttime, endtime, renewTill,
caddr);
}
public KerberosTime getStartTime() {
return starttime;
}
public KerberosTime getAuthTime() {
return authtime;
}
public KerberosTime getEndTime() {
return endtime;
}
public KerberosTime getRenewTill() {
return renewTill;
}
public TicketFlags getTicketFlags() {
return flags;
}
public int getEType() {
return key.getEType();
}
public EncryptionKey getKey() {
return key;
}
public int getTktEType() {
return ticket.encPart.getEType();
}
public int getTktEType2() {
return (secondTicket == null) ? 0 : secondTicket.encPart.getEType();
}
}

View File

@@ -0,0 +1,176 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import java.util.List;
import java.io.IOException;
/**
* CredentialsCache stores credentials(tickets, session keys, etc) in a semi-permanent store
* for later use by different program.
*
* @author Yanni Zhang
*/
public abstract class CredentialsCache {
static CredentialsCache singleton = null;
static String cacheName;
private static boolean DEBUG = Krb5.DEBUG;
public static CredentialsCache getInstance(PrincipalName principal) {
return FileCredentialsCache.acquireInstance(principal, null);
}
public static CredentialsCache getInstance(String cache) {
if ((cache.length() >= 5) && cache.substring(0, 5).equalsIgnoreCase("FILE:")) {
return FileCredentialsCache.acquireInstance(null, cache.substring(5));
}
// XXX else, memory credential cache
// default is file credential cache.
return FileCredentialsCache.acquireInstance(null, cache);
}
public static CredentialsCache getInstance(PrincipalName principal,
String cache) {
// XXX Modify this to use URL framework of the JDK
if (cache != null &&
(cache.length() >= 5) &&
cache.regionMatches(true, 0, "FILE:", 0, 5)) {
return FileCredentialsCache.acquireInstance(principal,
cache.substring(5));
}
// When cache is null, read the default cache.
// XXX else ..we haven't provided support for memory credential cache
// yet. (supported in native code)
// default is file credentials cache.
return FileCredentialsCache.acquireInstance(principal, cache);
}
/**
* Gets the default credentials cache.
*/
public static CredentialsCache getInstance() {
// Default credentials cache is file-based.
return FileCredentialsCache.acquireInstance();
}
public static CredentialsCache create(PrincipalName principal, String name) {
if (name == null) {
throw new RuntimeException("cache name error");
}
if ((name.length() >= 5)
&& name.regionMatches(true, 0, "FILE:", 0, 5)) {
name = name.substring(5);
return (FileCredentialsCache.New(principal, name));
}
// else return file credentials cache
// default is file credentials cache.
return (FileCredentialsCache.New(principal, name));
}
public static CredentialsCache create(PrincipalName principal) {
// create a default credentials cache for a specified principal
return (FileCredentialsCache.New(principal));
}
public static String cacheName() {
return cacheName;
}
public abstract PrincipalName getPrimaryPrincipal();
public abstract void update(Credentials c);
public abstract void save() throws IOException, KrbException;
public abstract Credentials[] getCredsList();
public abstract Credentials getDefaultCreds();
public abstract sun.security.krb5.Credentials getInitialCreds();
public abstract Credentials getCreds(PrincipalName sname);
public abstract Credentials getCreds(LoginOptions options, PrincipalName sname);
public abstract void addConfigEntry(ConfigEntry e);
public abstract List<ConfigEntry> getConfigEntries();
public ConfigEntry getConfigEntry(String name) {
List<ConfigEntry> entries = getConfigEntries();
if (entries != null) {
for (ConfigEntry e : entries) {
if (e.getName().equals(name)) {
return e;
}
}
}
return null;
}
public static class ConfigEntry {
public ConfigEntry(String name, PrincipalName princ, byte[] data) {
this.name = name;
this.princ = princ;
this.data = data;
}
private final String name;
private final PrincipalName princ;
private final byte[] data; // not worth cloning
public String getName() {
return name;
}
public PrincipalName getPrinc() {
return princ;
}
public byte[] getData() {
return data;
}
@Override
public String toString() {
return name + (princ != null ? ("." + princ) : "")
+ ": " + new String(data);
}
public PrincipalName getSName() {
try {
return new PrincipalName("krb5_ccache_conf_data/" + name
+ (princ != null ? ("/" + princ) : "")
+ "@X-CACHECONF:");
} catch (RealmException e) {
throw new AssertionError(e);
}
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
/**
* Constants used by file-based credential cache classes.
*
* @author Yanni Zhang
*
*/
public interface FileCCacheConstants {
/*
* FCC version 2 contains type information for principals. FCC
* version 1 does not.
*
* FCC version 3 contains keyblock encryption type information, and is
* architecture independent. Previous versions are not. */
public final int KRB5_FCC_FVNO_1 = 0x501;
public final int KRB5_FCC_FVNO_2 = 0x502;
public final int KRB5_FCC_FVNO_3 = 0x503;
public final int KRB5_FCC_FVNO_4 = 0x504;
public final int FCC_TAG_DELTATIME = 1;
public final int KRB5_NT_UNKNOWN = 0;
public final int TKT_FLG_FORWARDABLE = 0x40000000;
public final int TKT_FLG_FORWARDED = 0x20000000;
public final int TKT_FLG_PROXIABLE = 0x10000000;
public final int TKT_FLG_PROXY = 0x08000000;
public final int TKT_FLG_MAY_POSTDATE = 0x04000000;
public final int TKT_FLG_POSTDATED = 0x02000000;
public final int TKT_FLG_INVALID = 0x01000000;
public final int TKT_FLG_RENEWABLE = 0x00800000;
public final int TKT_FLG_INITIAL = 0x00400000;
public final int TKT_FLG_PRE_AUTH = 0x00200000;
public final int TKT_FLG_HW_AUTH = 0x00100000;
}

View File

@@ -0,0 +1,643 @@
/*
* Copyright (c) 2000, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* ===========================================================================
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
*
* Copyright 1997 The Open Group Research Institute. All rights reserved.
* ===========================================================================
*
*/
package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.util.SecurityProperties;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.*;
/**
* CredentialsCache stores credentials(tickets, session keys, etc) in a
* semi-permanent store
* for later use by different program.
*
* @author Yanni Zhang
* @author Ram Marti
*/
public class FileCredentialsCache extends CredentialsCache
implements FileCCacheConstants {
public int version;
public Tag tag; // optional
public PrincipalName primaryPrincipal;
private Vector<Credentials> credentialsList;
private static String dir;
private static boolean DEBUG = Krb5.DEBUG;
public static synchronized FileCredentialsCache acquireInstance(
PrincipalName principal, String cache) {
try {
FileCredentialsCache fcc = new FileCredentialsCache();
if (cache == null) {
cacheName = FileCredentialsCache.getDefaultCacheName();
} else {
cacheName = FileCredentialsCache.checkValidation(cache);
}
if ((cacheName == null) || !(new File(cacheName)).exists()) {
// invalid cache name or the file doesn't exist
return null;
}
if (principal != null) {
fcc.primaryPrincipal = principal;
}
fcc.load(cacheName);
return fcc;
} catch (IOException e) {
// we don't handle it now, instead we return a null at the end.
if (DEBUG) {
e.printStackTrace();
}
} catch (KrbException e) {
// we don't handle it now, instead we return a null at the end.
if (DEBUG) {
e.printStackTrace();
}
}
return null;
}
public static FileCredentialsCache acquireInstance() {
return acquireInstance(null, null);
}
static synchronized FileCredentialsCache New(PrincipalName principal,
String name) {
try {
FileCredentialsCache fcc = new FileCredentialsCache();
cacheName = FileCredentialsCache.checkValidation(name);
if (cacheName == null) {
// invalid cache name or the file doesn't exist
return null;
}
fcc.init(principal, cacheName);
return fcc;
}
catch (IOException e) {
}
catch (KrbException e) {
}
return null;
}
static synchronized FileCredentialsCache New(PrincipalName principal) {
try {
FileCredentialsCache fcc = new FileCredentialsCache();
cacheName = FileCredentialsCache.getDefaultCacheName();
fcc.init(principal, cacheName);
return fcc;
}
catch (IOException e) {
if (DEBUG) {
e.printStackTrace();
}
} catch (KrbException e) {
if (DEBUG) {
e.printStackTrace();
}
}
return null;
}
private FileCredentialsCache() {
}
boolean exists(String cache) {
File file = new File(cache);
if (file.exists()) {
return true;
} else return false;
}
synchronized void init(PrincipalName principal, String name)
throws IOException, KrbException {
primaryPrincipal = principal;
try (FileOutputStream fos = new FileOutputStream(name);
CCacheOutputStream cos = new CCacheOutputStream(fos)) {
version = KRB5_FCC_FVNO_3;
cos.writeHeader(primaryPrincipal, version);
}
load(name);
}
synchronized void load(String name) throws IOException, KrbException {
PrincipalName p;
try (FileInputStream fis = new FileInputStream(name);
CCacheInputStream cis = new CCacheInputStream(fis)) {
version = cis.readVersion();
if (version == KRB5_FCC_FVNO_4) {
tag = cis.readTag();
} else {
tag = null;
if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) {
cis.setNativeByteOrder();
}
}
p = cis.readPrincipal(version);
if (primaryPrincipal != null) {
if (!(primaryPrincipal.match(p))) {
throw new IOException("Primary principals don't match.");
}
} else
primaryPrincipal = p;
credentialsList = new Vector<Credentials>();
while (cis.available() > 0) {
Object cred = cis.readCred(version);
if (cred != null) {
if (cred instanceof Credentials) {
credentialsList.addElement((Credentials)cred);
} else {
addConfigEntry((CredentialsCache.ConfigEntry)cred);
}
}
}
}
}
/**
* Updates the credentials list. If the specified credentials for the
* service is new, add it to the list. If there is an entry in the list,
* replace the old credentials with the new one.
* @param c the credentials.
*/
public synchronized void update(Credentials c) {
if (credentialsList != null) {
if (credentialsList.isEmpty()) {
credentialsList.addElement(c);
} else {
Credentials tmp = null;
boolean matched = false;
for (int i = 0; i < credentialsList.size(); i++) {
tmp = credentialsList.elementAt(i);
if (match(c.sname.getNameStrings(),
tmp.sname.getNameStrings()) &&
((c.sname.getRealmString()).equalsIgnoreCase(
tmp.sname.getRealmString()))) {
matched = true;
if (c.endtime.getTime() >= tmp.endtime.getTime()) {
if (DEBUG) {
System.out.println(" >>> FileCredentialsCache "
+ "Ticket matched, overwrite "
+ "the old one.");
}
credentialsList.removeElementAt(i);
credentialsList.addElement(c);
}
}
}
if (matched == false) {
if (DEBUG) {
System.out.println(" >>> FileCredentialsCache Ticket "
+ "not exactly matched, "
+ "add new one into cache.");
}
credentialsList.addElement(c);
}
}
}
}
public synchronized PrincipalName getPrimaryPrincipal() {
return primaryPrincipal;
}
/**
* Saves the credentials cache file to the disk.
*/
public synchronized void save() throws IOException, Asn1Exception {
try (FileOutputStream fos = new FileOutputStream(cacheName);
CCacheOutputStream cos = new CCacheOutputStream(fos)) {
cos.writeHeader(primaryPrincipal, version);
Credentials[] tmp = null;
if ((tmp = getCredsList()) != null) {
for (int i = 0; i < tmp.length; i++) {
cos.addCreds(tmp[i]);
}
}
for (ConfigEntry e : getConfigEntries()) {
cos.addConfigEntry(primaryPrincipal, e);
}
}
}
boolean match(String[] s1, String[] s2) {
if (s1.length != s2.length) {
return false;
} else {
for (int i = 0; i < s1.length; i++) {
if (!(s1[i].equalsIgnoreCase(s2[i]))) {
return false;
}
}
}
return true;
}
/**
* Returns the list of credentials entries in the cache file.
*/
public synchronized Credentials[] getCredsList() {
if ((credentialsList == null) || (credentialsList.isEmpty())) {
return null;
} else {
Credentials[] tmp = new Credentials[credentialsList.size()];
for (int i = 0; i < credentialsList.size(); i++) {
tmp[i] = credentialsList.elementAt(i);
}
return tmp;
}
}
public Credentials getCreds(LoginOptions options, PrincipalName sname) {
if (options == null) {
return getCreds(sname);
} else {
Credentials[] list = getCredsList();
if (list == null) {
return null;
} else {
for (int i = 0; i < list.length; i++) {
if (sname.match(list[i].sname)) {
if (list[i].flags.match(options)) {
return list[i];
}
}
}
}
return null;
}
}
private List<ConfigEntry> configEntries = new ArrayList<>();
@Override
public void addConfigEntry(ConfigEntry e) {
configEntries.add(e);
}
@Override
public List<ConfigEntry> getConfigEntries() {
return Collections.unmodifiableList(configEntries);
}
/**
* Gets a credentials for a specified service.
* @param sname service principal name.
*/
public Credentials getCreds(PrincipalName sname) {
Credentials[] list = getCredsList();
if (list == null) {
return null;
} else {
for (int i = 0; i < list.length; i++) {
if (sname.match(list[i].sname)) {
return list[i];
}
}
}
return null;
}
public sun.security.krb5.Credentials getInitialCreds() {
Credentials defaultCreds = getDefaultCreds();
if (defaultCreds == null) {
return null;
}
sun.security.krb5.Credentials tgt = defaultCreds.setKrbCreds();
CredentialsCache.ConfigEntry entry = getConfigEntry("proxy_impersonator");
if (entry == null) {
if (DEBUG) {
System.out.println("get normal credential");
}
return tgt;
}
boolean force;
String prop = SecurityProperties.privilegedGetOverridable(
"jdk.security.krb5.default.initiate.credential");
if (prop == null) {
prop = "always-impersonate";
}
switch (prop) {
case "no-impersonate": // never try impersonation
if (DEBUG) {
System.out.println("get normal credential");
}
return tgt;
case "try-impersonate":
force = false;
break;
case "always-impersonate":
force = true;
break;
default:
throw new RuntimeException(
"Invalid jdk.security.krb5.default.initiate.credential");
}
try {
PrincipalName service = new PrincipalName(
new String(entry.getData(), StandardCharsets.UTF_8));
if (!tgt.getClient().equals(service)) {
if (DEBUG) {
System.out.println("proxy_impersonator does not match service name");
}
return force ? null : tgt;
}
PrincipalName client = getPrimaryPrincipal();
Credentials proxy = null;
for (Credentials c : getCredsList()) {
if (c.getClientPrincipal().equals(client)
&& c.getServicePrincipal().equals(service)) {
proxy = c;
break;
}
}
if (proxy == null) {
if (DEBUG) {
System.out.println("Cannot find evidence ticket in ccache");
}
return force ? null : tgt;
}
if (DEBUG) {
System.out.println("Get proxied credential");
}
return tgt.setProxy(proxy.setKrbCreds());
} catch (KrbException e) {
if (DEBUG) {
System.out.println("Impersonation with ccache failed");
}
return force ? null : tgt;
}
}
public Credentials getDefaultCreds() {
Credentials[] list = getCredsList();
if (list == null) {
return null;
} else {
for (int i = list.length-1; i >= 0; i--) {
if (list[i].sname.toString().startsWith("krbtgt")) {
String[] nameStrings = list[i].sname.getNameStrings();
// find the TGT for the current realm krbtgt/realm@realm
if (nameStrings[1].equals(list[i].sname.getRealm().toString())) {
return list[i];
}
}
}
}
return null;
}
/*
* Returns path name of the credentials cache file.
* The path name is searched in the following order:
*
* 1. KRB5CCNAME (bare file name without FILE:)
* 2. /tmp/krb5cc_<uid> on unix systems
* 3. <user.home>/krb5cc_<user.name>
* 4. <user.home>/krb5cc (if can't get <user.name>)
*/
public static String getDefaultCacheName() {
String stdCacheNameComponent = "krb5cc";
String name;
// The env var can start with TYPE:, we only support FILE: here.
// https://docs.oracle.com/cd/E19082-01/819-2252/6n4i8rtr3/index.html
name = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<String>() {
@Override
public String run() {
String cache = System.getenv("KRB5CCNAME");
if (cache != null &&
(cache.length() >= 5) &&
cache.regionMatches(true, 0, "FILE:", 0, 5)) {
cache = cache.substring(5);
}
return cache;
}
});
if (name != null) {
if (DEBUG) {
System.out.println(">>>KinitOptions cache name is " + name);
}
return name;
}
// get cache name from system.property
String osname =
java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("os.name"));
/*
* For Unix platforms we use the default cache name to be
* /tmp/krbcc_uid ; for all other platforms we use
* {user_home}/krb5_cc{user_name}
* Please note that for Windows 2K we will use LSA to get
* the TGT from the the default cache even before we come here;
* however when we create cache we will create a cache under
* {user_home}/krb5_cc{user_name} for non-Unix platforms including
* Windows 2K.
*/
if (osname != null) {
String cmd = null;
String uidStr = null;
long uid = 0;
if (!osname.startsWith("Windows")) {
try {
Class<?> c = Class.forName
("com.sun.security.auth.module.UnixSystem");
Constructor<?> constructor = c.getConstructor();
Object obj = constructor.newInstance();
Method method = c.getMethod("getUid");
uid = ((Long)method.invoke(obj)).longValue();
name = File.separator + "tmp" +
File.separator + stdCacheNameComponent + "_" + uid;
if (DEBUG) {
System.out.println(">>>KinitOptions cache name is " +
name);
}
return name;
} catch (Exception e) {
if (DEBUG) {
System.out.println("Exception in obtaining uid " +
"for Unix platforms " +
"Using user's home directory");
e.printStackTrace();
}
}
}
}
// we did not get the uid;
String user_name =
java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.name"));
String user_home =
java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.home"));
if (user_home == null) {
user_home =
java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.dir"));
}
if (user_name != null) {
name = user_home + File.separator +
stdCacheNameComponent + "_" + user_name;
} else {
name = user_home + File.separator + stdCacheNameComponent;
}
if (DEBUG) {
System.out.println(">>>KinitOptions cache name is " + name);
}
return name;
}
public static String checkValidation(String name) {
String fullname = null;
if (name == null) {
return null;
}
try {
// get full path name
fullname = (new File(name)).getCanonicalPath();
File fCheck = new File(fullname);
if (!(fCheck.exists())) {
// get absolute directory
File temp = new File(fCheck.getParent());
// test if the directory exists
if (!(temp.isDirectory()))
fullname = null;
temp = null;
}
fCheck = null;
} catch (IOException e) {
fullname = null; // invalid name
}
return fullname;
}
private static String exec(String c) {
StringTokenizer st = new StringTokenizer(c);
Vector<String> v = new Vector<>();
while (st.hasMoreTokens()) {
v.addElement(st.nextToken());
}
final String[] command = new String[v.size()];
v.copyInto(command);
try {
Process p =
java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<Process> () {
public Process run() {
try {
return (Runtime.getRuntime().exec(command));
} catch (java.io.IOException e) {
if (DEBUG) {
e.printStackTrace();
}
return null;
}
}
});
if (p == null) {
// exception occurred during executing the command
return null;
}
BufferedReader commandResult =
new BufferedReader
(new InputStreamReader(p.getInputStream(), "8859_1"));
String s1 = null;
if ((command.length == 1) &&
(command[0].equals("/usr/bin/env"))) {
while ((s1 = commandResult.readLine()) != null) {
if (s1.length() >= 11) {
if ((s1.substring(0, 11)).equalsIgnoreCase
("KRB5CCNAME=")) {
s1 = s1.substring(11);
break;
}
}
}
} else s1 = commandResult.readLine();
commandResult.close();
return s1;
} catch (Exception e) {
if (DEBUG) {
e.printStackTrace();
}
}
return null;
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import java.io.IOException;
import java.io.File;
//Windows supports the "API: cache" type, which is a shared memory cache. This is
//implemented by krbcc32.dll as part of the MIT Kerberos for Win32 distribution.
//MemoryCredentialsCache will provide future functions to access shared memeory cache on
//Windows platform. Native code implementation may be necessary.
/**
* This class extends CredentialsCache. It is used for accessing data in shared memory
* cache on Windows platforms.
*
* @author Yanni Zhang
*/
public abstract class MemoryCredentialsCache extends CredentialsCache {
private static CredentialsCache getCCacheInstance(PrincipalName p) {
return null;
}
private static CredentialsCache getCCacheInstance(PrincipalName p, File cacheFile) {
return null;
}
public abstract boolean exists(String cache);
public abstract void update(Credentials c);
public abstract void save() throws IOException, KrbException;
public abstract Credentials[] getCredsList();
public abstract Credentials getCreds(PrincipalName sname) ;
public abstract PrincipalName getPrimaryPrincipal();
}

View File

@@ -0,0 +1,73 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import java.io.ByteArrayOutputStream;
/**
* tag field introduced in KRB5_FCC_FVNO_4
*
* @author Yanni Zhang
*/
public class Tag{
int length;
int tag;
int tagLen;
Integer time_offset;
Integer usec_offset;
public Tag(int len, int new_tag, Integer new_time, Integer new_usec) {
tag = new_tag;
tagLen = 8;
time_offset = new_time;
usec_offset = new_usec;
length = 4 + tagLen;
}
public Tag(int new_tag) {
tag = new_tag;
tagLen = 0;
length = 4 + tagLen;
}
public byte[] toByteArray() {
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write(length);
os.write(tag);
os.write(tagLen);
if (time_offset != null) {
os.write(time_offset.intValue());
}
if (usec_offset != null) {
os.write(usec_offset.intValue());
}
return os.toByteArray();
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2004, 2005, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.internal.crypto.dk.AesDkCrypto;
import sun.security.krb5.KrbCryptoException;
import java.security.GeneralSecurityException;
/**
* Class with static methods for doing AES operations.
*
* @author Seema Malkani
*/
public class Aes128 {
private static final AesDkCrypto CRYPTO = new AesDkCrypto(128);
private Aes128() {
}
public static byte[] stringToKey(char[] password, String salt, byte[] params)
throws GeneralSecurityException {
return CRYPTO.stringToKey(password, salt, params);
}
// in bytes
public static int getChecksumLength() {
return CRYPTO.getChecksumLength();
}
public static byte[] calculateChecksum(byte[] baseKey, int usage,
byte[] input, int start, int len) throws GeneralSecurityException {
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
}
public static byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
plaintext, start, len);
}
/* Encrypt plaintext; do not add confounder, or checksum */
public static byte[] encryptRaw(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
}
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
}
/* Decrypt ciphertext; do not remove confounder, or check checksum */
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
}
};

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2004, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Checksum;
/*
* This class encapsulates the encryption type for AES128
*
* @author Seema Malkani
*/
public final class Aes128CtsHmacSha1EType extends EType {
public int eType() {
return EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96;
}
public int minimumPadSize() {
return 0;
}
public int confounderSize() {
return blockSize();
}
public int checksumType() {
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
}
public int checksumSize() {
return Aes128.getChecksumLength();
}
public int blockSize() {
return 16;
}
public int keyType() {
return Krb5.KEYTYPE_AES;
}
public int keySize() {
return 16; // bytes
}
public byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return encrypt(data, key, ivec, usage);
}
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
throws KrbCryptoException {
try {
return Aes128.encrypt(key, usage, ivec, data, 0, data.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return decrypt(cipher, key, ivec, usage);
}
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
throws KrbApErrException, KrbCryptoException {
try {
return Aes128.decrypt(key, usage, ivec, cipher, 0, cipher.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
// Override default, because our decrypted data does not return confounder
// Should eventually get rid of EType.decryptedData and
// EncryptedData.decryptedData altogether
public byte[] decryptedData(byte[] data) {
return data;
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2004, 2005, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.internal.crypto.dk.AesDkCrypto;
import sun.security.krb5.KrbCryptoException;
import java.security.GeneralSecurityException;
/**
* Class with static methods for doing AES operations.
*
* @author Seema Malkani
*/
public class Aes256 {
private static final AesDkCrypto CRYPTO = new AesDkCrypto(256);
private Aes256() {
}
public static byte[] stringToKey(char[] password, String salt, byte[] params)
throws GeneralSecurityException {
return CRYPTO.stringToKey(password, salt, params);
}
// in bytes
public static int getChecksumLength() {
return CRYPTO.getChecksumLength();
}
public static byte[] calculateChecksum(byte[] baseKey, int usage,
byte[] input, int start, int len) throws GeneralSecurityException {
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
}
public static byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
plaintext, start, len);
}
/* Encrypt plaintext; do not add confounder, padding, or checksum */
public static byte[] encryptRaw(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
}
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
}
/*
* Decrypt ciphertext; do not remove confounder, padding, or check
* checksum
*/
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
}
};

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2004, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Checksum;
/*
* This class encapsulates the encryption type for AES256
*
* @author Seema Malkani
*/
public final class Aes256CtsHmacSha1EType extends EType {
public int eType() {
return EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96;
}
public int minimumPadSize() {
return 0;
}
public int confounderSize() {
return blockSize();
}
public int checksumType() {
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
}
public int checksumSize() {
return Aes256.getChecksumLength();
}
public int blockSize() {
return 16;
}
public int keyType() {
return Krb5.KEYTYPE_AES;
}
public int keySize() {
return 32; // bytes
}
public byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return encrypt(data, key, ivec, usage);
}
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
throws KrbCryptoException {
try {
return Aes256.encrypt(key, usage, ivec, data, 0, data.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return decrypt(cipher, key, ivec, usage);
}
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
throws KrbApErrException, KrbCryptoException {
try {
return Aes256.decrypt(key, usage, ivec, cipher, 0, cipher.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
// Override default, because our decrypted data does not return confounder
// Should eventually get rid of EType.decryptedData and
// EncryptedData.decryptedData altogether
public byte[] decryptedData(byte[] data) {
return data;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2005, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.internal.crypto.dk.ArcFourCrypto;
import sun.security.krb5.KrbCryptoException;
import java.security.GeneralSecurityException;
/**
* Class with static methods for doing RC4-HMAC operations.
*
* @author Seema Malkani
*/
public class ArcFourHmac {
private static final ArcFourCrypto CRYPTO = new ArcFourCrypto(128);
private ArcFourHmac() {
}
public static byte[] stringToKey(char[] password)
throws GeneralSecurityException {
return CRYPTO.stringToKey(password);
}
// in bytes
public static int getChecksumLength() {
return CRYPTO.getChecksumLength();
}
public static byte[] calculateChecksum(byte[] baseKey, int usage,
byte[] input, int start, int len) throws GeneralSecurityException {
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
}
/* Encrypt Sequence Number */
public static byte[] encryptSeq(byte[] baseKey, int usage,
byte[] checksum, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encryptSeq(baseKey, usage, checksum, plaintext, start, len);
}
/* Decrypt Sequence Number */
public static byte[] decryptSeq(byte[] baseKey, int usage, byte[] checksum,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.decryptSeq(baseKey, usage, checksum, ciphertext, start, len);
}
public static byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
plaintext, start, len);
}
/* Encrypt plaintext; do not add confounder, or checksum */
public static byte[] encryptRaw(byte[] baseKey, int usage,
byte[] seqNum, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encryptRaw(baseKey, usage, seqNum, plaintext, start, len);
}
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
}
/* Decrypt ciphertext; do not remove confounder, or check checksum */
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len, byte[] seqNum)
throws GeneralSecurityException {
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len, seqNum);
}
};

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2005, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Checksum;
/*
* This class encapsulates the encryption type for RC4-HMAC
*
* @author Seema Malkani
*/
public final class ArcFourHmacEType extends EType {
public int eType() {
return EncryptedData.ETYPE_ARCFOUR_HMAC;
}
public int minimumPadSize() {
return 1;
}
public int confounderSize() {
return 8;
}
public int checksumType() {
return Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
}
public int checksumSize() {
return ArcFourHmac.getChecksumLength();
}
public int blockSize() {
return 1;
}
public int keyType() {
return Krb5.KEYTYPE_ARCFOUR_HMAC;
}
public int keySize() {
return 16; // bytes
}
public byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return encrypt(data, key, ivec, usage);
}
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
throws KrbCryptoException {
try {
return ArcFourHmac.encrypt(key, usage, ivec, data, 0, data.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return decrypt(cipher, key, ivec, usage);
}
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
throws KrbApErrException, KrbCryptoException {
try {
return ArcFourHmac.decrypt(key, usage, ivec, cipher, 0, cipher.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
// Override default, because our decrypted data does not return confounder
// Should eventually get rid of EType.decryptedData and
// EncryptedData.decryptedData altogether
public byte[] decryptedData(byte[] data) {
return data;
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (c) 2000, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
public abstract class CksumType {
private static boolean DEBUG = Krb5.DEBUG;
public static CksumType getInstance(int cksumTypeConst)
throws KdcErrException {
CksumType cksumType = null;
String cksumTypeName = null;
switch (cksumTypeConst) {
case Checksum.CKSUMTYPE_CRC32:
cksumType = new Crc32CksumType();
cksumTypeName = "sun.security.krb5.internal.crypto.Crc32CksumType";
break;
case Checksum.CKSUMTYPE_DES_MAC:
cksumType = new DesMacCksumType();
cksumTypeName = "sun.security.krb5.internal.crypto.DesMacCksumType";
break;
case Checksum.CKSUMTYPE_DES_MAC_K:
cksumType = new DesMacKCksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.DesMacKCksumType";
break;
case Checksum.CKSUMTYPE_RSA_MD5:
cksumType = new RsaMd5CksumType();
cksumTypeName = "sun.security.krb5.internal.crypto.RsaMd5CksumType";
break;
case Checksum.CKSUMTYPE_RSA_MD5_DES:
cksumType = new RsaMd5DesCksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.RsaMd5DesCksumType";
break;
case Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD:
cksumType = new HmacSha1Des3KdCksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha1Des3KdCksumType";
break;
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128:
cksumType = new HmacSha1Aes128CksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha1Aes128CksumType";
break;
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
cksumType = new HmacSha1Aes256CksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha1Aes256CksumType";
break;
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
cksumType = new HmacMd5ArcFourCksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacMd5ArcFourCksumType";
break;
// currently we don't support MD4.
case Checksum.CKSUMTYPE_RSA_MD4_DES_K:
// cksumType = new RsaMd4DesKCksumType();
// cksumTypeName =
// "sun.security.krb5.internal.crypto.RsaMd4DesKCksumType";
case Checksum.CKSUMTYPE_RSA_MD4:
// cksumType = new RsaMd4CksumType();
// linux box support rsamd4, how to solve conflict?
// cksumTypeName =
// "sun.security.krb5.internal.crypto.RsaMd4CksumType";
case Checksum.CKSUMTYPE_RSA_MD4_DES:
// cksumType = new RsaMd4DesCksumType();
// cksumTypeName =
// "sun.security.krb5.internal.crypto.RsaMd4DesCksumType";
default:
throw new KdcErrException(Krb5.KDC_ERR_SUMTYPE_NOSUPP);
}
if (DEBUG) {
System.out.println(">>> CksumType: " + cksumTypeName);
}
return cksumType;
}
public abstract int confounderSize();
public abstract int cksumType();
public abstract boolean isKeyed();
public abstract int cksumSize();
public abstract int keyType();
public abstract int keySize();
// Note: key and usage will be ignored for an unkeyed checksum.
public abstract byte[] calculateChecksum(byte[] data, int size,
byte[] key, int usage) throws KrbCryptoException;
// Note: key and usage will be ignored for an unkeyed checksum.
public abstract boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException;
public static boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
if (cksum1 == cksum2)
return true;
if ((cksum1 == null && cksum2 != null) ||
(cksum1 != null && cksum2 == null))
return false;
if (cksum1.length != cksum2.length)
return false;
for (int i = 0; i < cksum1.length; i++)
if (cksum1[i] != cksum2[i])
return false;
return true;
}
}

View File

@@ -0,0 +1,93 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
public class Crc32CksumType extends CksumType {
public Crc32CksumType() {
}
public int confounderSize() {
return 0;
}
public int cksumType() {
return Checksum.CKSUMTYPE_CRC32;
}
public boolean isKeyed() {
return false;
}
public int cksumSize() {
return 4;
}
public int keyType() {
return Krb5.KEYTYPE_NULL;
}
public int keySize() {
return 0;
}
public byte[] calculateChecksum(byte[] data, int size,
byte[] key, int usage) {
return crc32.byte2crc32sum_bytes(data, size);
}
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) {
return CksumType.isChecksumEqual(checksum,
crc32.byte2crc32sum_bytes(data));
}
public static byte[] int2quad(long input) {
byte[] output = new byte[4];
for (int i = 0; i < 4; i++) {
output[i] = (byte)((input >>> (i * 8)) & 0xff);
}
return output;
}
public static long bytes2long(byte[] input) {
long result = 0;
result |= (((long)input[0]) & 0xffL) << 24;
result |= (((long)input[1]) & 0xffL) << 16;
result |= (((long)input[2]) & 0xffL) << 8;
result |= (((long)input[3]) & 0xffL);
return result;
}
}

View File

@@ -0,0 +1,368 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import java.security.GeneralSecurityException;
import javax.crypto.spec.IvParameterSpec;
import sun.security.krb5.KrbCryptoException;
import java.util.Arrays;
import sun.security.action.GetPropertyAction;
public final class Des {
// RFC 3961 demands that UTF-8 encoding be used in DES's
// string-to-key function. For historical reasons, some
// implementations use a locale-specific encoding. Even
// so, when the client and server use different locales,
// they must agree on a common value, normally the one
// used when the password is set/reset.
//
// The following system property is provided to perform the
// string-to-key encoding. When set, the specified charset
// name is used. Otherwise, the system default charset.
private final static String CHARSET =
java.security.AccessController.doPrivileged(
new GetPropertyAction("sun.security.krb5.msinterop.des.s2kcharset"));
private static final long[] bad_keys = {
0x0101010101010101L, 0xfefefefefefefefeL,
0x1f1f1f1f1f1f1f1fL, 0xe0e0e0e0e0e0e0e0L,
0x01fe01fe01fe01feL, 0xfe01fe01fe01fe01L,
0x1fe01fe00ef10ef1L, 0xe01fe01ff10ef10eL,
0x01e001e001f101f1L, 0xe001e001f101f101L,
0x1ffe1ffe0efe0efeL, 0xfe1ffe1ffe0efe0eL,
0x011f011f010e010eL, 0x1f011f010e010e01L,
0xe0fee0fef1fef1feL, 0xfee0fee0fef1fef1L
};
private static final byte[] good_parity = {
1, 1, 2, 2, 4, 4, 7, 7,
8, 8, 11, 11, 13, 13, 14, 14,
16, 16, 19, 19, 21, 21, 22, 22,
25, 25, 26, 26, 28, 28, 31, 31,
32, 32, 35, 35, 37, 37, 38, 38,
41, 41, 42, 42, 44, 44, 47, 47,
49, 49, 50, 50, 52, 52, 55, 55,
56, 56, 59, 59, 61, 61, 62, 62,
64, 64, 67, 67, 69, 69, 70, 70,
73, 73, 74, 74, 76, 76, 79, 79,
81, 81, 82, 82, 84, 84, 87, 87,
88, 88, 91, 91, 93, 93, 94, 94,
97, 97, 98, 98, 100, 100, 103, 103,
104, 104, 107, 107, 109, 109, 110, 110,
112, 112, 115, 115, 117, 117, 118, 118,
121, 121, 122, 122, 124, 124, 127, 127,
(byte)128, (byte)128, (byte)131, (byte)131,
(byte)133, (byte)133, (byte)134, (byte)134,
(byte)137, (byte)137, (byte)138, (byte)138,
(byte)140, (byte)140, (byte)143, (byte)143,
(byte)145, (byte)145, (byte)146, (byte)146,
(byte)148, (byte)148, (byte)151, (byte)151,
(byte)152, (byte)152, (byte)155, (byte)155,
(byte)157, (byte)157, (byte)158, (byte)158,
(byte)161, (byte)161, (byte)162, (byte)162,
(byte)164, (byte)164, (byte)167, (byte)167,
(byte)168, (byte)168, (byte)171, (byte)171,
(byte)173, (byte)173, (byte)174, (byte)174,
(byte)176, (byte)176, (byte)179, (byte)179,
(byte)181, (byte)181, (byte)182, (byte)182,
(byte)185, (byte)185, (byte)186, (byte)186,
(byte)188, (byte)188, (byte)191, (byte)191,
(byte)193, (byte)193, (byte)194, (byte)194,
(byte)196, (byte)196, (byte)199, (byte)199,
(byte)200, (byte)200, (byte)203, (byte)203,
(byte)205, (byte)205, (byte)206, (byte)206,
(byte)208, (byte)208, (byte)211, (byte)211,
(byte)213, (byte)213, (byte)214, (byte)214,
(byte)217, (byte)217, (byte)218, (byte)218,
(byte)220, (byte)220, (byte)223, (byte)223,
(byte)224, (byte)224, (byte)227, (byte)227,
(byte)229, (byte)229, (byte)230, (byte)230,
(byte)233, (byte)233, (byte)234, (byte)234,
(byte)236, (byte)236, (byte)239, (byte)239,
(byte)241, (byte)241, (byte)242, (byte)242,
(byte)244, (byte)244, (byte)247, (byte)247,
(byte)248, (byte)248, (byte)251, (byte)251,
(byte)253, (byte)253, (byte)254, (byte)254
};
public static final byte[] set_parity(byte[] key) {
for (int i=0; i < 8; i++) {
key[i] = good_parity[key[i] & 0xff];
}
return key;
}
public static final long set_parity(long key) {
return octet2long(set_parity(long2octet(key)));
}
public static final boolean bad_key(long key) {
for (int i = 0; i < bad_keys.length; i++) {
if (bad_keys[i] == key) {
return true;
}
}
return false;
}
public static final boolean bad_key(byte[] key) {
return bad_key(octet2long(key));
}
public static long octet2long(byte[] input) {
return octet2long(input, 0);
}
public static long octet2long(byte[] input, int offset) { //convert a 8-byte to a long
long result = 0;
for (int i = 0; i < 8; i++) {
if (i + offset < input.length) {
result |= (((long)input[i + offset]) & 0xffL) << ((7 - i) * 8);
}
}
return result;
}
public static byte[] long2octet(long input) {
byte[] output = new byte[8];
for (int i = 0; i < 8; i++) {
output[i] = (byte)((input >>> ((7 - i) * 8)) & 0xffL);
}
return output;
}
public static void long2octet(long input, byte[] output) {
long2octet(input, output, 0);
}
public static void long2octet(long input, byte[] output, int offset) {
for (int i = 0; i < 8; i++) {
if (i + offset < output.length) {
output[i + offset] =
(byte)((input >>> ((7 - i) * 8)) & 0xffL);
}
}
}
/**
* Creates a DES cipher in Electronic Codebook mode, with no padding.
* @param input plain text.
* @param output the buffer for the result.
* @param key DES the key to encrypt the text.
* @param ivec initialization vector.
*
* @created by Yanni Zhang, Dec 6 99.
*/
public static void cbc_encrypt (
byte[] input,
byte[] output,
byte[] key,
byte[] ivec,
boolean encrypt) throws KrbCryptoException {
Cipher cipher = null;
try {
cipher = Cipher.getInstance("DES/CBC/NoPadding");
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException("JCE provider may not be installed. "
+ e.getMessage());
ke.initCause(e);
throw ke;
}
IvParameterSpec params = new IvParameterSpec(ivec);
SecretKeySpec skSpec = new SecretKeySpec(key, "DES");
try {
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
// SecretKey sk = skf.generateSecret(skSpec);
SecretKey sk = (SecretKey) skSpec;
if (encrypt)
cipher.init(Cipher.ENCRYPT_MODE, sk, params);
else
cipher.init(Cipher.DECRYPT_MODE, sk, params);
byte[] result;
result = cipher.doFinal(input);
System.arraycopy(result, 0, output, 0, result.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
/**
* Generates DES key from the password.
* @param passwdChars a char[] used to create the key.
* @return DES key.
*
* @modified by Yanni Zhang, Dec 6, 99
*/
public static long char_to_key(char[] passwdChars) throws KrbCryptoException {
long key = 0;
long octet, octet1, octet2 = 0;
byte[] cbytes = null;
// Convert password to byte array
try {
if (CHARSET == null) {
cbytes = (new String(passwdChars)).getBytes();
} else {
cbytes = (new String(passwdChars)).getBytes(CHARSET);
}
} catch (Exception e) {
// clear-up sensitive information
if (cbytes != null) {
Arrays.fill(cbytes, 0, cbytes.length, (byte) 0);
}
KrbCryptoException ce =
new KrbCryptoException("Unable to convert passwd, " + e);
ce.initCause(e);
throw ce;
}
// pad data
byte[] passwdBytes = pad(cbytes);
byte[] newkey = new byte[8];
int length = (passwdBytes.length / 8) + (passwdBytes.length % 8 == 0 ? 0 : 1);
for (int i = 0; i < length; i++) {
octet = octet2long(passwdBytes, i * 8) & 0x7f7f7f7f7f7f7f7fL;
if (i % 2 == 1) {
octet1 = 0;
for (int j = 0; j < 64; j++) {
octet1 |= ((octet & (1L << j)) >>> j) << (63 - j);
}
octet = octet1 >>> 1;
}
key ^= (octet << 1);
}
key = set_parity(key);
if (bad_key(key)) {
byte [] temp = long2octet(key);
temp[7] ^= 0xf0;
key = octet2long(temp);
}
newkey = des_cksum(long2octet(key), passwdBytes, long2octet(key));
key = octet2long(set_parity(newkey));
if (bad_key(key)) {
byte [] temp = long2octet(key);
temp[7] ^= 0xf0;
key = octet2long(temp);
}
// clear-up sensitive information
if (cbytes != null) {
Arrays.fill(cbytes, 0, cbytes.length, (byte) 0);
}
if (passwdBytes != null) {
Arrays.fill(passwdBytes, 0, passwdBytes.length, (byte) 0);
}
return key;
}
/**
* Encrypts the message blocks using DES CBC and output the
* final block of 8-byte ciphertext.
* @param ivec Initialization vector.
* @param msg Input message as an byte array.
* @param key DES key to encrypt the message.
* @return the last block of ciphertext.
*
* @created by Yanni Zhang, Dec 6, 99.
*/
public static byte[] des_cksum(byte[] ivec, byte[] msg, byte[] key) throws KrbCryptoException {
Cipher cipher = null;
byte[] result = new byte[8];
try{
cipher = Cipher.getInstance("DES/CBC/NoPadding");
} catch (Exception e) {
KrbCryptoException ke = new KrbCryptoException("JCE provider may not be installed. "
+ e.getMessage());
ke.initCause(e);
throw ke;
}
IvParameterSpec params = new IvParameterSpec(ivec);
SecretKeySpec skSpec = new SecretKeySpec(key, "DES");
try {
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
// SecretKey sk = skf.generateSecret(skSpec);
SecretKey sk = (SecretKey) skSpec;
cipher.init(Cipher.ENCRYPT_MODE, sk, params);
for (int i = 0; i < msg.length / 8; i++) {
result = cipher.doFinal(msg, i * 8, 8);
cipher.init(Cipher.ENCRYPT_MODE, sk, (new IvParameterSpec(result)));
}
}
catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
return result;
}
/**
* Pads the data so that its length is a multiple of 8 bytes.
* @param data the raw data.
* @return the data being padded.
*
* @created by Yanni Zhang, Dec 6 99. //Kerberos does not use PKCS5 padding.
*/
static byte[] pad(byte[] data) {
int len;
if (data.length < 8) len = data.length;
else len = data.length % 8;
if (len == 0) return data;
else {
byte[] padding = new byte[ 8 - len + data.length];
for (int i = padding.length - 1; i > data.length - 1; i--) {
padding[i] = 0;
}
System.arraycopy(data, 0, padding, 0, data.length);
return padding;
}
}
// Caller is responsible for clearing password
public static byte[] string_to_key_bytes(char[] passwdChars)
throws KrbCryptoException {
return long2octet(char_to_key(passwdChars));
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2004, 2007, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.internal.crypto.dk.Des3DkCrypto;
import sun.security.krb5.KrbCryptoException;
import java.security.GeneralSecurityException;
/**
* Class with static methods for doing Triple DES operations.
*/
public class Des3 {
private static final Des3DkCrypto CRYPTO = new Des3DkCrypto();
private Des3() {
}
public static byte[] stringToKey(char[] chars)
throws GeneralSecurityException {
return CRYPTO.stringToKey(chars);
}
public static byte[] parityFix(byte[] value)
throws GeneralSecurityException {
return CRYPTO.parityFix(value);
}
// in bytes
public static int getChecksumLength() {
return CRYPTO.getChecksumLength();
}
public static byte[] calculateChecksum(byte[] baseKey, int usage,
byte[] input, int start, int len) throws GeneralSecurityException {
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
}
public static byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
plaintext, start, len);
}
/* Encrypt plaintext; do not add confounder, padding, or checksum */
public static byte[] encryptRaw(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
}
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
}
/**
* Decrypt ciphertext; do not remove confounder, padding,
* or check checksum
*/
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
}
};

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2004, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.Checksum;
public final class Des3CbcHmacSha1KdEType extends EType {
public int eType() {
return EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD;
}
public int minimumPadSize() {
return 0;
}
public int confounderSize() {
return blockSize();
}
public int checksumType() {
return Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
}
public int checksumSize() {
return Des3.getChecksumLength();
}
public int blockSize() {
return 8;
}
public int keyType() {
return Krb5.KEYTYPE_DES3;
}
public int keySize() {
return 24; // bytes
}
public byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException {
byte[] ivec = new byte[blockSize()];
return encrypt(data, key, ivec, usage);
}
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
throws KrbCryptoException {
try {
return Des3.encrypt(key, usage, ivec, data, 0, data.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException{
byte[] ivec = new byte[blockSize()];
return decrypt(cipher, key, ivec, usage);
}
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
throws KrbApErrException, KrbCryptoException {
try {
return Des3.decrypt(key, usage, ivec, cipher, 0, cipher.length);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
// Override default, because our decrypted data does not return confounder
// Should eventually get rid of EType.decryptedData and
// EncryptedData.decryptedData altogether
public byte[] decryptedData(byte[] data) {
return data;
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
public class DesCbcCrcEType extends DesCbcEType {
public DesCbcCrcEType() {
}
public int eType() {
return EncryptedData.ETYPE_DES_CBC_CRC;
}
public int minimumPadSize() {
return 4;
}
public int confounderSize() {
return 8;
}
public int checksumType() {
return Checksum.CKSUMTYPE_RSA_MD5;
}
public int checksumSize() {
return 4;
}
/**
* Encrypts data using DES in CBC mode with CRC32.
* @param data the data to be encrypted.
* @param key the secret key to encrypt the data. It is also used as initialization vector during cipher block chaining.
* @return the buffer for cipher text.
*
* @written by Yanni Zhang, Dec 10, 1999
*/
public byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException {
return encrypt(data, key, key, usage);
}
/**
* Decrypts data with provided key using DES in CBC mode with CRC32.
* @param cipher the cipher text to be decrypted.
* @param key the secret key to decrypt the data.
*
* @written by Yanni Zhang, Dec 10, 1999
*/
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException{
return decrypt(cipher, key, key, usage);
}
protected byte[] calculateChecksum(byte[] data, int size) {
return crc32.byte2crc32sum_bytes(data, size);
}
}

View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 2000, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Confounder;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
abstract class DesCbcEType extends EType {
protected abstract byte[] calculateChecksum(byte[] data, int size)
throws KrbCryptoException;
public int blockSize() {
return 8;
}
public int keyType() {
return Krb5.KEYTYPE_DES;
}
public int keySize() {
return 8;
}
/**
* Encrypts the data using DES in CBC mode.
* @param data the buffer for plain text.
* @param key the key to encrypt the data.
* @return the buffer for encrypted data.
*
* @written by Yanni Zhang, Dec 6 99.
*/
public byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException {
byte[] ivec = new byte[keySize()];
return encrypt(data, key, ivec, usage);
}
/**
* Encrypts the data using DES in CBC mode.
* @param data the buffer for plain text.
* @param key the key to encrypt the data.
* @param ivec initialization vector.
* @return buffer for encrypted data.
*
* @modified by Yanni Zhang, Feb 24 00.
*/
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
int usage) throws KrbCryptoException {
/*
* To meet export control requirements, double check that the
* key being used is no longer than 64 bits.
*
* Note that from a protocol point of view, an
* algorithm that is not DES will be rejected before this
* point. Also, a DES key that is not 64 bits will be
* rejected by a good implementations of JCE.
*/
if (key.length > 8)
throw new KrbCryptoException("Invalid DES Key!");
int new_size = data.length + confounderSize() + checksumSize();
byte[] new_data;
byte pad;
/*Data padding: using Kerberos 5 GSS-API mechanism (1.2.2.3), Jun 1996.
*Before encryption, plain text data is padded to the next highest multiple of blocksize.
*by appending between 1 and 8 bytes, the value of each such byte being the total number
*of pad bytes. For example, if new_size = 10, blockSize is 8, we should pad 2 bytes,
*and the value of each byte is 2.
*If plaintext data is a multiple of blocksize, we pad a 8 bytes of 8.
*/
if (new_size % blockSize() == 0) {
new_data = new byte[new_size + blockSize()];
pad = (byte)8;
}
else {
new_data = new byte[new_size + blockSize() - new_size % blockSize()];
pad = (byte)(blockSize() - new_size % blockSize());
}
for (int i = new_size; i < new_data.length; i++) {
new_data[i] = pad;
}
byte[] conf = Confounder.bytes(confounderSize());
System.arraycopy(conf, 0, new_data, 0, confounderSize());
System.arraycopy(data, 0, new_data, startOfData(), data.length);
byte[] cksum = calculateChecksum(new_data, new_data.length);
System.arraycopy(cksum, 0, new_data, startOfChecksum(),
checksumSize());
byte[] cipher = new byte[new_data.length];
Des.cbc_encrypt(new_data, cipher, key, ivec, true);
return cipher;
}
/**
* Decrypts the data using DES in CBC mode.
* @param cipher the input buffer.
* @param key the key to decrypt the data.
*
* @written by Yanni Zhang, Dec 6 99.
*/
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException{
byte[] ivec = new byte[keySize()];
return decrypt(cipher, key, ivec, usage);
}
/**
* Decrypts the data using DES in CBC mode.
* @param cipher the input buffer.
* @param key the key to decrypt the data.
* @param ivec initialization vector.
*
* @modified by Yanni Zhang, Dec 6 99.
*/
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
throws KrbApErrException, KrbCryptoException {
/*
* To meet export control requirements, double check that the
* key being used is no longer than 64 bits.
*
* Note that from a protocol point of view, an
* algorithm that is not DES will be rejected before this
* point. Also, a DES key that is not 64 bits will be
* rejected by a good JCE provider.
*/
if (key.length > 8)
throw new KrbCryptoException("Invalid DES Key!");
byte[] data = new byte[cipher.length];
Des.cbc_encrypt(cipher, data, key, ivec, false);
if (!isChecksumValid(data))
throw new KrbApErrException(Krb5.KRB_AP_ERR_BAD_INTEGRITY);
return data;
}
private void copyChecksumField(byte[] data, byte[] cksum) {
for (int i = 0; i < checksumSize(); i++)
data[startOfChecksum() + i] = cksum[i];
}
private byte[] checksumField(byte[] data) {
byte[] result = new byte[checksumSize()];
for (int i = 0; i < checksumSize(); i++)
result[i] = data[startOfChecksum() + i];
return result;
}
private void resetChecksumField(byte[] data) {
for (int i = startOfChecksum(); i < startOfChecksum() +
checksumSize(); i++)
data[i] = 0;
}
/*
// Not used.
public void setChecksum(byte[] data, int size) throws KrbCryptoException{
resetChecksumField(data);
byte[] cksum = calculateChecksum(data, size);
copyChecksumField(data, cksum);
}
*/
private byte[] generateChecksum(byte[] data) throws KrbCryptoException{
byte[] cksum1 = checksumField(data);
resetChecksumField(data);
byte[] cksum2 = calculateChecksum(data, data.length);
copyChecksumField(data, cksum1);
return cksum2;
}
private boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
if (cksum1 == cksum2)
return true;
if ((cksum1 == null && cksum2 != null) ||
(cksum1 != null && cksum2 == null))
return false;
if (cksum1.length != cksum2.length)
return false;
for (int i = 0; i < cksum1.length; i++)
if (cksum1[i] != cksum2[i])
return false;
return true;
}
protected boolean isChecksumValid(byte[] data) throws KrbCryptoException {
byte[] cksum1 = checksumField(data);
byte[] cksum2 = generateChecksum(data);
return isChecksumEqual(cksum1, cksum2);
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.internal.*;
import sun.security.krb5.Checksum;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.KrbCryptoException;
import java.security.MessageDigest;
import java.security.Provider;
import java.security.Security;
public final class DesCbcMd5EType extends DesCbcEType {
public DesCbcMd5EType() {
}
public int eType() {
return EncryptedData.ETYPE_DES_CBC_MD5;
}
public int minimumPadSize() {
return 0;
}
public int confounderSize() {
return 8;
}
public int checksumType() {
return Checksum.CKSUMTYPE_RSA_MD5;
}
public int checksumSize() {
return 16;
}
/**
* Calculates checksum using MD5.
* @param data the input data.
* @param size the length of data.
* @return the checksum.
*
* @modified by Yanni Zhang, 12/06/99.
*/
protected byte[] calculateChecksum(byte[] data, int size)
throws KrbCryptoException {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage());
}
try {
md5.update(data);
return(md5.digest());
} catch (Exception e) {
throw new KrbCryptoException(e.getMessage());
}
}
}

View File

@@ -0,0 +1,180 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.Confounder;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
public class DesMacCksumType extends CksumType {
public DesMacCksumType() {
}
public int confounderSize() {
return 8;
}
public int cksumType() {
return Checksum.CKSUMTYPE_DES_MAC;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 16;
}
public int keyType() {
return Krb5.KEYTYPE_DES;
}
public int keySize() {
return 8;
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
byte[] new_data = new byte[size + confounderSize()];
byte[] conf = Confounder.bytes(confounderSize());
System.arraycopy(conf, 0, new_data, 0, confounderSize());
System.arraycopy(data, 0, new_data, confounderSize(), size);
//check for weak keys
try {
if (DESKeySpec.isWeak(key, 0)) {
key[7] = (byte)(key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] residue_ivec = new byte[key.length];
byte[] residue = Des.des_cksum(residue_ivec, new_data, key);
byte[] cksum = new byte[cksumSize()];
System.arraycopy(conf, 0, cksum, 0, confounderSize());
System.arraycopy(residue, 0, cksum, confounderSize(),
cksumSize() - confounderSize());
byte[] new_key = new byte[keySize()];
System.arraycopy(key, 0, new_key, 0, key.length);
for (int i = 0; i < new_key.length; i++)
new_key[i] = (byte)(new_key[i] ^ 0xf0);
//check for weak keys
try {
if (DESKeySpec.isWeak(new_key, 0)) {
new_key[7] = (byte)(new_key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] ivec = new byte[new_key.length];
//des-cbc encrypt
byte[] enc_cksum = new byte[cksum.length];
Des.cbc_encrypt(cksum, enc_cksum, new_key, ivec, true);
return enc_cksum;
}
/**
* Verifies keyed checksum.
* @param data the data.
* @param size the length of data.
* @param key the key used to encrypt the checksum.
* @param checksum the checksum.
* @return true if verification is successful.
*
* @modified by Yanni Zhang, 12/08/99.
*/
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
byte[] cksum = decryptKeyedChecksum(checksum, key);
byte[] new_data = new byte[size + confounderSize()];
System.arraycopy(cksum, 0, new_data, 0, confounderSize());
System.arraycopy(data, 0, new_data, confounderSize(), size);
//check for weak keys
try {
if (DESKeySpec.isWeak(key, 0)) {
key[7] = (byte)(key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] ivec = new byte[key.length];
byte[] new_cksum = Des.des_cksum(ivec, new_data, key);
byte[] orig_cksum = new byte[cksumSize() - confounderSize()];
System.arraycopy(cksum, confounderSize(), orig_cksum, 0,
cksumSize() - confounderSize());
return isChecksumEqual(orig_cksum, new_cksum);
}
/**
* Decrypts keyed checksum.
* @param enc_cksum the buffer for encrypted checksum.
* @param key the key.
* @return the checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
private byte[] decryptKeyedChecksum(byte[] enc_cksum, byte[] key) throws KrbCryptoException {
byte[] new_key = new byte[keySize()];
System.arraycopy(key, 0, new_key, 0, key.length);
for (int i = 0; i < new_key.length; i++)
new_key[i] = (byte)(new_key[i] ^ 0xf0);
//check for weak keys
try {
if (DESKeySpec.isWeak(new_key, 0)) {
new_key[7] = (byte)(new_key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] ivec = new byte[new_key.length];
byte[] cksum = new byte[enc_cksum.length];
Des.cbc_encrypt(enc_cksum, cksum, new_key, ivec, false);
return cksum;
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
public class DesMacKCksumType extends CksumType {
public DesMacKCksumType() {
}
public int confounderSize() {
return 0;
}
public int cksumType() {
return Checksum.CKSUMTYPE_DES_MAC_K;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 16;
}
public int keyType() {
return Krb5.KEYTYPE_DES;
}
public int keySize() {
return 8;
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
//check for weak keys
try {
if (DESKeySpec.isWeak(key, 0)) {
key[7] = (byte)(key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] ivec = new byte[key.length];
System.arraycopy(key, 0, ivec, 0, key.length);
byte[] cksum = Des.des_cksum(ivec, data, key);
return cksum;
}
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
byte[] new_cksum = calculateChecksum(data, data.length, key, usage);
return isChecksumEqual(checksum, new_cksum);
}
}

View File

@@ -0,0 +1,370 @@
/*
* Copyright (c) 2000, 2021, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.internal.*;
import sun.security.krb5.Config;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.KrbException;
import sun.security.krb5.KrbCryptoException;
import javax.crypto.*;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
//only needed if dataSize() implementation changes back to spec;
//see dataSize() below
public abstract class EType {
private static final boolean DEBUG = Krb5.DEBUG;
private static boolean allowWeakCrypto;
static {
initStatic();
}
public static void initStatic() {
boolean allowed = false;
try {
Config cfg = Config.getInstance();
allowed = cfg.getBooleanObject("libdefaults", "allow_weak_crypto")
== Boolean.TRUE;
} catch (Exception exc) {
if (DEBUG) {
System.out.println ("Exception in getting allow_weak_crypto, " +
"using default value " +
exc.getMessage());
}
}
allowWeakCrypto = allowed;
}
public static EType getInstance (int eTypeConst)
throws KdcErrException {
EType eType = null;
String eTypeName = null;
switch (eTypeConst) {
case EncryptedData.ETYPE_NULL:
eType = new NullEType();
eTypeName = "sun.security.krb5.internal.crypto.NullEType";
break;
case EncryptedData.ETYPE_DES_CBC_CRC:
eType = new DesCbcCrcEType();
eTypeName = "sun.security.krb5.internal.crypto.DesCbcCrcEType";
break;
case EncryptedData.ETYPE_DES_CBC_MD5:
eType = new DesCbcMd5EType();
eTypeName = "sun.security.krb5.internal.crypto.DesCbcMd5EType";
break;
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
eType = new Des3CbcHmacSha1KdEType();
eTypeName =
"sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType";
break;
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
eType = new Aes128CtsHmacSha1EType();
eTypeName =
"sun.security.krb5.internal.crypto.Aes128CtsHmacSha1EType";
break;
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
eType = new Aes256CtsHmacSha1EType();
eTypeName =
"sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType";
break;
case EncryptedData.ETYPE_ARCFOUR_HMAC:
eType = new ArcFourHmacEType();
eTypeName = "sun.security.krb5.internal.crypto.ArcFourHmacEType";
break;
default:
String msg = "encryption type = " + toString(eTypeConst)
+ " (" + eTypeConst + ")";
throw new KdcErrException(Krb5.KDC_ERR_ETYPE_NOSUPP, msg);
}
if (DEBUG) {
System.out.println(">>> EType: " + eTypeName);
}
return eType;
}
public abstract int eType();
public abstract int minimumPadSize();
public abstract int confounderSize();
public abstract int checksumType();
public abstract int checksumSize();
public abstract int blockSize();
public abstract int keyType();
public abstract int keySize();
public abstract byte[] encrypt(byte[] data, byte[] key, int usage)
throws KrbCryptoException;
public abstract byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
int usage) throws KrbCryptoException;
public abstract byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException, KrbCryptoException;
public abstract byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec,
int usage) throws KrbApErrException, KrbCryptoException;
public int dataSize(byte[] data)
// throws Asn1Exception
{
// EncodeRef ref = new EncodeRef(data, startOfData());
// return ref.end - startOfData();
// should be the above according to spec, but in fact
// implementations include the pad bytes in the data size
return data.length - startOfData();
}
public int padSize(byte[] data) {
return data.length - confounderSize() - checksumSize() -
dataSize(data);
}
public int startOfChecksum() {
return confounderSize();
}
public int startOfData() {
return confounderSize() + checksumSize();
}
public int startOfPad(byte[] data) {
return confounderSize() + checksumSize() + dataSize(data);
}
public byte[] decryptedData(byte[] data) {
int tempSize = dataSize(data);
byte[] result = new byte[tempSize];
System.arraycopy(data, startOfData(), result, 0, tempSize);
return result;
}
// Note: the first 2 entries of BUILTIN_ETYPES and BUILTIN_ETYPES_NOAES256
// should be kept DES-related. They will be removed when allow_weak_crypto
// is set to false.
private static final int[] BUILTIN_ETYPES = new int[] {
EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
EncryptedData.ETYPE_ARCFOUR_HMAC,
EncryptedData.ETYPE_DES_CBC_CRC,
EncryptedData.ETYPE_DES_CBC_MD5,
};
private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
EncryptedData.ETYPE_ARCFOUR_HMAC,
EncryptedData.ETYPE_DES_CBC_CRC,
EncryptedData.ETYPE_DES_CBC_MD5,
};
// used in Config
public static int[] getBuiltInDefaults() {
int allowed = 0;
try {
allowed = Cipher.getMaxAllowedKeyLength("AES");
} catch (Exception e) {
// should not happen
}
int[] result;
if (allowed < 256) {
result = BUILTIN_ETYPES_NOAES256;
} else {
result = BUILTIN_ETYPES;
}
if (!allowWeakCrypto) {
// The last 4 etypes are now weak ones
return Arrays.copyOfRange(result, 0, result.length - 4);
}
return result;
}
/**
* Retrieves the default etypes from the configuration file, or
* if that's not available, return the built-in list of default etypes.
* This result is always non-empty. If no etypes are found,
* an exception is thrown.
*/
public static int[] getDefaults(String configName)
throws KrbException {
Config config = null;
try {
config = Config.getInstance();
} catch (KrbException exc) {
if (DEBUG) {
System.out.println("Exception while getting " +
configName + exc.getMessage());
System.out.println("Using default builtin etypes");
}
return getBuiltInDefaults();
}
return config.defaultEtype(configName);
}
/**
* Retrieve the default etypes from the configuration file for
* those etypes for which there are corresponding keys.
* Used in scenario we have some keys from a keytab with etypes
* different from those named in configName. Then, in order
* to decrypt an AS-REP, we should only ask for etypes for which
* we have keys.
*/
public static int[] getDefaults(String configName, EncryptionKey[] keys)
throws KrbException {
int[] answer = getDefaults(configName);
List<Integer> list = new ArrayList<>(answer.length);
for (int i = 0; i < answer.length; i++) {
if (EncryptionKey.findKey(answer[i], keys) != null) {
list.add(answer[i]);
}
}
int len = list.size();
if (len <= 0) {
StringBuffer keystr = new StringBuffer();
for (int i = 0; i < keys.length; i++) {
keystr.append(toString(keys[i].getEType()));
keystr.append(" ");
}
throw new KrbException(
"Do not have keys of types listed in " + configName +
" available; only have keys of following type: " +
keystr.toString());
} else {
answer = new int[len];
for (int i = 0; i < len; i++) {
answer[i] = list.get(i);
}
return answer;
}
}
public static boolean isSupported(int eTypeConst, int[] config) {
for (int i = 0; i < config.length; i++) {
if (eTypeConst == config[i]) {
return true;
}
}
return false;
}
public static boolean isSupported(int eTypeConst) {
int[] enabledETypes = getBuiltInDefaults();
return isSupported(eTypeConst, enabledETypes);
}
/**
* https://tools.ietf.org/html/rfc4120#section-3.1.3:
*
* A "newer" enctype is any enctype first officially
* specified concurrently with or subsequent to the issue of this RFC.
* The enctypes DES, 3DES, or RC4 and any defined in [RFC1510] are not
* "newer" enctypes.
*
* @param eTypeConst the encryption type
* @return true if "newer"
*/
public static boolean isNewer(int eTypeConst) {
return eTypeConst != EncryptedData.ETYPE_DES_CBC_CRC &&
eTypeConst != EncryptedData.ETYPE_DES_CBC_MD4 &&
eTypeConst != EncryptedData.ETYPE_DES_CBC_MD5 &&
eTypeConst != EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD &&
eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC &&
eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC_EXP;
}
public static String toString(int type) {
switch (type) {
case 0:
return "NULL";
case 1:
return "DES CBC mode with CRC-32";
case 2:
return "DES CBC mode with MD4";
case 3:
return "DES CBC mode with MD5";
case 4:
return "reserved";
case 5:
return "DES3 CBC mode with MD5";
case 6:
return "reserved";
case 7:
return "DES3 CBC mode with SHA1";
case 9:
return "DSA with SHA1- Cms0ID";
case 10:
return "MD5 with RSA encryption - Cms0ID";
case 11:
return "SHA1 with RSA encryption - Cms0ID";
case 12:
return "RC2 CBC mode with Env0ID";
case 13:
return "RSA encryption with Env0ID";
case 14:
return "RSAES-0AEP-ENV-0ID";
case 15:
return "DES-EDE3-CBC-ENV-0ID";
case 16:
return "DES3 CBC mode with SHA1-KD";
case 17:
return "AES128 CTS mode with HMAC SHA1-96";
case 18:
return "AES256 CTS mode with HMAC SHA1-96";
case 23:
return "RC4 with HMAC";
case 24:
return "RC4 with HMAC EXP";
}
return "Unknown (" + type + ")";
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2005, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
/**
* This class encapsulates the checksum type for HMAC RC4
*
* @author Seema Malkani
*/
public class HmacMd5ArcFourCksumType extends CksumType {
public HmacMd5ArcFourCksumType() {
}
public int confounderSize() {
return 8;
}
public int cksumType() {
return Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 16; // bytes
}
public int keyType() {
return Krb5.KEYTYPE_ARCFOUR_HMAC;
}
public int keySize() {
return 16; // bytes
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
try {
return ArcFourHmac.calculateChecksum(key, usage, data, 0, size);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
/**
* Verifies keyed checksum.
* @param data the data.
* @param size the length of data.
* @param key the key used to encrypt the checksum.
* @param checksum the checksum.
* @return true if verification is successful.
*/
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
try {
byte[] newCksum = ArcFourHmac.calculateChecksum(key, usage,
data, 0, size);
return isChecksumEqual(checksum, newCksum);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2004, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
/*
* This class encapsulates the checksum type for AES128
*
* @author Seema Malkani
*/
public class HmacSha1Aes128CksumType extends CksumType {
public HmacSha1Aes128CksumType() {
}
public int confounderSize() {
return 16;
}
public int cksumType() {
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 12; // bytes
}
public int keyType() {
return Krb5.KEYTYPE_AES;
}
public int keySize() {
return 16; // bytes
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
try {
return Aes128.calculateChecksum(key, usage, data, 0, size);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
/**
* Verifies keyed checksum.
* @param data the data.
* @param size the length of data.
* @param key the key used to encrypt the checksum.
* @param checksum the checksum.
* @return true if verification is successful.
*/
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
try {
byte[] newCksum = Aes128.calculateChecksum(key, usage,
data, 0, size);
return isChecksumEqual(checksum, newCksum);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2004, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
/*
* This class encapsulates the checksum type for AES256
*
* @author Seema Malkani
*/
public class HmacSha1Aes256CksumType extends CksumType {
public HmacSha1Aes256CksumType() {
}
public int confounderSize() {
return 16;
}
public int cksumType() {
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 12; // bytes
}
public int keyType() {
return Krb5.KEYTYPE_AES;
}
public int keySize() {
return 32; // bytes
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
try {
return Aes256.calculateChecksum(key, usage, data, 0, size);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
/**
* Verifies keyed checksum.
* @param data the data.
* @param size the length of data.
* @param key the key used to encrypt the checksum.
* @param checksum the checksum.
* @return true if verification is successful.
*/
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
try {
byte[] newCksum = Aes256.calculateChecksum(key, usage, data,
0, size);
return isChecksumEqual(checksum, newCksum);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2004, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.GeneralSecurityException;
public class HmacSha1Des3KdCksumType extends CksumType {
public HmacSha1Des3KdCksumType() {
}
public int confounderSize() {
return 8;
}
public int cksumType() {
return Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 20; // bytes
}
public int keyType() {
return Krb5.KEYTYPE_DES3;
}
public int keySize() {
return 24; // bytes
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
try {
return Des3.calculateChecksum(key, usage, data, 0, size);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
/**
* Verifies keyed checksum.
* @param data the data.
* @param size the length of data.
* @param key the key used to encrypt the checksum.
* @param checksum the checksum.
* @return true if verification is successful.
*/
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
try {
byte[] newCksum = Des3.calculateChecksum(key, usage,
data, 0, size);
return isChecksumEqual(checksum, newCksum);
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2004, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*/
package sun.security.krb5.internal.crypto;
/**
* Key usages used for key derivation in Kerberos.
*/
public class KeyUsage {
private KeyUsage() {
}
public static final int KU_UNKNOWN = 0; // Cannot be 0
// Defined in draft-yu-krb-wg-kerberos-extensions-00.txt, Appendix A
public static final int KU_PA_ENC_TS = 1; // KrbAsReq
public static final int KU_TICKET = 2; // KrbApReq (ticket)
public static final int KU_ENC_AS_REP_PART = 3; // KrbAsRep
public static final int KU_TGS_REQ_AUTH_DATA_SESSKEY= 4; // KrbTgsReq
public static final int KU_TGS_REQ_AUTH_DATA_SUBKEY = 5; // KrbTgsReq
public static final int KU_PA_TGS_REQ_CKSUM = 6; // KrbTgsReq
public static final int KU_PA_TGS_REQ_AUTHENTICATOR = 7; // KrbApReq
public static final int KU_ENC_TGS_REP_PART_SESSKEY = 8; // KrbTgsRep
public static final int KU_ENC_TGS_REP_PART_SUBKEY = 9; // KrbTgsRep
public static final int KU_AUTHENTICATOR_CKSUM = 10;
public static final int KU_AP_REQ_AUTHENTICATOR = 11; // KrbApReq
public static final int KU_ENC_AP_REP_PART = 12; // KrbApRep
public static final int KU_ENC_KRB_PRIV_PART = 13; // KrbPriv
public static final int KU_ENC_KRB_CRED_PART = 14; // KrbCred
public static final int KU_KRB_SAFE_CKSUM = 15; // KrbSafe
public static final int KU_PA_FOR_USER_ENC_CKSUM = 17; // S4U2user
public static final int KU_AD_KDC_ISSUED_CKSUM = 19;
public static final int KU_AS_REQ = 56;
public static final boolean isValid(int usage) {
return usage >= 0;
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2000, 2007, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
public class Nonce {
public static synchronized int value() {
return sun.security.krb5.Confounder.intValue() & 0x7fffffff;
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.internal.*;
public class NullEType extends EType {
public NullEType() {
}
public int eType() {
return EncryptedData.ETYPE_NULL;
}
public int minimumPadSize() {
return 0;
}
public int confounderSize() {
return 0;
}
public int checksumType() {
return Checksum.CKSUMTYPE_NULL;
}
public int checksumSize() {
return 0;
}
public int blockSize() {
return 1;
}
public int keyType() {
return Krb5.KEYTYPE_NULL;
}
public int keySize() {
return 0;
}
public byte[] encrypt(byte[] data, byte[] key, int usage) {
byte[] cipher = new byte[data.length];
System.arraycopy(data, 0, cipher, 0, data.length);
return cipher;
}
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage) {
byte[] cipher = new byte[data.length];
System.arraycopy(data, 0, cipher, 0, data.length);
return cipher;
}
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
throws KrbApErrException {
return cipher.clone();
}
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
throws KrbApErrException {
return cipher.clone();
}
}

View File

@@ -0,0 +1,104 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import java.security.MessageDigest;
public final class RsaMd5CksumType extends CksumType {
public RsaMd5CksumType() {
}
public int confounderSize() {
return 0;
}
public int cksumType() {
return Checksum.CKSUMTYPE_RSA_MD5;
}
public boolean isKeyed() {
return false;
}
public int cksumSize() {
return 16;
}
public int keyType() {
return Krb5.KEYTYPE_NULL;
}
public int keySize() {
return 0;
}
/**
* Calculates checksum using MD5.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @return the checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
public byte[] calculateChecksum(byte[] data, int size,
byte[] key, int usage) throws KrbCryptoException{
MessageDigest md5;
byte[] result = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage());
}
try {
md5.update(data);
result = md5.digest();
} catch (Exception e) {
throw new KrbCryptoException(e.getMessage());
}
return result;
}
@Override
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage)
throws KrbCryptoException {
try {
byte[] calculated = MessageDigest.getInstance("MD5").digest(data);
return CksumType.isChecksumEqual(calculated, checksum);
} catch (Exception e) {
return false;
}
}
}

View File

@@ -0,0 +1,196 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.crypto;
import sun.security.krb5.Checksum;
import sun.security.krb5.Confounder;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;
import javax.crypto.spec.DESKeySpec;
import java.security.MessageDigest;
import java.security.InvalidKeyException;
public final class RsaMd5DesCksumType extends CksumType {
public RsaMd5DesCksumType() {
}
public int confounderSize() {
return 8;
}
public int cksumType() {
return Checksum.CKSUMTYPE_RSA_MD5_DES;
}
public boolean isKeyed() {
return true;
}
public int cksumSize() {
return 24;
}
public int keyType() {
return Krb5.KEYTYPE_DES;
}
public int keySize() {
return 8;
}
/**
* Calculates keyed checksum.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @param key the key used to encrypt the checksum.
* @return keyed checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
int usage) throws KrbCryptoException {
//prepend confounder
byte[] new_data = new byte[size + confounderSize()];
byte[] conf = Confounder.bytes(confounderSize());
System.arraycopy(conf, 0, new_data, 0, confounderSize());
System.arraycopy(data, 0, new_data, confounderSize(), size);
//calculate md5 cksum
byte[] mdc_cksum = calculateRawChecksum(new_data, new_data.length);
byte[] cksum = new byte[cksumSize()];
System.arraycopy(conf, 0, cksum, 0, confounderSize());
System.arraycopy(mdc_cksum, 0, cksum, confounderSize(),
cksumSize() - confounderSize());
//compute modified key
byte[] new_key = new byte[keySize()];
System.arraycopy(key, 0, new_key, 0, key.length);
for (int i = 0; i < new_key.length; i++)
new_key[i] = (byte)(new_key[i] ^ 0xf0);
//check for weak keys
try {
if (DESKeySpec.isWeak(new_key, 0)) {
new_key[7] = (byte)(new_key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] ivec = new byte[new_key.length];
//des-cbc encrypt
byte[] enc_cksum = new byte[cksum.length];
Des.cbc_encrypt(cksum, enc_cksum, new_key, ivec, true);
return enc_cksum;
}
/**
* Verifies keyed checksum.
* @param data the data.
* @param size the length of data.
* @param key the key used to encrypt the checksum.
* @param checksum the checksum.
* @return true if verification is successful.
*
* @modified by Yanni Zhang, 12/08/99.
*/
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
//decrypt checksum
byte[] cksum = decryptKeyedChecksum(checksum, key);
//prepend confounder
byte[] new_data = new byte[size + confounderSize()];
System.arraycopy(cksum, 0, new_data, 0, confounderSize());
System.arraycopy(data, 0, new_data, confounderSize(), size);
byte[] new_cksum = calculateRawChecksum(new_data, new_data.length);
//extract original cksum value
byte[] orig_cksum = new byte[cksumSize() - confounderSize()];
System.arraycopy(cksum, confounderSize(), orig_cksum, 0,
cksumSize() - confounderSize());
return isChecksumEqual(orig_cksum, new_cksum);
}
/**
* Decrypts keyed checksum.
* @param enc_cksum the buffer for encrypted checksum.
* @param key the key.
* @return the checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
private byte[] decryptKeyedChecksum(byte[] enc_cksum, byte[] key) throws KrbCryptoException {
//compute modified key
byte[] new_key = new byte[keySize()];
System.arraycopy(key, 0, new_key, 0, key.length);
for (int i = 0; i < new_key.length; i++)
new_key[i] = (byte)(new_key[i] ^ 0xf0);
//check for weak keys
try {
if (DESKeySpec.isWeak(new_key, 0)) {
new_key[7] = (byte)(new_key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
byte[] ivec = new byte[new_key.length];
byte[] cksum = new byte[enc_cksum.length];
Des.cbc_encrypt(enc_cksum, cksum, new_key, ivec, false);
return cksum;
}
/**
* Calculates checksum using MD5.
* @param data the data used to generate the checksum.
* @param size length of the data.
* @return the checksum.
*
* @modified by Yanni Zhang, 12/08/99.
*/
private byte[] calculateRawChecksum(byte[] data, int size) throws KrbCryptoException{
MessageDigest md5;
byte[] result = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage());
}
try {
md5.update(data);
result = md5.digest();
} catch (Exception e) {
throw new KrbCryptoException(e.getMessage());
}
return result;
}
}

View File

@@ -0,0 +1,278 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
// crc32.java
package sun.security.krb5.internal.crypto;
import java.security.MessageDigestSpi;
import java.security.DigestException;
public final class crc32 extends MessageDigestSpi implements Cloneable {
private static final int CRC32_LENGTH = 4; //32-bit
private int seed;
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
// buffer;
// private int bufferIndex, bufferLeft;
public crc32() {
init();
}
public Object clone() {
try {
crc32 crc = (crc32)super.clone();
crc.init();
return crc;
}
catch (CloneNotSupportedException e) {
}
return null;
}
/**
* Return the digest length in bytes
*/
protected int engineGetDigestLength() {
return (CRC32_LENGTH);
}
/**
*/
protected byte[] engineDigest() {
byte[] result = new byte[CRC32_LENGTH];
result = int2quad(seed);
//processBuffer(buffer, 0, bufferIndex, result, 0);
init();
return result;
}
/**
*/
protected int engineDigest(byte[] buf, int offset, int len) throws DigestException {
byte[] result = new byte[CRC32_LENGTH];
result = int2quad(seed);
if (len < CRC32_LENGTH) {
throw new DigestException("partial digests not returned");
}
if (buf.length - offset < CRC32_LENGTH) {
throw new DigestException("insufficient space in the output " +
"buffer to store the digest");
}
System.arraycopy(result, 0, buf, offset, CRC32_LENGTH);
//processBuffer(buffer, 0, bufferIndex, result, 0);
/*if (len < CRC32_LENGTH) {
throw new DigestException("partial digests not returned");
}
if (buf.length - offset < CRC32_LENGTH) {
throw new DigestException("insufficient space in the output " +
"buffer to store the digest");
}
System.arraycopy(result, 0, buf, offset, CRC32_LENGTH); */
init();
return CRC32_LENGTH;
}
/**
* Update adds the passed byte to the digested data.
*/
protected synchronized void engineUpdate(byte b) {
byte[] input = new byte[1];
input[0] = b;
//engineUpdate(input, 0, 1);
engineUpdate(input, seed, 1);
}
/**
* Update adds the selected part of an array of bytes to the digest.
* This version is more efficient than the byte-at-a-time version;
* it avoids data copies and reduces per-byte call overhead.
*/
protected synchronized void engineUpdate(byte input[], int offset,
int len) {
processData(input, offset, len);
}
private static int[] crc32Table = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
protected void engineReset() {
init();
}
/**
* Initialize the CRC32 information
*/
public void init() {
seed = 0;
}
private void processData(byte[] data, int off, int len) {
int result = seed;
for (int i = 0; i < len; i++)
result = (result >>> 8) ^ crc32Table[(result ^ data[i]) & 0xff];
seed = result;
}
public static int int2crc32(int b) {
int crc = b;
for (int i = 8; i > 0; i--) {
if ((crc & 1) != 0)
crc = (crc >>> 1) ^ 0xedb88320;
else
crc = crc >>> 1;
}
return crc;
}
public static void printcrc32Table() {
String temp;
String zerofill = "00000000";
System.out.print("\tpublic static int[] crc32Table = {");
for (int i = 0; i < 256; i++) {
if ((i % 4) == 0)
System.out.print("\n\t\t");
temp = Integer.toHexString(int2crc32(i));
System.out.print("0x" +
zerofill.substring(temp.length()) + temp);
if (i != 255)
System.out.print(", ");
}
System.out.println("\n\t};");
}
public static int byte2crc32sum(int seed, byte[] data, int size) {
int crc = seed;
for (int i = 0; i < size; i++)
crc = (crc >>> 8) ^ crc32Table[(crc ^ data[i]) & 0xff];
return crc;
}
public static int byte2crc32sum(int seed, byte[] data) {
return byte2crc32sum(seed, data, data.length);
}
//sum from zero, i.e., no pre- or post-conditioning
public static int byte2crc32sum(byte[] data) {
return byte2crc32sum(0, data);
}
//CCITT ITU-T 3309 CRC-32 w/ standard pre- and post-conditioning
public static int byte2crc32(byte[] data) {
return ~byte2crc32sum(0xffffffff, data);
}
public static byte[] byte2crc32sum_bytes(byte[] data) {
int temp = byte2crc32sum(data);
return int2quad(temp);
}
public static byte[] byte2crc32sum_bytes(byte[] data, int size) {
int temp = byte2crc32sum(0, data, size);
if (DEBUG) {
System.out.println(">>>crc32: " + Integer.toHexString(temp));
System.out.println(">>>crc32: " + Integer.toBinaryString(temp));
}
return int2quad(temp);
}
public static byte[] int2quad(long input) {
byte[] output = new byte[4];
for (int i = 0; i < 4; i++) {
output[i] = (byte)((input >>> (i * 8)) & 0xff);
}
return output;
}
}

View File

@@ -0,0 +1,501 @@
/*
* Copyright (c) 2004, 2008, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*/
package sun.security.krb5.internal.crypto.dk;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import java.security.spec.KeySpec;
import java.security.GeneralSecurityException;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.Confounder;
import sun.security.krb5.internal.crypto.KeyUsage;
import java.util.Arrays;
/**
* This class provides the implementation of AES Encryption for Kerberos
* as defined RFC 3962.
* http://www.ietf.org/rfc/rfc3962.txt
*
* Algorithm profile described in [KCRYPTO]:
* +--------------------------------------------------------------------+
* | protocol key format 128- or 256-bit string |
* | |
* | string-to-key function PBKDF2+DK with variable |
* | iteration count (see |
* | above) |
* | |
* | default string-to-key parameters 00 00 10 00 |
* | |
* | key-generation seed length key size |
* | |
* | random-to-key function identity function |
* | |
* | hash function, H SHA-1 |
* | |
* | HMAC output size, h 12 octets (96 bits) |
* | |
* | message block size, m 1 octet |
* | |
* | encryption/decryption functions, AES in CBC-CTS mode |
* | E and D (cipher block size 16 |
* | octets), with next to |
* | last block as CBC-style |
* | ivec |
* +--------------------------------------------------------------------+
*
* Supports AES128 and AES256
*
* @author Seema Malkani
*/
public class AesDkCrypto extends DkCrypto {
private static final boolean debug = false;
private static final int BLOCK_SIZE = 16;
private static final int DEFAULT_ITERATION_COUNT = 4096;
private static final byte[] ZERO_IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
private static final int hashSize = 96/8;
private final int keyLength;
public AesDkCrypto(int length) {
keyLength = length;
}
protected int getKeySeedLength() {
return keyLength; // bits; AES key material
}
public byte[] stringToKey(char[] password, String salt, byte[] s2kparams)
throws GeneralSecurityException {
byte[] saltUtf8 = null;
try {
saltUtf8 = salt.getBytes("UTF-8");
return stringToKey(password, saltUtf8, s2kparams);
} catch (Exception e) {
return null;
} finally {
if (saltUtf8 != null) {
Arrays.fill(saltUtf8, (byte)0);
}
}
}
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
throws GeneralSecurityException {
int iter_count = DEFAULT_ITERATION_COUNT;
if (params != null) {
if (params.length != 4) {
throw new RuntimeException("Invalid parameter to stringToKey");
}
iter_count = readBigEndian(params, 0, 4);
}
byte[] tmpKey = randomToKey(PBKDF2(secret, salt, iter_count,
getKeySeedLength()));
byte[] result = dk(tmpKey, KERBEROS_CONSTANT);
return result;
}
protected byte[] randomToKey(byte[] in) {
// simple identity operation
return in;
}
protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
throws GeneralSecurityException {
// IV
if (ivec == null) {
ivec = ZERO_IV;
}
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
cipher.init(mode, secretKey, encIv);
return cipher;
}
// get an instance of the AES Cipher in CTS mode
public int getChecksumLength() {
return hashSize; // bytes
}
/**
* Get the truncated HMAC
*/
protected byte[] getHmac(byte[] key, byte[] msg)
throws GeneralSecurityException {
SecretKey keyKi = new SecretKeySpec(key, "HMAC");
Mac m = Mac.getInstance("HmacSHA1");
m.init(keyKi);
// generate hash
byte[] hash = m.doFinal(msg);
// truncate hash
byte[] output = new byte[hashSize];
System.arraycopy(hash, 0, output, 0, hashSize);
return output;
}
/**
* Calculate the checksum
*/
public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
int start, int len) throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
// Derive keys
byte[] constant = new byte[5];
constant[0] = (byte) ((usage>>24)&0xff);
constant[1] = (byte) ((usage>>16)&0xff);
constant[2] = (byte) ((usage>>8)&0xff);
constant[3] = (byte) (usage&0xff);
constant[4] = (byte) 0x99;
byte[] Kc = dk(baseKey, constant); // Checksum key
if (debug) {
System.err.println("usage: " + usage);
traceOutput("input", input, start, Math.min(len, 32));
traceOutput("constant", constant, 0, constant.length);
traceOutput("baseKey", baseKey, 0, baseKey.length);
traceOutput("Kc", Kc, 0, Kc.length);
}
try {
// Generate checksum
// H1 = HMAC(Kc, input)
byte[] hmac = getHmac(Kc, input);
if (debug) {
traceOutput("hmac", hmac, 0, hmac.length);
}
if (hmac.length == getChecksumLength()) {
return hmac;
} else if (hmac.length > getChecksumLength()) {
byte[] buf = new byte[getChecksumLength()];
System.arraycopy(hmac, 0, buf, 0, buf.length);
return buf;
} else {
throw new GeneralSecurityException("checksum size too short: " +
hmac.length + "; expecting : " + getChecksumLength());
}
} finally {
Arrays.fill(Kc, 0, Kc.length, (byte)0);
}
}
/**
* Performs encryption using derived key; adds confounder.
*/
public byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] output = encryptCTS(baseKey, usage, ivec, new_ivec, plaintext,
start, len, true);
return output;
}
/**
* Performs encryption using derived key; does not add confounder.
*/
public byte[] encryptRaw(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] output = encryptCTS(baseKey, usage, ivec, null, plaintext,
start, len, false);
return output;
}
/**
* @param baseKey key from which keys are to be derived using usage
* @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
*/
public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len) throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] output = decryptCTS(baseKey, usage, ivec, ciphertext,
start, len, true);
return output;
}
/**
* Decrypts data using specified key and initial vector.
* @param baseKey encryption key to use
* @param ciphertext encrypted data to be decrypted
* @param usage ignored
*/
public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] output = decryptCTS(baseKey, usage, ivec, ciphertext,
start, len, false);
return output;
}
/**
* Encrypt AES in CBC-CTS mode using derived keys.
*/
private byte[] encryptCTS(byte[] baseKey, int usage, byte[] ivec,
byte[] new_ivec, byte[] plaintext, int start, int len,
boolean confounder_exists)
throws GeneralSecurityException, KrbCryptoException {
byte[] Ke = null;
byte[] Ki = null;
if (debug) {
System.err.println("usage: " + usage);
if (ivec != null) {
traceOutput("old_state.ivec", ivec, 0, ivec.length);
}
traceOutput("plaintext", plaintext, start, Math.min(len, 32));
traceOutput("baseKey", baseKey, 0, baseKey.length);
}
try {
// derive Encryption key
byte[] constant = new byte[5];
constant[0] = (byte) ((usage>>24)&0xff);
constant[1] = (byte) ((usage>>16)&0xff);
constant[2] = (byte) ((usage>>8)&0xff);
constant[3] = (byte) (usage&0xff);
constant[4] = (byte) 0xaa;
Ke = dk(baseKey, constant); // Encryption key
byte[] toBeEncrypted = null;
if (confounder_exists) {
byte[] confounder = Confounder.bytes(BLOCK_SIZE);
toBeEncrypted = new byte[confounder.length + len];
System.arraycopy(confounder, 0, toBeEncrypted,
0, confounder.length);
System.arraycopy(plaintext, start, toBeEncrypted,
confounder.length, len);
} else {
toBeEncrypted = new byte[len];
System.arraycopy(plaintext, start, toBeEncrypted, 0, len);
}
// encryptedData + HMAC
byte[] output = new byte[toBeEncrypted.length + hashSize];
// AES in JCE
Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, encIv);
cipher.doFinal(toBeEncrypted, 0, toBeEncrypted.length, output);
// Derive integrity key
constant[4] = (byte) 0x55;
Ki = dk(baseKey, constant);
if (debug) {
traceOutput("constant", constant, 0, constant.length);
traceOutput("Ki", Ki, 0, Ke.length);
}
// Generate checksum
// H1 = HMAC(Ki, conf | plaintext | pad)
byte[] hmac = getHmac(Ki, toBeEncrypted);
// encryptedData + HMAC
System.arraycopy(hmac, 0, output, toBeEncrypted.length,
hmac.length);
return output;
} finally {
if (Ke != null) {
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
}
if (Ki != null) {
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
}
}
}
/**
* Decrypt AES in CBC-CTS mode using derived keys.
*/
private byte[] decryptCTS(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len, boolean confounder_exists)
throws GeneralSecurityException {
byte[] Ke = null;
byte[] Ki = null;
try {
// Derive encryption key
byte[] constant = new byte[5];
constant[0] = (byte) ((usage>>24)&0xff);
constant[1] = (byte) ((usage>>16)&0xff);
constant[2] = (byte) ((usage>>8)&0xff);
constant[3] = (byte) (usage&0xff);
constant[4] = (byte) 0xaa;
Ke = dk(baseKey, constant); // Encryption key
if (debug) {
System.err.println("usage: " + usage);
if (ivec != null) {
traceOutput("old_state.ivec", ivec, 0, ivec.length);
}
traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
traceOutput("constant", constant, 0, constant.length);
traceOutput("baseKey", baseKey, 0, baseKey.length);
traceOutput("Ke", Ke, 0, Ke.length);
}
// Decrypt [confounder | plaintext ] (without checksum)
// AES in JCE
Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
cipher.init(Cipher.DECRYPT_MODE, secretKey, encIv);
byte[] plaintext = cipher.doFinal(ciphertext, start, len-hashSize);
if (debug) {
traceOutput("AES PlainText", plaintext, 0,
Math.min(plaintext.length, 32));
}
// Derive integrity key
constant[4] = (byte) 0x55;
Ki = dk(baseKey, constant); // Integrity key
if (debug) {
traceOutput("constant", constant, 0, constant.length);
traceOutput("Ki", Ki, 0, Ke.length);
}
// Verify checksum
// H1 = HMAC(Ki, conf | plaintext | pad)
byte[] calculatedHmac = getHmac(Ki, plaintext);
int hmacOffset = start + len - hashSize;
if (debug) {
traceOutput("calculated Hmac", calculatedHmac,
0, calculatedHmac.length);
traceOutput("message Hmac", ciphertext, hmacOffset, hashSize);
}
boolean cksumFailed = false;
if (calculatedHmac.length >= hashSize) {
for (int i = 0; i < hashSize; i++) {
if (calculatedHmac[i] != ciphertext[hmacOffset+i]) {
cksumFailed = true;
if (debug) {
System.err.println("Checksum failed !");
}
break;
}
}
}
if (cksumFailed) {
throw new GeneralSecurityException("Checksum failed");
}
if (confounder_exists) {
// Get rid of confounder
// [ confounder | plaintext ]
byte[] output = new byte[plaintext.length - BLOCK_SIZE];
System.arraycopy(plaintext, BLOCK_SIZE, output,
0, output.length);
return output;
} else {
return plaintext;
}
} finally {
if (Ke != null) {
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
}
if (Ki != null) {
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
}
}
}
/*
* Invoke the PKCS#5 PBKDF2 algorithm
*/
private static byte[] PBKDF2(char[] secret, byte[] salt,
int count, int keyLength) throws GeneralSecurityException {
PBEKeySpec keySpec = new PBEKeySpec(secret, salt, count, keyLength);
SecretKeyFactory skf =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey key = skf.generateSecret(keySpec);
byte[] result = key.getEncoded();
return result;
}
public static final int readBigEndian(byte[] data, int pos, int size) {
int retVal = 0;
int shifter = (size-1)*8;
while (size > 0) {
retVal += (data[pos] & 0xff) << shifter;
shifter -= 8;
pos++;
size--;
}
return retVal;
}
}

View File

@@ -0,0 +1,482 @@
/*
* Copyright (c) 2005, 2008, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto.dk;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.Confounder;
import sun.security.krb5.internal.crypto.KeyUsage;
/**
* Support for ArcFour in Kerberos
* as defined in RFC 4757.
* http://www.ietf.org/rfc/rfc4757.txt
*
* @author Seema Malkani
*/
public class ArcFourCrypto extends DkCrypto {
private static final boolean debug = false;
private static final int confounderSize = 8;
private static final byte[] ZERO_IV = new byte[] {0, 0, 0, 0, 0, 0, 0, 0};
private static final int hashSize = 16;
private final int keyLength;
public ArcFourCrypto(int length) {
keyLength = length;
}
protected int getKeySeedLength() {
return keyLength; // bits; RC4 key material
}
protected byte[] randomToKey(byte[] in) {
// simple identity operation
return in;
}
public byte[] stringToKey(char[] passwd)
throws GeneralSecurityException {
return stringToKey(passwd, null);
}
/*
* String2Key(Password)
* K = MD4(UNICODE(password))
*/
private byte[] stringToKey(char[] secret, byte[] opaque)
throws GeneralSecurityException {
if (opaque != null && opaque.length > 0) {
throw new RuntimeException("Invalid parameter to stringToKey");
}
byte[] passwd = null;
byte[] digest = null;
try {
// convert ascii to unicode
passwd = charToUtf16(secret);
// provider for MD4
MessageDigest md = sun.security.provider.MD4.getInstance();
md.update(passwd);
digest = md.digest();
} catch (Exception e) {
return null;
} finally {
if (passwd != null) {
Arrays.fill(passwd, (byte)0);
}
}
return digest;
}
protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
throws GeneralSecurityException {
// IV
if (ivec == null) {
ivec = ZERO_IV;
}
SecretKeySpec secretKey = new SecretKeySpec(key, "ARCFOUR");
Cipher cipher = Cipher.getInstance("ARCFOUR");
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
cipher.init(mode, secretKey, encIv);
return cipher;
}
public int getChecksumLength() {
return hashSize; // bytes
}
/**
* Get the HMAC-MD5
*/
protected byte[] getHmac(byte[] key, byte[] msg)
throws GeneralSecurityException {
SecretKey keyKi = new SecretKeySpec(key, "HmacMD5");
Mac m = Mac.getInstance("HmacMD5");
m.init(keyKi);
// generate hash
byte[] hash = m.doFinal(msg);
return hash;
}
/**
* Calculate the checksum
*/
public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
int start, int len) throws GeneralSecurityException {
if (debug) {
System.out.println("ARCFOUR: calculateChecksum with usage = " +
usage);
}
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] Ksign = null;
// Derive signing key from session key
try {
byte[] ss = "signaturekey".getBytes();
// need to append end-of-string 00
byte[] new_ss = new byte[ss.length+1];
System.arraycopy(ss, 0, new_ss, 0, ss.length);
Ksign = getHmac(baseKey, new_ss);
} catch (Exception e) {
GeneralSecurityException gse =
new GeneralSecurityException("Calculate Checkum Failed!");
gse.initCause(e);
throw gse;
}
// get the salt using key usage
byte[] salt = getSalt(usage);
// Generate checksum of message
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
GeneralSecurityException gse =
new GeneralSecurityException("Calculate Checkum Failed!");
gse.initCause(e);
throw gse;
}
messageDigest.update(salt);
messageDigest.update(input, start, len);
byte[] md5tmp = messageDigest.digest();
// Generate checksum
byte[] hmac = getHmac(Ksign, md5tmp);
if (debug) {
traceOutput("hmac", hmac, 0, hmac.length);
}
if (hmac.length == getChecksumLength()) {
return hmac;
} else if (hmac.length > getChecksumLength()) {
byte[] buf = new byte[getChecksumLength()];
System.arraycopy(hmac, 0, buf, 0, buf.length);
return buf;
} else {
throw new GeneralSecurityException("checksum size too short: " +
hmac.length + "; expecting : " + getChecksumLength());
}
}
/**
* Performs encryption of Sequence Number using derived key.
*/
public byte[] encryptSeq(byte[] baseKey, int usage,
byte[] checksum, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
// derive encryption for sequence number
byte[] salt = new byte[4];
byte[] kSeq = getHmac(baseKey, salt);
// derive new encryption key salted with sequence number
kSeq = getHmac(kSeq, checksum);
Cipher cipher = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKey = new SecretKeySpec(kSeq, "ARCFOUR");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] output = cipher.doFinal(plaintext, start, len);
return output;
}
/**
* Performs decryption of Sequence Number using derived key.
*/
public byte[] decryptSeq(byte[] baseKey, int usage,
byte[] checksum, byte[] ciphertext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
// derive decryption for sequence number
byte[] salt = new byte[4];
byte[] kSeq = getHmac(baseKey, salt);
// derive new encryption key salted with sequence number
kSeq = getHmac(kSeq, checksum);
Cipher cipher = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKey = new SecretKeySpec(kSeq, "ARCFOUR");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] output = cipher.doFinal(ciphertext, start, len);
return output;
}
/**
* Performs encryption using derived key; adds confounder.
*/
public byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
if (debug) {
System.out.println("ArcFour: ENCRYPT with key usage = " + usage);
}
// get the confounder
byte[] confounder = Confounder.bytes(confounderSize);
// add confounder to the plaintext for encryption
int plainSize = roundup(confounder.length + len, 1);
byte[] toBeEncrypted = new byte[plainSize];
System.arraycopy(confounder, 0, toBeEncrypted, 0, confounder.length);
System.arraycopy(plaintext, start, toBeEncrypted,
confounder.length, len);
/* begin the encryption, compute K1 */
byte[] k1 = new byte[baseKey.length];
System.arraycopy(baseKey, 0, k1, 0, baseKey.length);
// get the salt using key usage
byte[] salt = getSalt(usage);
// compute K2 using K1
byte[] k2 = getHmac(k1, salt);
// generate checksum using K2
byte[] checksum = getHmac(k2, toBeEncrypted);
// compute K3 using K2 and checksum
byte[] k3 = getHmac(k2, checksum);
Cipher cipher = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKey = new SecretKeySpec(k3, "ARCFOUR");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] output = cipher.doFinal(toBeEncrypted, 0, toBeEncrypted.length);
// encryptedData + HMAC
byte[] result = new byte[hashSize + output.length];
System.arraycopy(checksum, 0, result, 0, hashSize);
System.arraycopy(output, 0, result, hashSize, output.length);
return result;
}
/**
* Performs encryption using derived key; does not add confounder.
*/
public byte[] encryptRaw(byte[] baseKey, int usage,
byte[] seqNum, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
if (debug) {
System.out.println("\nARCFOUR: encryptRaw with usage = " + usage);
}
// Derive encryption key for data
// Key derivation salt = 0
byte[] klocal = new byte[baseKey.length];
for (int i = 0; i <= 15; i++) {
klocal[i] = (byte) (baseKey[i] ^ 0xF0);
}
byte[] salt = new byte[4];
byte[] kcrypt = getHmac(klocal, salt);
// Note: When using this RC4 based encryption type, the sequence number
// is always sent in big-endian rather than little-endian order.
// new encryption key salted with sequence number
kcrypt = getHmac(kcrypt, seqNum);
Cipher cipher = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKey = new SecretKeySpec(kcrypt, "ARCFOUR");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] output = cipher.doFinal(plaintext, start, len);
return output;
}
/**
* @param baseKey key from which keys are to be derived using usage
* @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
*/
public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
if (debug) {
System.out.println("\nARCFOUR: DECRYPT using key usage = " + usage);
}
// compute K1
byte[] k1 = new byte[baseKey.length];
System.arraycopy(baseKey, 0, k1, 0, baseKey.length);
// get the salt using key usage
byte[] salt = getSalt(usage);
// compute K2 using K1
byte[] k2 = getHmac(k1, salt);
// compute K3 using K2 and checksum
byte[] checksum = new byte[hashSize];
System.arraycopy(ciphertext, start, checksum, 0, hashSize);
byte[] k3 = getHmac(k2, checksum);
// Decrypt [confounder | plaintext ] (without checksum)
Cipher cipher = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKey = new SecretKeySpec(k3, "ARCFOUR");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] plaintext = cipher.doFinal(ciphertext, start+hashSize,
len-hashSize);
// Verify checksum
byte[] calculatedHmac = getHmac(k2, plaintext);
if (debug) {
traceOutput("calculated Hmac", calculatedHmac, 0,
calculatedHmac.length);
traceOutput("message Hmac", ciphertext, 0,
hashSize);
}
boolean cksumFailed = false;
if (calculatedHmac.length >= hashSize) {
for (int i = 0; i < hashSize; i++) {
if (calculatedHmac[i] != ciphertext[i]) {
cksumFailed = true;
if (debug) {
System.err.println("Checksum failed !");
}
break;
}
}
}
if (cksumFailed) {
throw new GeneralSecurityException("Checksum failed");
}
// Get rid of confounder
// [ confounder | plaintext ]
byte[] output = new byte[plaintext.length - confounderSize];
System.arraycopy(plaintext, confounderSize, output, 0, output.length);
return output;
}
/**
* Decrypts data using specified key and initial vector.
* @param baseKey encryption key to use
* @param ciphertext encrypted data to be decrypted
* @param usage ignored
*/
public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len, byte[] seqNum)
throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
if (debug) {
System.out.println("\nARCFOUR: decryptRaw with usage = " + usage);
}
// Derive encryption key for data
// Key derivation salt = 0
byte[] klocal = new byte[baseKey.length];
for (int i = 0; i <= 15; i++) {
klocal[i] = (byte) (baseKey[i] ^ 0xF0);
}
byte[] salt = new byte[4];
byte[] kcrypt = getHmac(klocal, salt);
// need only first 4 bytes of sequence number
byte[] sequenceNum = new byte[4];
System.arraycopy(seqNum, 0, sequenceNum, 0, sequenceNum.length);
// new encryption key salted with sequence number
kcrypt = getHmac(kcrypt, sequenceNum);
Cipher cipher = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKey = new SecretKeySpec(kcrypt, "ARCFOUR");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] output = cipher.doFinal(ciphertext, start, len);
return output;
}
// get the salt using key usage
private byte[] getSalt(int usage) {
int ms_usage = arcfour_translate_usage(usage);
byte[] salt = new byte[4];
salt[0] = (byte)(ms_usage & 0xff);
salt[1] = (byte)((ms_usage >> 8) & 0xff);
salt[2] = (byte)((ms_usage >> 16) & 0xff);
salt[3] = (byte)((ms_usage >> 24) & 0xff);
return salt;
}
// Key usage translation for MS
private int arcfour_translate_usage(int usage) {
switch (usage) {
case 3: return 8;
case 9: return 8;
case 23: return 13;
default: return usage;
}
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 2004, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.krb5.internal.crypto.dk;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.spec.KeySpec;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.util.Arrays;
public class Des3DkCrypto extends DkCrypto {
private static final byte[] ZERO_IV = new byte[] {0, 0, 0, 0, 0, 0, 0, 0};
public Des3DkCrypto() {
}
protected int getKeySeedLength() {
return 168; // bits; 3DES key material has 21 bytes
}
public byte[] stringToKey(char[] salt) throws GeneralSecurityException {
byte[] saltUtf8 = null;
try {
saltUtf8 = charToUtf8(salt);
return stringToKey(saltUtf8, null);
} finally {
if (saltUtf8 != null) {
Arrays.fill(saltUtf8, (byte)0);
}
// Caller responsible for clearing its own salt
}
}
private byte[] stringToKey(byte[] secretAndSalt, byte[] opaque)
throws GeneralSecurityException {
if (opaque != null && opaque.length > 0) {
throw new RuntimeException("Invalid parameter to stringToKey");
}
byte[] tmpKey = randomToKey(nfold(secretAndSalt, getKeySeedLength()));
return dk(tmpKey, KERBEROS_CONSTANT);
}
public byte[] parityFix(byte[] value)
throws GeneralSecurityException {
// fix key parity
setParityBit(value);
return value;
}
/*
* From RFC 3961.
*
* The 168 bits of random key data are converted to a protocol key value
* as follows. First, the 168 bits are divided into three groups of 56
* bits, which are expanded individually into 64 bits as in des3Expand().
* Result is a 24 byte (192-bit) key.
*/
protected byte[] randomToKey(byte[] in) {
if (in.length != 21) {
throw new IllegalArgumentException("input must be 168 bits");
}
byte[] one = keyCorrection(des3Expand(in, 0, 7));
byte[] two = keyCorrection(des3Expand(in, 7, 14));
byte[] three = keyCorrection(des3Expand(in, 14, 21));
byte[] key = new byte[24];
System.arraycopy(one, 0, key, 0, 8);
System.arraycopy(two, 0, key, 8, 8);
System.arraycopy(three, 0, key, 16, 8);
return key;
}
private static byte[] keyCorrection(byte[] key) {
// check for weak key
try {
if (DESKeySpec.isWeak(key, 0)) {
key[7] = (byte)(key[7] ^ 0xF0);
}
} catch (InvalidKeyException ex) {
// swallow, since it should never happen
}
return key;
}
/**
* From RFC 3961.
*
* Expands a 7-byte array into an 8-byte array that contains parity bits.
* The 56 bits are expanded into 64 bits as follows:
* 1 2 3 4 5 6 7 p
* 9 10 11 12 13 14 15 p
* 17 18 19 20 21 22 23 p
* 25 26 27 28 29 30 31 p
* 33 34 35 36 37 38 39 p
* 41 42 43 44 45 46 47 p
* 49 50 51 52 53 54 55 p
* 56 48 40 32 24 16 8 p
*
* (PI,P2,...,P8) are reserved for parity bits computed on the preceding
* seven independent bits and set so that the parity of the octet is odd,
* i.e., there is an odd number of "1" bits in the octet.
*
* @param start index of starting byte (inclusive)
* @param end index of ending byte (exclusive)
*/
private static byte[] des3Expand(byte[] input, int start, int end) {
if ((end - start) != 7)
throw new IllegalArgumentException(
"Invalid length of DES Key Value:" + start + "," + end);
byte[] result = new byte[8];
byte last = 0;
System.arraycopy(input, start, result, 0, 7);
byte posn = 0;
// Fill in last row
for (int i = start; i < end; i++) {
byte bit = (byte) (input[i]&0x01);
if (debug) {
System.out.println(i + ": " + Integer.toHexString(input[i]) +
" bit= " + Integer.toHexString(bit));
}
++posn;
if (bit != 0) {
last |= (bit<<posn);
}
}
if (debug) {
System.out.println("last: " + Integer.toHexString(last));
}
result[7] = last;
setParityBit(result);
return result;
}
/**
* Sets the parity bit (0th bit) in each byte so that each byte
* contains an odd number of 1's.
*/
private static void setParityBit(byte[] key) {
for (int i = 0; i < key.length; i++) {
int b = key[i] & 0xfe;
b |= (Integer.bitCount(b) & 1) ^ 1;
key[i] = (byte) b;
}
}
protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
throws GeneralSecurityException {
// NoSuchAlgorithException
SecretKeyFactory factory = SecretKeyFactory.getInstance("desede");
// InvalidKeyException
KeySpec spec = new DESedeKeySpec(key, 0);
// InvalidKeySpecException
SecretKey secretKey = factory.generateSecret(spec);
// IV
if (ivec == null) {
ivec = ZERO_IV;
}
// NoSuchAlgorithmException, NoSuchPaddingException
// NoSuchProviderException
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
// InvalidKeyException, InvalidAlgorithParameterException
cipher.init(mode, secretKey, encIv);
return cipher;
}
public int getChecksumLength() {
return 20; // bytes
}
protected byte[] getHmac(byte[] key, byte[] msg)
throws GeneralSecurityException {
SecretKey keyKi = new SecretKeySpec(key, "HmacSHA1");
Mac m = Mac.getInstance("HmacSHA1");
m.init(keyKi);
return m.doFinal(msg);
}
}

View File

@@ -0,0 +1,699 @@
/*
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
* All rights reserved.
*
* Export of this software from the United States of America may require
* a specific license from the United States Government. It is the
* responsibility of any person or organization contemplating export to
* obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of FundsXpress. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package sun.security.krb5.internal.crypto.dk;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import java.security.GeneralSecurityException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import sun.misc.HexDumpEncoder;
import sun.security.krb5.Confounder;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.krb5.KrbCryptoException;
/**
* Implements Derive Key cryptography functionality as defined in RFC 3961.
* http://www.ietf.org/rfc/rfc3961.txt
*
* This is an abstract class. Concrete subclasses need to implement
* the abstract methods.
*/
public abstract class DkCrypto {
protected static final boolean debug = false;
// These values correspond to the ASCII encoding for the string "kerberos"
static final byte[] KERBEROS_CONSTANT =
{0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73};
protected abstract int getKeySeedLength(); // in bits
protected abstract byte[] randomToKey(byte[] in);
protected abstract Cipher getCipher(byte[] key, byte[] ivec, int mode)
throws GeneralSecurityException;
public abstract int getChecksumLength(); // in bytes
protected abstract byte[] getHmac(byte[] key, byte[] plaintext)
throws GeneralSecurityException;
/**
* From RFC 3961.
*
* encryption function conf = random string of length c
* pad = shortest string to bring confounder
* and plaintext to a length that's a
* multiple of m
* (C1, newIV) = E(Ke, conf | plaintext | pad,
* oldstate.ivec)
* H1 = HMAC(Ki, conf | plaintext | pad)
* ciphertext = C1 | H1[1..h]
* newstate.ivec = newIV
*
* @param ivec initial vector to use when initializing the cipher; if null,
* then blocksize number of zeros are used,
* @param new_ivec if non-null, it is updated upon return to be the
* new ivec to use when calling encrypt next time
*/
public byte[] encrypt(byte[] baseKey, int usage,
byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] Ke = null;
byte[] Ki = null;
try {
// Derive encryption key
byte[] constant = new byte[5];
constant[0] = (byte) ((usage>>24)&0xff);
constant[1] = (byte) ((usage>>16)&0xff);
constant[2] = (byte) ((usage>>8)&0xff);
constant[3] = (byte) (usage&0xff);
constant[4] = (byte) 0xaa;
Ke = dk(baseKey, constant);
if (debug) {
System.err.println("usage: " + usage);
if (ivec != null) {
traceOutput("old_state.ivec", ivec, 0, ivec.length);
}
traceOutput("plaintext", plaintext, start, Math.min(len, 32));
traceOutput("constant", constant, 0, constant.length);
traceOutput("baseKey", baseKey, 0, baseKey.length);
traceOutput("Ke", Ke, 0, Ke.length);
}
// Encrypt
// C1 = E(Ke, conf | plaintext | pad, oldivec)
Cipher encCipher = getCipher(Ke, ivec, Cipher.ENCRYPT_MODE);
int blockSize = encCipher.getBlockSize();
byte[] confounder = Confounder.bytes(blockSize);
int plainSize = roundup(confounder.length + len, blockSize);
if (debug) {
System.err.println("confounder = " + confounder.length +
"; plaintext = " + len + "; padding = " +
(plainSize - confounder.length - len) + "; total = " +
plainSize);
traceOutput("confounder", confounder, 0, confounder.length);
}
byte[] toBeEncrypted = new byte[plainSize];
System.arraycopy(confounder, 0, toBeEncrypted,
0, confounder.length);
System.arraycopy(plaintext, start, toBeEncrypted,
confounder.length, len);
// Set padding bytes to zero
Arrays.fill(toBeEncrypted, confounder.length + len, plainSize,
(byte)0);
int cipherSize = encCipher.getOutputSize(plainSize);
int ccSize = cipherSize + getChecksumLength(); // cipher | hmac
byte[] ciphertext = new byte[ccSize];
encCipher.doFinal(toBeEncrypted, 0, plainSize, ciphertext, 0);
// Update ivec for next operation
// (last blockSize bytes of ciphertext)
// newstate.ivec = newIV
if (new_ivec != null && new_ivec.length == blockSize) {
System.arraycopy(ciphertext, cipherSize - blockSize,
new_ivec, 0, blockSize);
if (debug) {
traceOutput("new_ivec", new_ivec, 0, new_ivec.length);
}
}
// Derive integrity key
constant[4] = (byte) 0x55;
Ki = dk(baseKey, constant);
if (debug) {
traceOutput("constant", constant, 0, constant.length);
traceOutput("Ki", Ki, 0, Ke.length);
}
// Generate checksum
// H1 = HMAC(Ki, conf | plaintext | pad)
byte[] hmac = getHmac(Ki, toBeEncrypted);
if (debug) {
traceOutput("hmac", hmac, 0, hmac.length);
traceOutput("ciphertext", ciphertext, 0,
Math.min(ciphertext.length, 32));
}
// C1 | H1[1..h]
System.arraycopy(hmac, 0, ciphertext, cipherSize,
getChecksumLength());
return ciphertext;
} finally {
if (Ke != null) {
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
}
if (Ki != null) {
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
}
}
}
/**
* Performs encryption using given key only; does not add
* confounder, padding, or checksum. Incoming data to be encrypted
* assumed to have the correct blocksize.
* Ignore key usage.
*/
public byte[] encryptRaw(byte[] baseKey, int usage,
byte[] ivec, byte[] plaintext, int start, int len)
throws GeneralSecurityException, KrbCryptoException {
if (debug) {
System.err.println("usage: " + usage);
if (ivec != null) {
traceOutput("old_state.ivec", ivec, 0, ivec.length);
}
traceOutput("plaintext", plaintext, start, Math.min(len, 32));
traceOutput("baseKey", baseKey, 0, baseKey.length);
}
// Encrypt
Cipher encCipher = getCipher(baseKey, ivec, Cipher.ENCRYPT_MODE);
int blockSize = encCipher.getBlockSize();
if ((len % blockSize) != 0) {
throw new GeneralSecurityException(
"length of data to be encrypted (" + len +
") is not a multiple of the blocksize (" + blockSize + ")");
}
int cipherSize = encCipher.getOutputSize(len);
byte[] ciphertext = new byte[cipherSize];
encCipher.doFinal(plaintext, 0, len, ciphertext, 0);
return ciphertext;
}
/**
* Decrypts data using specified key and initial vector.
* @param baseKey encryption key to use
* @param ciphertext encrypted data to be decrypted
* @param usage ignored
*/
public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len)
throws GeneralSecurityException {
if (debug) {
System.err.println("usage: " + usage);
if (ivec != null) {
traceOutput("old_state.ivec", ivec, 0, ivec.length);
}
traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
traceOutput("baseKey", baseKey, 0, baseKey.length);
}
Cipher decCipher = getCipher(baseKey, ivec, Cipher.DECRYPT_MODE);
int blockSize = decCipher.getBlockSize();
if ((len % blockSize) != 0) {
throw new GeneralSecurityException(
"length of data to be decrypted (" + len +
") is not a multiple of the blocksize (" + blockSize + ")");
}
byte[] decrypted = decCipher.doFinal(ciphertext, start, len);
if (debug) {
traceOutput("decrypted", decrypted, 0,
Math.min(decrypted.length, 32));
}
return decrypted;
}
/**
* @param baseKey key from which keys are to be derived using usage
* @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
*/
public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
byte[] ciphertext, int start, int len) throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
byte[] Ke = null;
byte[] Ki = null;
try {
// Derive encryption key
byte[] constant = new byte[5];
constant[0] = (byte) ((usage>>24)&0xff);
constant[1] = (byte) ((usage>>16)&0xff);
constant[2] = (byte) ((usage>>8)&0xff);
constant[3] = (byte) (usage&0xff);
constant[4] = (byte) 0xaa;
Ke = dk(baseKey, constant); // Encryption key
if (debug) {
System.err.println("usage: " + usage);
if (ivec != null) {
traceOutput("old_state.ivec", ivec, 0, ivec.length);
}
traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
traceOutput("constant", constant, 0, constant.length);
traceOutput("baseKey", baseKey, 0, baseKey.length);
traceOutput("Ke", Ke, 0, Ke.length);
}
Cipher decCipher = getCipher(Ke, ivec, Cipher.DECRYPT_MODE);
int blockSize = decCipher.getBlockSize();
// Decrypt [confounder | plaintext | padding] (without checksum)
int cksumSize = getChecksumLength();
int cipherSize = len - cksumSize;
byte[] decrypted = decCipher.doFinal(ciphertext, start, cipherSize);
if (debug) {
traceOutput("decrypted", decrypted, 0,
Math.min(decrypted.length, 32));
}
// decrypted = [confounder | plaintext | padding]
// Derive integrity key
constant[4] = (byte) 0x55;
Ki = dk(baseKey, constant); // Integrity key
if (debug) {
traceOutput("constant", constant, 0, constant.length);
traceOutput("Ki", Ki, 0, Ke.length);
}
// Verify checksum
// H1 = HMAC(Ki, conf | plaintext | pad)
byte[] calculatedHmac = getHmac(Ki, decrypted);
if (debug) {
traceOutput("calculated Hmac", calculatedHmac, 0,
calculatedHmac.length);
traceOutput("message Hmac", ciphertext, cipherSize,
cksumSize);
}
boolean cksumFailed = false;
if (calculatedHmac.length >= cksumSize) {
for (int i = 0; i < cksumSize; i++) {
if (calculatedHmac[i] != ciphertext[cipherSize+i]) {
cksumFailed = true;
break;
}
}
}
if (cksumFailed) {
throw new GeneralSecurityException("Checksum failed");
}
// Prepare decrypted msg and ivec to be returned
// Last blockSize bytes of ciphertext without checksum
if (ivec != null && ivec.length == blockSize) {
System.arraycopy(ciphertext, start + cipherSize - blockSize,
ivec, 0, blockSize);
if (debug) {
traceOutput("new_state.ivec", ivec, 0, ivec.length);
}
}
// Get rid of confounder
// [plaintext | padding]
byte[] plaintext = new byte[decrypted.length - blockSize];
System.arraycopy(decrypted, blockSize, plaintext,
0, plaintext.length);
return plaintext; // padding still there
} finally {
if (Ke != null) {
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
}
if (Ki != null) {
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
}
}
}
// Round up to the next blocksize
int roundup(int n, int blocksize) {
return (((n + blocksize - 1) / blocksize) * blocksize);
}
public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
int start, int len) throws GeneralSecurityException {
if (!KeyUsage.isValid(usage)) {
throw new GeneralSecurityException("Invalid key usage number: "
+ usage);
}
// Derive keys
byte[] constant = new byte[5];
constant[0] = (byte) ((usage>>24)&0xff);
constant[1] = (byte) ((usage>>16)&0xff);
constant[2] = (byte) ((usage>>8)&0xff);
constant[3] = (byte) (usage&0xff);
constant[4] = (byte) 0x99;
byte[] Kc = dk(baseKey, constant); // Checksum key
if (debug) {
System.err.println("usage: " + usage);
traceOutput("input", input, start, Math.min(len, 32));
traceOutput("constant", constant, 0, constant.length);
traceOutput("baseKey", baseKey, 0, baseKey.length);
traceOutput("Kc", Kc, 0, Kc.length);
}
try {
// Generate checksum
// H1 = HMAC(Kc, input)
byte[] hmac = getHmac(Kc, input);
if (debug) {
traceOutput("hmac", hmac, 0, hmac.length);
}
if (hmac.length == getChecksumLength()) {
return hmac;
} else if (hmac.length > getChecksumLength()) {
byte[] buf = new byte[getChecksumLength()];
System.arraycopy(hmac, 0, buf, 0, buf.length);
return buf;
} else {
throw new GeneralSecurityException("checksum size too short: " +
hmac.length + "; expecting : " + getChecksumLength());
}
} finally {
Arrays.fill(Kc, 0, Kc.length, (byte)0);
}
}
// DK(Key, Constant) = random-to-key(DR(Key, Constant))
byte[] dk(byte[] key, byte[] constant)
throws GeneralSecurityException {
return randomToKey(dr(key, constant));
}
/*
* From RFC 3961.
*
* DR(Key, Constant) = k-truncate(E(Key, Constant,
* initial-cipher-state))
*
* Here DR is the random-octet generation function described below, and
* DK is the key-derivation function produced from it. In this
* construction, E(Key, Plaintext, CipherState) is a cipher, Constant is
* a well-known constant determined by the specific usage of this
* function, and k-truncate truncates its argument by taking the first k
* bits. Here, k is the key generation seed length needed for the
* encryption system.
*
* The output of the DR function is a string of bits; the actual key is
* produced by applying the cryptosystem's random-to-key operation on
* this bitstring.
*
* If the Constant is smaller than the cipher block size of E, then it
* must be expanded with n-fold() so it can be encrypted. If the output
* of E is shorter than k bits it is fed back into the encryption as
* many times as necessary. The construct is as follows (where |
* indicates concatentation):
*
* K1 = E(Key, n-fold(Constant), initial-cipher-state)
* K2 = E(Key, K1, initial-cipher-state)
* K3 = E(Key, K2, initial-cipher-state)
* K4 = ...
*
* DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
*/
private byte[] dr(byte[] key, byte[] constant)
throws GeneralSecurityException {
Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
int blocksize = encCipher.getBlockSize();
if (constant.length != blocksize) {
constant = nfold(constant, blocksize * 8);
}
byte[] toBeEncrypted = constant;
int keybytes = (getKeySeedLength()>>3); // from bits to bytes
byte[] rawkey = new byte[keybytes];
int posn = 0;
/* loop encrypting the blocks until enough key bytes are generated */
int n = 0, len;
while (n < keybytes) {
if (debug) {
System.err.println("Encrypting: " +
bytesToString(toBeEncrypted));
}
byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
if (debug) {
System.err.println("K: " + ++posn + " = " +
bytesToString(cipherBlock));
}
len = (keybytes - n <= cipherBlock.length ? (keybytes - n) :
cipherBlock.length);
if (debug) {
System.err.println("copying " + len + " key bytes");
}
System.arraycopy(cipherBlock, 0, rawkey, n, len);
n += len;
toBeEncrypted = cipherBlock;
}
return rawkey;
}
// ---------------------------------
// From MIT-1.3.1 distribution
/*
* n-fold(k-bits):
* l = lcm(n,k)
* r = l/k
* s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
* compute the 1's complement sum:
* n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
*/
/*
* representation: msb first, assume n and k are multiples of 8, and
* that k>=16. this is the case of all the cryptosystems which are
* likely to be used. this function can be replaced if that
* assumption ever fails.
*/
/* input length is in bits */
static byte[] nfold(byte[] in, int outbits) {
int inbits = in.length;
outbits >>= 3; // count in bytes
/* first compute lcm(n,k) */
int a, b, c, lcm;
a = outbits; // n
b = inbits; // k
while (b != 0) {
c = b;
b = a % b;
a = c;
}
lcm = outbits*inbits/a;
if (debug) {
System.err.println("k: " + inbits);
System.err.println("n: " + outbits);
System.err.println("lcm: " + lcm);
}
/* now do the real work */
byte[] out = new byte[outbits];
Arrays.fill(out, (byte)0);
int thisbyte = 0;
int msbit, i, bval, oval;
// this will end up cycling through k lcm(k,n)/k times, which
// is correct
for (i = lcm-1; i >= 0; i--) {
/* compute the msbit in k which gets added into this byte */
msbit = (/* first, start with msbit in the first, unrotated byte */
((inbits<<3)-1)
/* then, for each byte, shift to right for each repetition */
+ (((inbits<<3)+13)*(i/inbits))
/* last, pick out correct byte within that shifted repetition */
+ ((inbits-(i%inbits)) << 3)) % (inbits << 3);
/* pull out the byte value itself */
// Mask off values using &0xff to get only the lower byte
// Use >>> to avoid sign extension
bval = ((((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)|
(in[((inbits)-(msbit>>>3))%inbits]&0xff))
>>>((msbit&7)+1))&0xff;
/*
System.err.println("((" +
((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)
+ "|" + (in[((inbits)-(msbit>>>3))%inbits]&0xff) + ")"
+ ">>>" + ((msbit&7)+1) + ")&0xff = " + bval);
*/
thisbyte += bval;
/* do the addition */
// Mask off values using &0xff to get only the lower byte
oval = (out[i%outbits]&0xff);
thisbyte += oval;
out[i%outbits] = (byte) (thisbyte&0xff);
if (debug) {
System.err.println("msbit[" + i + "] = " + msbit + "\tbval=" +
Integer.toHexString(bval) + "\toval=" +
Integer.toHexString(oval)
+ "\tsum = " + Integer.toHexString(thisbyte));
}
/* keep around the carry bit, if any */
thisbyte >>>= 8;
if (debug) {
System.err.println("carry=" + thisbyte);
}
}
/* if there's a carry bit left over, add it back in */
if (thisbyte != 0) {
for (i = outbits-1; i >= 0; i--) {
/* do the addition */
thisbyte += (out[i]&0xff);
out[i] = (byte) (thisbyte&0xff);
/* keep around the carry bit, if any */
thisbyte >>>= 8;
}
}
return out;
}
// Routines used for debugging
static String bytesToString(byte[] digest) {
// Get character representation of digest
StringBuffer digestString = new StringBuffer();
for (int i = 0; i < digest.length; i++) {
if ((digest[i] & 0x000000ff) < 0x10) {
digestString.append("0" +
Integer.toHexString(digest[i] & 0x000000ff));
} else {
digestString.append(
Integer.toHexString(digest[i] & 0x000000ff));
}
}
return digestString.toString();
}
private static byte[] binaryStringToBytes(String str) {
char[] usageStr = str.toCharArray();
byte[] usage = new byte[usageStr.length/2];
for (int i = 0; i < usage.length; i++) {
byte a = Byte.parseByte(new String(usageStr, i*2, 1), 16);
byte b = Byte.parseByte(new String(usageStr, i*2 + 1, 1), 16);
usage[i] = (byte) ((a<<4)|b);
}
return usage;
}
static void traceOutput(String traceTag, byte[] output, int offset,
int len) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(len);
new HexDumpEncoder().encodeBuffer(
new ByteArrayInputStream(output, offset, len), out);
System.err.println(traceTag + ":" + out.toString());
} catch (Exception e) {
}
}
// String.getBytes("UTF-8");
// Do this instead of using String to avoid making password immutable
static byte[] charToUtf8(char[] chars) {
Charset utf8 = Charset.forName("UTF-8");
CharBuffer cb = CharBuffer.wrap(chars);
ByteBuffer bb = utf8.encode(cb);
int len = bb.limit();
byte[] answer = new byte[len];
bb.get(answer, 0, len);
return answer;
}
static byte[] charToUtf16(char[] chars) {
Charset utf8 = Charset.forName("UTF-16LE");
CharBuffer cb = CharBuffer.wrap(chars);
ByteBuffer bb = utf8.encode(cb);
int len = bb.limit();
byte[] answer = new byte[len];
bb.get(answer, 0, len);
return answer;
}
}

View File

@@ -0,0 +1,524 @@
/*
* Copyright (c) 2000, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ktab;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
import sun.security.jgss.krb5.ServiceCreds;
/**
* This class represents key table. The key table functions deal with storing
* and retrieving service keys for use in authentication exchanges.
*
* A KeyTab object is always constructed, if the file specified does not
* exist, it's still valid but empty. If there is an I/O error or file format
* error, it's invalid.
*
* The class is immutable on the read side (the write side is only used by
* the ktab tool).
*
* @author Yanni Zhang
*/
public class KeyTab implements KeyTabConstants {
private static final boolean DEBUG = Krb5.DEBUG;
private static String defaultTabName = null;
// Attention: Currently there is no way to remove a keytab from this map,
// this might lead to a memory leak.
private static Map<String,KeyTab> map = new HashMap<>();
// KeyTab file does not exist. Note: a missing keytab is still valid
private boolean isMissing = false;
// KeyTab file is invalid, possibly an I/O error or a file format error.
private boolean isValid = true;
private final String tabName;
private long lastModified;
private int kt_vno = KRB5_KT_VNO;
private Vector<KeyTabEntry> entries = new Vector<>();
/**
* Constructs a KeyTab object.
*
* If there is any I/O error or format errot during the loading, the
* isValid flag is set to false, and all half-read entries are dismissed.
* @param filename path name for the keytab file, must not be null
*/
private KeyTab(String filename) {
tabName = filename;
try {
lastModified = new File(tabName).lastModified();
try (KeyTabInputStream kis =
new KeyTabInputStream(new FileInputStream(filename))) {
load(kis);
}
} catch (FileNotFoundException e) {
entries.clear();
isMissing = true;
} catch (Exception ioe) {
entries.clear();
isValid = false;
}
}
/**
* Read a keytab file. Returns a new object and save it into cache when
* new content (modified since last read) is available. If keytab file is
* invalid, the old object will be returned. This is a safeguard for
* partial-written keytab files or non-stable network. Please note that
* a missing keytab is valid, which is equivalent to an empty keytab.
*
* @param s file name of keytab, must not be null
* @return the keytab object, can be invalid, but never null.
*/
private synchronized static KeyTab getInstance0(String s) {
long lm = new File(s).lastModified();
KeyTab old = map.get(s);
if (old != null && old.isValid() && old.lastModified == lm) {
return old;
}
KeyTab ktab = new KeyTab(s);
if (ktab.isValid()) { // A valid new keytab
map.put(s, ktab);
return ktab;
} else if (old != null) { // An existing old one
return old;
} else {
return ktab; // first read is invalid
}
}
/**
* Gets a KeyTab object.
* @param s the key tab file name.
* @return the KeyTab object, never null.
*/
public static KeyTab getInstance(String s) {
if (s == null) {
return getInstance();
} else {
return getInstance0(normalize(s));
}
}
/**
* Gets a KeyTab object.
* @param file the key tab file.
* @return the KeyTab object, never null.
*/
public static KeyTab getInstance(File file) {
if (file == null) {
return getInstance();
} else {
return getInstance0(file.getPath());
}
}
/**
* Gets the default KeyTab object.
* @return the KeyTab object, never null.
*/
public static KeyTab getInstance() {
return getInstance(getDefaultTabName());
}
public boolean isMissing() {
return isMissing;
}
public boolean isValid() {
return isValid;
}
/**
* The location of keytab file will be read from the configuration file
* If it is not specified, consider user.home as the keytab file's
* default location.
* @return never null
*/
private static String getDefaultTabName() {
if (defaultTabName != null) {
return defaultTabName;
} else {
String kname = null;
try {
String keytab_names = Config.getInstance().get
("libdefaults", "default_keytab_name");
if (keytab_names != null) {
StringTokenizer st = new StringTokenizer(keytab_names, " ");
while (st.hasMoreTokens()) {
kname = normalize(st.nextToken());
if (new File(kname).exists()) {
break;
}
}
}
} catch (KrbException e) {
kname = null;
}
if (kname == null) {
String user_home =
java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.home"));
if (user_home == null) {
user_home =
java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.dir"));
}
kname = user_home + File.separator + "krb5.keytab";
}
defaultTabName = kname;
return kname;
}
}
/**
* Normalizes some common keytab name formats into the bare file name.
* For example, FILE:/etc/krb5.keytab to /etc/krb5.keytab
* @param name never null
* @return never null
*/
// This method is used in this class and Krb5LoginModule
public static String normalize(String name) {
String kname;
if ((name.length() >= 5) &&
(name.substring(0, 5).equalsIgnoreCase("FILE:"))) {
kname = name.substring(5);
} else if ((name.length() >= 9) &&
(name.substring(0, 9).equalsIgnoreCase("ANY:FILE:"))) {
// this format found in MIT's krb5.ini.
kname = name.substring(9);
} else if ((name.length() >= 7) &&
(name.substring(0, 7).equalsIgnoreCase("SRVTAB:"))) {
// this format found in MIT's krb5.ini.
kname = name.substring(7);
} else
kname = name;
return kname;
}
private void load(KeyTabInputStream kis)
throws IOException, RealmException {
entries.clear();
kt_vno = kis.readVersion();
if (kt_vno == KRB5_KT_VNO_1) {
kis.setNativeByteOrder();
}
int entryLength = 0;
KeyTabEntry entry;
while (kis.available() > 0) {
entryLength = kis.readEntryLength();
entry = kis.readEntry(entryLength, kt_vno);
if (DEBUG) {
System.out.println(">>> KeyTab: load() entry length: " +
entryLength + "; type: " +
(entry != null? entry.keyType : 0));
}
if (entry != null)
entries.addElement(entry);
}
}
/**
* Returns a principal name in this keytab. Used by
* {@link ServiceCreds#getKKeys()}.
*/
public PrincipalName getOneName() {
int size = entries.size();
return size > 0 ? entries.elementAt(size-1).service : null;
}
/**
* Reads all keys for a service from the keytab file that have
* etypes that have been configured for use.
* @param service the PrincipalName of the requested service
* @return an array containing all the service keys, never null
*/
public EncryptionKey[] readServiceKeys(PrincipalName service) {
KeyTabEntry entry;
EncryptionKey key;
int size = entries.size();
ArrayList<EncryptionKey> keys = new ArrayList<>(size);
if (DEBUG) {
System.out.println("Looking for keys for: " + service);
}
for (int i = size-1; i >= 0; i--) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
key = new EncryptionKey(entry.keyblock,
entry.keyType,
new Integer(entry.keyVersion));
keys.add(key);
if (DEBUG) {
System.out.println("Added key: " + entry.keyType +
"version: " + entry.keyVersion);
}
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
}
}
}
size = keys.size();
EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
// Sort the keys by kvno. Sometimes we must choose a single key (say,
// generate encrypted timestamp in AS-REQ). A key with a higher KVNO
// sounds like a newer one.
Arrays.sort(retVal, new Comparator<EncryptionKey>() {
@Override
public int compare(EncryptionKey o1, EncryptionKey o2) {
return o2.getKeyVersionNumber().intValue()
- o1.getKeyVersionNumber().intValue();
}
});
return retVal;
}
/**
* Searches for the service entry in the keytab file.
* The etype of the key must be one that has been configured
* to be used.
* @param service the PrincipalName of the requested service.
* @return true if the entry is found, otherwise, return false.
*/
public boolean findServiceEntry(PrincipalName service) {
KeyTabEntry entry;
for (int i = 0; i < entries.size(); i++) {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
return true;
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
}
}
}
return false;
}
public String tabName() {
return tabName;
}
/////////////////// THE WRITE SIDE ///////////////////////
/////////////// only used by ktab tool //////////////////
/**
* Adds a new entry in the key table.
* @param service the service which will have a new entry in the key table.
* @param psswd the password which generates the key.
* @param kvno the kvno to use, -1 means automatic increasing
* @param append false if entries with old kvno would be removed.
* Note: if kvno is not -1, entries with the same kvno are always removed
*/
public void addEntry(PrincipalName service, char[] psswd,
int kvno, boolean append) throws KrbException {
addEntry(service, service.getSalt(), psswd, kvno, append);
}
// Called by KDC test
public void addEntry(PrincipalName service, String salt, char[] psswd,
int kvno, boolean append) throws KrbException {
EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
psswd, salt);
// There should be only one maximum KVNO value for all etypes, so that
// all added keys can have the same KVNO.
int maxKvno = 0; // only useful when kvno == -1
for (int i = entries.size()-1; i >= 0; i--) {
KeyTabEntry e = entries.get(i);
if (e.service.match(service)) {
if (e.keyVersion > maxKvno) {
maxKvno = e.keyVersion;
}
if (!append || e.keyVersion == kvno) {
entries.removeElementAt(i);
}
}
}
if (kvno == -1) {
kvno = maxKvno + 1;
}
for (int i = 0; encKeys != null && i < encKeys.length; i++) {
int keyType = encKeys[i].getEType();
byte[] keyValue = encKeys[i].getBytes();
KeyTabEntry newEntry = new KeyTabEntry(service,
service.getRealm(),
new KerberosTime(System.currentTimeMillis()),
kvno, keyType, keyValue);
entries.addElement(newEntry);
}
}
/**
* Gets the list of service entries in key table.
* @return array of <code>KeyTabEntry</code>.
*/
public KeyTabEntry[] getEntries() {
KeyTabEntry[] kentries = new KeyTabEntry[entries.size()];
for (int i = 0; i < kentries.length; i++) {
kentries[i] = entries.elementAt(i);
}
return kentries;
}
/**
* Creates a new default key table.
*/
public synchronized static KeyTab create()
throws IOException, RealmException {
String dname = getDefaultTabName();
return create(dname);
}
/**
* Creates a new default key table.
*/
public synchronized static KeyTab create(String name)
throws IOException, RealmException {
try (KeyTabOutputStream kos =
new KeyTabOutputStream(new FileOutputStream(name))) {
kos.writeVersion(KRB5_KT_VNO);
}
return new KeyTab(name);
}
/**
* Saves the file at the directory.
*/
public synchronized void save() throws IOException {
try (KeyTabOutputStream kos =
new KeyTabOutputStream(new FileOutputStream(tabName))) {
kos.writeVersion(kt_vno);
for (int i = 0; i < entries.size(); i++) {
kos.writeEntry(entries.elementAt(i));
}
}
}
/**
* Removes entries from the key table.
* @param service the service <code>PrincipalName</code>.
* @param etype the etype to match, remove all if -1
* @param kvno what kvno to remove, -1 for all, -2 for old
* @return the number of entries deleted
*/
public int deleteEntries(PrincipalName service, int etype, int kvno) {
int count = 0;
// Remember the highest KVNO for each etype. Used for kvno == -2
Map<Integer,Integer> highest = new HashMap<>();
for (int i = entries.size()-1; i >= 0; i--) {
KeyTabEntry e = entries.get(i);
if (service.match(e.getService())) {
if (etype == -1 || e.keyType == etype) {
if (kvno == -2) {
// Two rounds for kvno == -2. In the first round (here),
// only find out highest KVNO for each etype
if (highest.containsKey(e.keyType)) {
int n = highest.get(e.keyType);
if (e.keyVersion > n) {
highest.put(e.keyType, e.keyVersion);
}
} else {
highest.put(e.keyType, e.keyVersion);
}
} else if (kvno == -1 || e.keyVersion == kvno) {
entries.removeElementAt(i);
count++;
}
}
}
}
// Second round for kvno == -2, remove old entries
if (kvno == -2) {
for (int i = entries.size()-1; i >= 0; i--) {
KeyTabEntry e = entries.get(i);
if (service.match(e.getService())) {
if (etype == -1 || e.keyType == etype) {
int n = highest.get(e.keyType);
if (e.keyVersion != n) {
entries.removeElementAt(i);
count++;
}
}
}
}
}
return count;
}
/**
* Creates key table file version.
* @param file the key table file.
* @exception IOException
*/
public synchronized void createVersion(File file) throws IOException {
try (KeyTabOutputStream kos =
new KeyTabOutputStream(new FileOutputStream(file))) {
kos.write16(KRB5_KT_VNO);
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ktab;
import sun.security.krb5.internal.*;
/**
* This class represents a Key Table entry. Each entry contains the service principal of
* the key, time stamp, key version and secret key itself.
*
* @author Yanni Zhang
*/
public interface KeyTabConstants {
final int principalComponentSize = 2;
final int realmSize = 2;
final int principalSize = 2;
final int principalTypeSize = 4;
final int timestampSize = 4;
final int keyVersionSize = 1;
final int keyTypeSize = 2;
final int keySize = 2;
static final int KRB5_KT_VNO_1 = 0x0501; /* krb v5, keytab version 1 (DCE compat) */
static final int KRB5_KT_VNO = 0x0502; /* krb v5, keytab version 2 (standard) */
}

View File

@@ -0,0 +1,112 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ktab;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import java.io.UnsupportedEncodingException;
/**
* This class represents a Key Table entry. Each entry contains the service principal of
* the key, time stamp, key version and secret key itself.
*
* @author Yanni Zhang
*/
public class KeyTabEntry implements KeyTabConstants {
PrincipalName service;
Realm realm;
KerberosTime timestamp;
int keyVersion;
int keyType;
byte[] keyblock = null;
boolean DEBUG = Krb5.DEBUG;
public KeyTabEntry (PrincipalName new_service, Realm new_realm, KerberosTime new_time,
int new_keyVersion, int new_keyType, byte[] new_keyblock) {
service = new_service;
realm = new_realm;
timestamp = new_time;
keyVersion = new_keyVersion;
keyType = new_keyType;
if (new_keyblock != null) {
keyblock = new_keyblock.clone();
}
}
public PrincipalName getService() {
return service;
}
public EncryptionKey getKey() {
EncryptionKey key = new EncryptionKey(keyblock,
keyType,
new Integer(keyVersion));
return key;
}
public String getKeyString() {
StringBuffer sb = new StringBuffer("0x");
for (int i = 0; i < keyblock.length; i++) {
sb.append(String.format("%02x", keyblock[i]&0xff));
}
return sb.toString();
}
public int entryLength() {
int totalPrincipalLength = 0;
String[] names = service.getNameStrings();
for (int i = 0; i < names.length; i++) {
try {
totalPrincipalLength += principalSize + names[i].getBytes("8859_1").length;
} catch (UnsupportedEncodingException exc) {
}
}
int realmLen = 0;
try {
realmLen = realm.toString().getBytes("8859_1").length;
} catch (UnsupportedEncodingException exc) {
}
int size = principalComponentSize + realmSize + realmLen
+ totalPrincipalLength + principalTypeSize
+ timestampSize + keyVersionSize
+ keyTypeSize + keySize + keyblock.length;
if (DEBUG) {
System.out.println(">>> KeyTabEntry: key tab entry size is " + size);
}
return size;
}
public KerberosTime getTimeStamp() {
return timestamp;
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2000, 2012, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ktab;
import sun.security.krb5.internal.*;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.Realm;
import sun.security.krb5.RealmException;
import sun.security.krb5.internal.util.KrbDataInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* This class implements a buffered input stream. It is used for parsing key table
* data to memory.
*
* @author Yanni Zhang
*
*/
public class KeyTabInputStream extends KrbDataInputStream implements KeyTabConstants {
boolean DEBUG = Krb5.DEBUG;
int index;
public KeyTabInputStream(InputStream is) {
super(is);
}
/**
* Reads the number of bytes this entry data occupy.
*/
int readEntryLength() throws IOException {
return read(4);
}
KeyTabEntry readEntry(int entryLen, int ktVersion) throws IOException, RealmException {
index = entryLen;
if (index == 0) { //in native implementation, when the last entry is deleted, a byte 0 is left.
return null;
}
if (index < 0) { //in native implementation, when one of the entries is deleted, the entry length turns to be negative, and
skip(Math.abs(index)); //the fields are left with 0 bytes
return null;
}
int principalNum = read(2); //the number of service names.
index -= 2;
if (ktVersion == KRB5_KT_VNO_1) { //V1 includes realm in the count.
principalNum -= 1;
}
Realm realm = new Realm(readName());
String[] nameParts = new String[principalNum];
for (int i = 0; i < principalNum; i++) {
nameParts[i] = readName();
}
int nameType = read(4);
index -= 4;
PrincipalName service = new PrincipalName(nameType, nameParts, realm);
KerberosTime timeStamp = readTimeStamp();
int keyVersion = read() & 0xff;
index -= 1;
int keyType = read(2);
index -= 2;
int keyLength = read(2);
index -= 2;
byte[] keyblock = readKey(keyLength);
index -= keyLength;
// There might be a 32 bit kvno here.
// If index is zero, assume that the 8 bit key version number was
// right, otherwise trust the new nonzero value.
if (index >= 4) {
int extKvno = read(4);
if (extKvno != 0) {
keyVersion = extKvno;
}
index -= 4;
}
// if index is negative, the keytab format must be wrong.
if (index < 0) {
throw new RealmException("Keytab is corrupted");
}
// ignore the left bytes.
skip(index);
return new KeyTabEntry(service, realm, timeStamp, keyVersion, keyType, keyblock);
}
byte[] readKey(int length) throws IOException {
byte[] bytes = new byte[length];
read(bytes, 0, length);
return bytes;
}
KerberosTime readTimeStamp() throws IOException {
index -= 4;
return new KerberosTime((long)read(4) * 1000);
}
String readName() throws IOException {
String name;
int length = read(2); //length of the realm name or service name
index -= 2;
byte[] bytes = new byte[length];
read(bytes, 0, length);
index -= length;
name = new String(bytes);
if (DEBUG) {
System.out.println(">>> KeyTabInputStream, readName(): " + name);
}
return name;
}
}

View File

@@ -0,0 +1,104 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.ktab;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.util.KrbDataOutputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* This class implements a buffered input stream. It is used for parsing key table
* data to memory.
*
* @author Yanni Zhang
*
*/
public class KeyTabOutputStream extends KrbDataOutputStream implements KeyTabConstants {
private KeyTabEntry entry;
private int keyType;
private byte[] keyValue;
public int version;
public KeyTabOutputStream(OutputStream os) {
super(os);
}
public void writeVersion(int num) throws IOException {
version = num;
write16(num); //we use the standard version.
}
public void writeEntry(KeyTabEntry entry) throws IOException {
write32(entry.entryLength());
String[] serviceNames = entry.service.getNameStrings();
int comp_num = serviceNames.length;
if (version == KRB5_KT_VNO_1) {
write16(comp_num + 1);
}
else write16(comp_num);
byte[] realm = null;
try {
realm = entry.service.getRealmString().getBytes("8859_1");
} catch (UnsupportedEncodingException exc) {
}
write16(realm.length);
write(realm);
for (int i = 0; i < comp_num; i++) {
try {
write16(serviceNames[i].getBytes("8859_1").length);
write(serviceNames[i].getBytes("8859_1"));
} catch (UnsupportedEncodingException exc) {
}
}
write32(entry.service.getNameType());
//time is long, but we only use 4 bytes to store the data.
write32((int)(entry.timestamp.getTime()/1000));
// the key version might be a 32 bit extended number.
write8(entry.keyVersion % 256 );
write16(entry.keyType);
write16(entry.keyblock.length);
write(entry.keyblock);
// if the key version isn't smaller than 256, it could be saved as
// extension key version number in 4 bytes. The nonzero extension
// key version number will be trusted. However, it isn't standardized
// yet, we won't support it.
// if (entry.keyVersion >= 256) {
// write32(entry.keyVersion);
//}
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 2000, 2018, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.rcache;
import sun.security.krb5.internal.Krb5;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import sun.security.krb5.internal.KerberosTime;
import sun.security.krb5.internal.KrbApErrException;
/**
* This class provides an efficient caching mechanism to store AuthTimeWithHash
* from client authenticators. The cache minimizes the memory usage by doing
* self-cleanup of expired items in the cache.
*
* AuthTimeWithHash objects inside a cache are always sorted from big (new) to
* small (old) as determined by {@link AuthTimeWithHash#compareTo}. In the most
* common case a newcomer should be newer than the first element.
*
* @author Yanni Zhang
*/
public class AuthList {
private final LinkedList<AuthTimeWithHash> entries;
private final int lifespan;
// entries.getLast().ctime, updated after each cleanup.
private volatile int oldestTime = Integer.MIN_VALUE;
/**
* Constructs a AuthList.
*/
public AuthList(int lifespan) {
this.lifespan = lifespan;
entries = new LinkedList<>();
}
/**
* Puts the authenticator timestamp into the cache in descending order,
* and throw an exception if it's already there.
*/
public synchronized void put(AuthTimeWithHash t, KerberosTime currentTime)
throws KrbApErrException {
if (entries.isEmpty()) {
entries.addFirst(t);
oldestTime = t.ctime;
return;
} else {
AuthTimeWithHash temp = entries.getFirst();
int cmp = temp.compareTo(t);
if (cmp < 0) {
// This is the most common case, newly received authenticator
// has larger timestamp.
entries.addFirst(t);
} else if (cmp == 0) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
} else {
//unless client clock being re-adjusted.
ListIterator<AuthTimeWithHash> it = entries.listIterator(1);
boolean found = false;
while (it.hasNext()) {
temp = it.next();
cmp = temp.compareTo(t);
if (cmp < 0) {
// Find an older one, put in front of it
entries.add(entries.indexOf(temp), t);
found = true;
break;
} else if (cmp == 0) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
}
}
if (!found) {
// All is newer than the newcomer. Sigh.
entries.addLast(t);
}
}
}
// let us cleanup while we are here
long timeLimit = currentTime.getSeconds() - lifespan;
// Only trigger a cleanup when the earliest entry is
// lifespan + 5 sec ago. This ensures a cleanup is done
// at most every 5 seconds so that we don't always
// addLast(removeLast).
if (oldestTime > timeLimit - 5) {
return;
}
// and we remove the *enough* old ones (1 lifetime ago)
while (!entries.isEmpty()) {
AuthTimeWithHash removed = entries.removeLast();
if (removed.ctime >= timeLimit) {
entries.addLast(removed);
oldestTime = removed.ctime;
return;
}
}
oldestTime = Integer.MIN_VALUE;
}
public boolean isEmpty() {
return entries.isEmpty();
}
public String toString() {
StringBuilder sb = new StringBuilder();
Iterator<AuthTimeWithHash> iter = entries.descendingIterator();
int pos = entries.size();
while (iter.hasNext()) {
AuthTimeWithHash at = iter.next();
sb.append('#').append(pos--).append(": ")
.append(at.toString()).append('\n');
}
return sb.toString();
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/*
*
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
* Copyright 1997 The Open Group Research Institute. All rights reserved.
*/
package sun.security.krb5.internal.rcache;
import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.StandardCharsets;
import java.util.StringTokenizer;
/**
* The class represents an old style replay cache entry. It is only used in
* a dfl file.
*
* @author Sun/Oracle
* @author Yanni Zhang
*/
public class AuthTime {
final int ctime;
final int cusec;
final String client;
final String server;
/**
* Constructs an <code>AuthTime</code>.
*/
public AuthTime(String client, String server,
int ctime, int cusec) {
this.ctime = ctime;
this.cusec = cusec;
this.client = client;
this.server = server;
}
@Override
public String toString() {
return String.format("%d/%06d/----/%s", ctime, cusec, client);
}
// Methods used when saved in a dfl file. See DflCache.java
/**
* Reads an LC style string from a channel, which is a int32 length
* plus a UTF-8 encoded string possibly ends with \0.
* @throws IOException if there is a format error
* @throws BufferUnderflowException if goes beyond the end
*/
private static String readStringWithLength(SeekableByteChannel chan)
throws IOException {
ByteBuffer bb = ByteBuffer.allocate(4);
bb.order(ByteOrder.nativeOrder());
chan.read(bb);
bb.flip();
int len = bb.getInt();
if (len > 1024) {
// Memory attack? The string should be fairly short.
throw new IOException("Invalid string length");
}
bb = ByteBuffer.allocate(len);
if (chan.read(bb) != len) {
throw new IOException("Not enough string");
}
byte[] data = bb.array();
return (data[len-1] == 0)?
new String(data, 0, len-1, StandardCharsets.UTF_8):
new String(data, StandardCharsets.UTF_8);
}
/**
* Reads an AuthTime or AuthTimeWithHash object from a channel.
* @throws IOException if there is a format error
* @throws BufferUnderflowException if goes beyond the end
*/
public static AuthTime readFrom(SeekableByteChannel chan)
throws IOException {
String client = readStringWithLength(chan);
String server = readStringWithLength(chan);
ByteBuffer bb = ByteBuffer.allocate(8);
chan.read(bb);
bb.order(ByteOrder.nativeOrder());
int cusec = bb.getInt(0);
int ctime = bb.getInt(4);
if (client.isEmpty()) {
StringTokenizer st = new StringTokenizer(server, " :");
if (st.countTokens() != 6) {
throw new IOException("Incorrect rcache style");
}
String hashAlg = st.nextToken();
String hash = st.nextToken();
st.nextToken();
client = st.nextToken();
st.nextToken();
server = st.nextToken();
return new AuthTimeWithHash(
client, server, ctime, cusec, hashAlg, hash);
} else {
return new AuthTime(
client, server, ctime, cusec);
}
}
/**
* Encodes to be used in a dfl file
*/
protected byte[] encode0(String cstring, String sstring) {
byte[] c = cstring.getBytes(StandardCharsets.UTF_8);;
byte[] s = sstring.getBytes(StandardCharsets.UTF_8);;
byte[] zero = new byte[1];
int len = 4 + c.length + 1 + 4 + s.length + 1 + 4 + 4;
ByteBuffer bb = ByteBuffer.allocate(len)
.order(ByteOrder.nativeOrder());
bb.putInt(c.length+1).put(c).put(zero)
.putInt(s.length+1).put(s).put(zero)
.putInt(cusec).putInt(ctime);
return bb.array();
}
/**
* Encodes to be used in a dfl file
* @param withHash useless here
*/
public byte[] encode(boolean withHash) {
return encode0(client, server);
}
}

Some files were not shown because too many files have changed in this diff Show More