8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,41 @@
/*
* 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;
public class Asn1Exception extends KrbException {
private static final long serialVersionUID = 8291288984575084132L;
public Asn1Exception(int i) {
super(i);
}
}

View file

@ -0,0 +1,343 @@
/*
* 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;
import java.util.Arrays;
import sun.security.util.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* This class encapsulates the concept of a Kerberos checksum.
*/
public class Checksum {
private int cksumType;
private byte[] checksum;
// ----------------------------------------------+-------------+-----------
// Checksum type |sumtype |checksum
// |value | size
// ----------------------------------------------+-------------+-----------
public static final int CKSUMTYPE_NULL = 0; // 0
public static final int CKSUMTYPE_CRC32 = 1; // 4
public static final int CKSUMTYPE_RSA_MD4 = 2; // 16
public static final int CKSUMTYPE_RSA_MD4_DES = 3; // 24
public static final int CKSUMTYPE_DES_MAC = 4; // 16
public static final int CKSUMTYPE_DES_MAC_K = 5; // 8
public static final int CKSUMTYPE_RSA_MD4_DES_K = 6; // 16
public static final int CKSUMTYPE_RSA_MD5 = 7; // 16
public static final int CKSUMTYPE_RSA_MD5_DES = 8; // 24
// draft-ietf-krb-wg-crypto-07.txt
public static final int CKSUMTYPE_HMAC_SHA1_DES3_KD = 12; // 20
// draft-raeburn-krb-rijndael-krb-07.txt
public static final int CKSUMTYPE_HMAC_SHA1_96_AES128 = 15; // 96
public static final int CKSUMTYPE_HMAC_SHA1_96_AES256 = 16; // 96
// draft-brezak-win2k-krb-rc4-hmac-04.txt
public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;
static int CKSUMTYPE_DEFAULT;
static int SAFECKSUMTYPE_DEFAULT;
private static boolean DEBUG = Krb5.DEBUG;
static {
initStatic();
}
public static void initStatic() {
String temp = null;
Config cfg = null;
try {
cfg = Config.getInstance();
temp = cfg.get("libdefaults", "default_checksum");
if (temp != null)
{
CKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
/*
* If the default checksum is not
* specified in the configuration we
* set it to RSA_MD5. We follow the MIT and
* SEAM implementation.
*/
CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
}
} catch (Exception exc) {
if (DEBUG) {
System.out.println("Exception in getting default checksum "+
"value from the configuration " +
"Setting default checksum to be RSA-MD5");
exc.printStackTrace();
}
CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
}
try {
temp = cfg.get("libdefaults", "safe_checksum_type");
if (temp != null)
{
SAFECKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
}
} catch (Exception exc) {
if (DEBUG) {
System.out.println("Exception in getting safe default " +
"checksum value " +
"from the configuration Setting " +
"safe default checksum to be RSA-MD5");
exc.printStackTrace();
}
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
}
}
/**
* Constructs a new Checksum using the raw data and type.
* @param data the byte array of checksum.
* @param new_cksumType the type of checksum.
*
*/
// used in InitialToken
public Checksum(byte[] data, int new_cksumType) {
cksumType = new_cksumType;
checksum = data;
}
/**
* Constructs a new Checksum by calculating the checksum over the data
* using specified checksum type.
* @param new_cksumType the type of checksum.
* @param data the data that needs to be performed a checksum calculation on.
*/
public Checksum(int new_cksumType, byte[] data)
throws KdcErrException, KrbCryptoException {
cksumType = new_cksumType;
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe()) {
checksum = cksumEngine.calculateChecksum(data, data.length);
} else {
throw new KdcErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
}
}
/**
* Constructs a new Checksum by calculating the keyed checksum
* over the data using specified checksum type.
* @param new_cksumType the type of checksum.
* @param data the data that needs to be performed a checksum calculation on.
*/
// KrbSafe, KrbTgsReq
public Checksum(int new_cksumType, byte[] data,
EncryptionKey key, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
cksumType = new_cksumType;
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe())
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
checksum =
cksumEngine.calculateKeyedChecksum(data,
data.length,
key.getBytes(),
usage);
}
/**
* Verifies the keyed checksum over the data passed in.
*/
public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key,
int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe())
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
return cksumEngine.verifyKeyedChecksum(data,
data.length,
key.getBytes(),
checksum,
usage);
}
/*
public Checksum(byte[] data) throws KdcErrException, KrbCryptoException {
this(Checksum.CKSUMTYPE_DEFAULT, data);
}
*/
boolean isEqual(Checksum cksum) throws KdcErrException {
if (cksumType != cksum.cksumType)
return false;
CksumType cksumEngine = CksumType.getInstance(cksumType);
return CksumType.isChecksumEqual(checksum, cksum.checksum);
}
/**
* Constructs an instance of Checksum from an ASN.1 encoded representation.
* @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 Checksum(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) {
cksumType = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x01) {
checksum = 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 Checksum object.
* <pre>{@code
* Checksum ::= SEQUENCE {
* cksumtype [0] Int32,
* checksum [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>.
* @return byte array of enocded Checksum.
* @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(cksumType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte)0x00), temp);
temp = new DerOutputStream();
temp.putOctetString(checksum);
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 checksum 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 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 Checksum.
*
*/
public static Checksum 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 Checksum(subDer);
}
}
/**
* Returns the raw bytes of the checksum, not in ASN.1 encoded form.
*/
public final byte[] getBytes() {
return checksum;
}
public final int getType() {
return cksumType;
}
@Override public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Checksum)) {
return false;
}
try {
return isEqual((Checksum)obj);
} catch (KdcErrException kee) {
return false;
}
}
@Override public int hashCode() {
int result = 17;
result = 37 * result + cksumType;
if (checksum != null) {
result = 37 * result + Arrays.hashCode(checksum);
}
return result;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2001, 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;
import java.security.SecureRandom;
public final class Confounder {
private static SecureRandom srand = new SecureRandom();
private Confounder() { // not instantiable
}
public static byte[] bytes(int size) {
byte[] data = new byte[size];
srand.nextBytes(data);
return data;
}
public static int intValue() {
return srand.nextInt();
}
public static long longValue() {
return srand.nextLong();
}
}

View file

@ -0,0 +1,549 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.ccache.CredentialsCache;
import sun.security.krb5.internal.crypto.EType;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import java.net.InetAddress;
/**
* This class encapsulates the concept of a Kerberos service
* credential. That includes a Kerberos ticket and an associated
* session key.
*/
public class Credentials {
Ticket ticket;
PrincipalName client;
PrincipalName server;
EncryptionKey key;
TicketFlags flags;
KerberosTime authTime;
KerberosTime startTime;
KerberosTime endTime;
KerberosTime renewTill;
HostAddresses cAddr;
EncryptionKey serviceKey;
AuthorizationData authzData;
private static boolean DEBUG = Krb5.DEBUG;
private static CredentialsCache cache;
static boolean alreadyLoaded = false;
private static boolean alreadyTried = false;
// Read native ticket with session key type in the given list
private static native Credentials acquireDefaultNativeCreds(int[] eTypes);
public Credentials(Ticket new_ticket,
PrincipalName new_client,
PrincipalName new_server,
EncryptionKey new_key,
TicketFlags new_flags,
KerberosTime authTime,
KerberosTime new_startTime,
KerberosTime new_endTime,
KerberosTime renewTill,
HostAddresses cAddr,
AuthorizationData authzData) {
this(new_ticket, new_client, new_server, new_key, new_flags,
authTime, new_startTime, new_endTime, renewTill, cAddr);
this.authzData = authzData;
}
public Credentials(Ticket new_ticket,
PrincipalName new_client,
PrincipalName new_server,
EncryptionKey new_key,
TicketFlags new_flags,
KerberosTime authTime,
KerberosTime new_startTime,
KerberosTime new_endTime,
KerberosTime renewTill,
HostAddresses cAddr) {
ticket = new_ticket;
client = new_client;
server = new_server;
key = new_key;
flags = new_flags;
this.authTime = authTime;
startTime = new_startTime;
endTime = new_endTime;
this.renewTill = renewTill;
this.cAddr = cAddr;
}
public Credentials(byte[] encoding,
String client,
String server,
byte[] keyBytes,
int keyType,
boolean[] flags,
Date authTime,
Date startTime,
Date endTime,
Date renewTill,
InetAddress[] cAddrs) throws KrbException, IOException {
this(new Ticket(encoding),
new PrincipalName(client, PrincipalName.KRB_NT_PRINCIPAL),
new PrincipalName(server, PrincipalName.KRB_NT_SRV_INST),
new EncryptionKey(keyType, keyBytes),
(flags == null? null: new TicketFlags(flags)),
(authTime == null? null: new KerberosTime(authTime)),
(startTime == null? null: new KerberosTime(startTime)),
(endTime == null? null: new KerberosTime(endTime)),
(renewTill == null? null: new KerberosTime(renewTill)),
null); // caddrs are in the encoding at this point
}
/**
* Acquires a service ticket for the specified service
* principal. If the service ticket is not already available, it
* obtains a new one from the KDC.
*/
/*
public Credentials(Credentials tgt, PrincipalName service)
throws KrbException {
}
*/
public final PrincipalName getClient() {
return client;
}
public final PrincipalName getServer() {
return server;
}
public final EncryptionKey getSessionKey() {
return key;
}
public final Date getAuthTime() {
if (authTime != null) {
return authTime.toDate();
} else {
return null;
}
}
public final Date getStartTime() {
if (startTime != null)
{
return startTime.toDate();
}
return null;
}
public final Date getEndTime() {
if (endTime != null)
{
return endTime.toDate();
}
return null;
}
public final Date getRenewTill() {
if (renewTill != null)
{
return renewTill.toDate();
}
return null;
}
public final boolean[] getFlags() {
if (flags == null) // Can be in a KRB-CRED
return null;
return flags.toBooleanArray();
}
public final InetAddress[] getClientAddresses() {
if (cAddr == null)
return null;
return cAddr.getInetAddresses();
}
public final byte[] getEncoded() {
byte[] retVal = null;
try {
retVal = ticket.asn1Encode();
} catch (Asn1Exception e) {
if (DEBUG)
System.out.println(e);
} catch (IOException ioe) {
if (DEBUG)
System.out.println(ioe);
}
return retVal;
}
public boolean isForwardable() {
return flags.get(Krb5.TKT_OPTS_FORWARDABLE);
}
public boolean isRenewable() {
return flags.get(Krb5.TKT_OPTS_RENEWABLE);
}
public Ticket getTicket() {
return ticket;
}
public TicketFlags getTicketFlags() {
return flags;
}
public AuthorizationData getAuthzData() {
return authzData;
}
/**
* Checks if the service ticket returned by the KDC has the OK-AS-DELEGATE
* flag set
* @return true if OK-AS_DELEGATE flag is set, otherwise, return false.
*/
public boolean checkDelegate() {
return flags.get(Krb5.TKT_OPTS_DELEGATE);
}
/**
* Reset TKT_OPTS_DELEGATE to false, called at credentials acquirement
* when one of the cross-realm TGTs does not have the OK-AS-DELEGATE
* flag set. This info must be preservable and restorable through
* the Krb5Util.credsToTicket/ticketToCreds() methods so that even if
* the service ticket is cached it still remembers the cross-realm
* authentication result.
*/
public void resetDelegate() {
flags.set(Krb5.TKT_OPTS_DELEGATE, false);
}
public Credentials renew() throws KrbException, IOException {
KDCOptions options = new KDCOptions();
options.set(KDCOptions.RENEW, true);
/*
* Added here to pass KrbKdcRep.check:73
*/
options.set(KDCOptions.RENEWABLE, true);
return new KrbTgsReq(options,
this,
server,
null, // from
null, // till
null, // rtime
null, // eTypes
cAddr,
null,
null,
null).sendAndGetCreds();
}
/**
* Returns a TGT for the given client principal from a ticket cache.
*
* @param princ the client principal. A value of null means that the
* default principal name in the credentials cache will be used.
* @param ticketCache the path to the tickets file. A value
* of null will be accepted to indicate that the default
* path should be searched
* @return the TGT credentials or null if none were found. If the tgt
* expired, it is the responsibility of the caller to determine this.
*/
public static Credentials acquireTGTFromCache(PrincipalName princ,
String ticketCache)
throws KrbException, IOException {
if (ticketCache == null) {
// The default ticket cache on Windows and Mac is not a file.
String os = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("os.name"));
if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS") ||
os.toUpperCase(Locale.ENGLISH).contains("OS X")) {
Credentials creds = acquireDefaultCreds();
if (creds == null) {
if (DEBUG) {
System.out.println(">>> Found no TGT's in LSA");
}
return null;
}
if (princ != null) {
if (creds.getClient().equals(princ)) {
if (DEBUG) {
System.out.println(">>> Obtained TGT from LSA: "
+ creds);
}
return creds;
} else {
if (DEBUG) {
System.out.println(">>> LSA contains TGT for "
+ creds.getClient()
+ " not "
+ princ);
}
return null;
}
} else {
if (DEBUG) {
System.out.println(">>> Obtained TGT from LSA: "
+ creds);
}
return creds;
}
}
}
/*
* Returns the appropriate cache. If ticketCache is null, it is the
* default cache otherwise it is the cache filename contained in it.
*/
CredentialsCache ccache =
CredentialsCache.getInstance(princ, ticketCache);
if (ccache == null) {
return null;
}
sun.security.krb5.internal.ccache.Credentials tgtCred =
ccache.getDefaultCreds();
if (tgtCred == null) {
return null;
}
if (EType.isSupported(tgtCred.getEType())) {
return tgtCred.setKrbCreds();
} else {
if (DEBUG) {
System.out.println(
">>> unsupported key type found the default TGT: " +
tgtCred.getEType());
}
return null;
}
}
/**
* Acquires default credentials.
* <br>The possible locations for default credentials cache is searched in
* the following order:
* <ol>
* <li> The directory and cache file name specified by "KRB5CCNAME" system.
* property.
* <li> The directory and cache file name specified by "KRB5CCNAME"
* environment variable.
* <li> A cache file named krb5cc_{user.name} at {user.home} directory.
* </ol>
* @return a <code>KrbCreds</code> object if the credential is found,
* otherwise return null.
*/
// this method is intentionally changed to not check if the caller's
// principal name matches cache file's principal name.
// It assumes that the GSS call has
// the privilege to access the default cache file.
// This method is only called on Windows and Mac OS X, the native
// acquireDefaultNativeCreds is also available on these platforms.
public static synchronized Credentials acquireDefaultCreds() {
Credentials result = null;
if (cache == null) {
cache = CredentialsCache.getInstance();
}
if (cache != null) {
sun.security.krb5.internal.ccache.Credentials temp =
cache.getDefaultCreds();
if (temp != null) {
if (DEBUG) {
System.out.println(">>> KrbCreds found the default ticket"
+ " granting ticket in credential cache.");
}
if (EType.isSupported(temp.getEType())) {
result = temp.setKrbCreds();
} else {
if (DEBUG) {
System.out.println(
">>> unsupported key type found the default TGT: " +
temp.getEType());
}
}
}
}
if (result == null) {
// Doesn't seem to be a default cache on this system or
// TGT has unsupported encryption type
if (!alreadyTried) {
// See if there's any native code to load
try {
ensureLoaded();
} catch (Exception e) {
if (DEBUG) {
System.out.println("Can not load credentials cache");
e.printStackTrace();
}
alreadyTried = true;
}
}
if (alreadyLoaded) {
// There is some native code
if (DEBUG) {
System.out.println(">> Acquire default native Credentials");
}
try {
result = acquireDefaultNativeCreds(
EType.getDefaults("default_tkt_enctypes"));
} catch (KrbException ke) {
// when there is no default_tkt_enctypes.
}
}
}
return result;
}
/**
* 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 foreigh KDC.
*
* @param service the name of service principal using format
* components@realm
* @param ccreds client's initial credential.
* @exception IOException if an error occurs in reading the credentials
* cache
* @exception KrbException if an error occurs specific to Kerberos
* @return a <code>Credentials</code> object.
*/
public static Credentials acquireServiceCreds(String service,
Credentials ccreds)
throws KrbException, IOException {
return CredentialsUtil.acquireServiceCreds(service, ccreds);
}
public static Credentials acquireS4U2selfCreds(PrincipalName user,
Credentials ccreds) throws KrbException, IOException {
return CredentialsUtil.acquireS4U2selfCreds(user, ccreds);
}
public static Credentials acquireS4U2proxyCreds(String service,
Ticket second, PrincipalName client, Credentials ccreds)
throws KrbException, IOException {
return CredentialsUtil.acquireS4U2proxyCreds(
service, second, client, ccreds);
}
public CredentialsCache getCache() {
return cache;
}
public EncryptionKey getServiceKey() {
return serviceKey;
}
/*
* Prints out debug info.
*/
public static void printDebug(Credentials c) {
System.out.println(">>> DEBUG: ----Credentials----");
System.out.println("\tclient: " + c.client.toString());
System.out.println("\tserver: " + c.server.toString());
System.out.println("\tticket: sname: " + c.ticket.sname.toString());
if (c.startTime != null) {
System.out.println("\tstartTime: " + c.startTime.getTime());
}
System.out.println("\tendTime: " + c.endTime.getTime());
System.out.println(" ----Credentials end----");
}
static void ensureLoaded() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void> () {
public Void run() {
if (System.getProperty("os.name").contains("OS X")) {
System.loadLibrary("osxkrb5");
} else {
System.loadLibrary("w2k_lsa_auth");
}
return null;
}
});
alreadyLoaded = true;
}
public String toString() {
StringBuilder sb = new StringBuilder("Credentials:");
sb.append( "\n client=").append(client);
sb.append( "\n server=").append(server);
if (authTime != null) {
sb.append("\n authTime=").append(authTime);
}
if (startTime != null) {
sb.append("\n startTime=").append(startTime);
}
sb.append( "\n endTime=").append(endTime);
sb.append( "\n renewTill=").append(renewTill);
sb.append( "\n flags=").append(flags);
sb.append( "\nEType (skey)=").append(key.getEType());
sb.append( "\n (tkt key)=").append(ticket.encPart.eType);
return sb.toString();
}
public sun.security.krb5.internal.ccache.Credentials toCCacheCreds() {
return new sun.security.krb5.internal.ccache.Credentials(
getClient(), getServer(),
getSessionKey(),
date2kt(getAuthTime()),
date2kt(getStartTime()),
date2kt(getEndTime()),
date2kt(getRenewTill()),
false,
flags,
new HostAddresses(getClientAddresses()),
getAuthzData(),
getTicket(),
null);
}
private static KerberosTime date2kt(Date d) {
return d == null ? null : new KerberosTime(d);
}
}

View file

@ -0,0 +1,380 @@
/*
* 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;
import sun.security.util.*;
import sun.security.krb5.internal.crypto.*;
import sun.security.krb5.internal.*;
import java.io.IOException;
import java.math.BigInteger;
/**
* This class encapsulates Kerberos encrypted data. It allows
* callers access to both the ASN.1 encoded form of the EncryptedData
* type as well as the raw cipher text.
*/
public class EncryptedData implements Cloneable {
int eType;
Integer kvno; // optional
byte[] cipher;
byte[] plain; // not part of ASN.1 encoding
// ----------------+-----------+----------+----------------+---------------
// Encryption type |etype value|block size|minimum pad size|confounder size
// ----------------+-----------+----------+----------------+---------------
public static final int
ETYPE_NULL = 0; // 1 0 0
public static final int
ETYPE_DES_CBC_CRC = 1; // 8 4 8
public static final int
ETYPE_DES_CBC_MD4 = 2; // 8 0 8
public static final int
ETYPE_DES_CBC_MD5 = 3; // 8 0 8
// draft-brezak-win2k-krb-rc4-hmac-04.txt
public static final int
ETYPE_ARCFOUR_HMAC = 23; // 1
// NOTE: the exportable RC4-HMAC is not supported;
// it is no longer a usable encryption type
public static final int
ETYPE_ARCFOUR_HMAC_EXP = 24; // 1
// draft-ietf-krb-wg-crypto-07.txt
public static final int
ETYPE_DES3_CBC_HMAC_SHA1_KD = 16; // 8 0 8
// draft-raeburn-krb-rijndael-krb-07.txt
public static final int
ETYPE_AES128_CTS_HMAC_SHA1_96 = 17; // 16 0 16
public static final int
ETYPE_AES256_CTS_HMAC_SHA1_96 = 18; // 16 0 16
/* used by self */
private EncryptedData() {
}
public Object clone() {
EncryptedData new_encryptedData = new EncryptedData();
new_encryptedData.eType = eType;
if (kvno != null) {
new_encryptedData.kvno = kvno.intValue();
}
if (cipher != null) {
new_encryptedData.cipher = new byte[cipher.length];
System.arraycopy(cipher, 0, new_encryptedData.cipher,
0, cipher.length);
}
return new_encryptedData;
}
// Used in JSSE (com.sun.net.ssl.internal.KerberosPreMasterSecret)
public EncryptedData(
int new_eType,
Integer new_kvno,
byte[] new_cipher) {
eType = new_eType;
kvno = new_kvno;
cipher = new_cipher;
}
/*
// Not used.
public EncryptedData(
EncryptionKey key,
byte[] plaintext)
throws KdcErrException, KrbCryptoException {
EType etypeEngine = EType.getInstance(key.getEType());
cipher = etypeEngine.encrypt(plaintext, key.getBytes());
eType = key.getEType();
kvno = key.getKeyVersionNumber();
}
*/
// used in KrbApRep, KrbApReq, KrbAsReq, KrbCred, KrbPriv
// Used in JSSE (com.sun.net.ssl.internal.KerberosPreMasterSecret)
public EncryptedData(
EncryptionKey key,
byte[] plaintext,
int usage)
throws KdcErrException, KrbCryptoException {
EType etypeEngine = EType.getInstance(key.getEType());
cipher = etypeEngine.encrypt(plaintext, key.getBytes(), usage);
eType = key.getEType();
kvno = key.getKeyVersionNumber();
}
/*
// Not used.
public EncryptedData(
EncryptionKey key,
byte[] ivec,
byte[] plaintext)
throws KdcErrException, KrbCryptoException {
EType etypeEngine = EType.getInstance(key.getEType());
cipher = etypeEngine.encrypt(plaintext, key.getBytes(), ivec);
eType = key.getEType();
kvno = key.getKeyVersionNumber();
}
*/
/*
// Not used.
EncryptedData(
StringBuffer password,
byte[] plaintext)
throws KdcErrException, KrbCryptoException {
EncryptionKey key = new EncryptionKey(password);
EType etypeEngine = EType.getInstance(key.getEType());
cipher = etypeEngine.encrypt(plaintext, key.getBytes());
eType = key.getEType();
kvno = key.getKeyVersionNumber();
}
*/
public byte[] decrypt(
EncryptionKey key, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
if (eType != key.getEType()) {
throw new KrbCryptoException(
"EncryptedData is encrypted using keytype " +
EType.toString(eType) +
" but decryption key is of type " +
EType.toString(key.getEType()));
}
EType etypeEngine = EType.getInstance(eType);
plain = etypeEngine.decrypt(cipher, key.getBytes(), usage);
// The service ticket will be used in S4U2proxy request. Therefore
// the raw ticket is still needed.
//cipher = null;
return etypeEngine.decryptedData(plain);
}
/*
// currently destructive on cipher
// Not used.
public byte[] decrypt(
EncryptionKey key,
byte[] ivec, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
// XXX check for matching eType and kvno here
EType etypeEngine = EType.getInstance(eType);
plain = etypeEngine.decrypt(cipher, key.getBytes(), ivec, usage);
cipher = null;
return etypeEngine.decryptedData(plain);
}
// currently destructive on cipher
// Not used.
byte[] decrypt(StringBuffer password)
throws KdcErrException, KrbApErrException, KrbCryptoException {
EncryptionKey key = new EncryptionKey(password);
// XXX check for matching eType here
EType etypeEngine = EType.getInstance(eType);
plain = etypeEngine.decrypt(cipher, key.getBytes());
cipher = null;
return etypeEngine.decryptedData(plain);
}
*/
private byte[] decryptedData() throws KdcErrException {
if (plain != null) {
EType etypeEngine = EType.getInstance(eType);
return etypeEngine.decryptedData(plain);
}
return null;
}
/**
* Constructs an instance of EncryptedData type.
* @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.
*
*/
/* Used by self */
private EncryptedData(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() & (byte)0x1F) == (byte)0x00) {
eType = (der.getData().getBigInteger()).intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if ((encoding.getData().peekByte() & 0x1F) == 1) {
der = encoding.getData().getDerValue();
int i = (der.getData().getBigInteger()).intValue();
kvno = i;
} else {
kvno = null;
}
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x02) {
cipher = der.getData().getOctetString();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
if (encoding.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Returns an ASN.1 encoded EncryptedData type.
*
* <pre>{@code
* EncryptedData ::= SEQUENCE {
* etype [0] Int32 -- EncryptionType --,
* kvno [1] UInt32 OPTIONAL,
* cipher [2] OCTET STRING -- ciphertext
* }
* }</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>.
*
* @return byte array of encoded EncryptedData 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(this.eType));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte)0x00), temp);
temp = new DerOutputStream();
if (kvno != null) {
// encode as an unsigned integer (UInt32)
temp.putInteger(BigInteger.valueOf(this.kvno.longValue()));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte)0x01), temp);
temp = new DerOutputStream();
}
temp.putOctetString(this.cipher);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
(byte)0x02), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Parse (unmarshal) an EncryptedData 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
* @exception Asn1Exception if an error occurs while decoding an
* ASN1 encoded data.
* @exception IOException if an I/O error occurs while reading
* encoded data.
* @return an instance of EncryptedData.
*
*/
public static EncryptedData 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 EncryptedData(subDer);
}
}
/**
* Reset asn.1 data stream after decryption, remove redundant bytes.
* @param data the decrypted data from decrypt().
* @return the reset byte array which holds exactly one asn1 datum
* including its tag and length.
*
*/
public byte[] reset(byte[] data) {
byte[] bytes = null;
// for asn.1 encoded data, we use length field to
// determine the data length and remove redundant paddings.
if ((data[1] & 0xFF) < 128) {
bytes = new byte[data[1] + 2];
System.arraycopy(data, 0, bytes, 0, data[1] + 2);
} else {
if ((data[1] & 0xFF) > 128) {
int len = data[1] & (byte)0x7F;
int result = 0;
for (int i = 0; i < len; i++) {
result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1));
}
bytes = new byte[result + len + 2];
System.arraycopy(data, 0, bytes, 0, result + len + 2);
}
}
return bytes;
}
public int getEType() {
return eType;
}
public Integer getKeyVersionNumber() {
return kvno;
}
/**
* Returns the raw cipher text bytes, not in ASN.1 encoding.
*/
public byte[] getBytes() {
return cipher;
}
}

View file

@ -0,0 +1,583 @@
/*
* 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;
import sun.security.util.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import sun.security.krb5.internal.ktab.KeyTab;
import sun.security.krb5.internal.ccache.CCacheOutputStream;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
/**
* This class encapsulates the concept of an EncryptionKey. An encryption
* key is defined in RFC 4120 as:
*
* EncryptionKey ::= SEQUENCE {
* keytype [0] Int32 -- actually encryption type --,
* keyvalue [1] OCTET STRING
* }
*
* keytype
* This field specifies the encryption type of the encryption key
* that follows in the keyvalue field. Although its name is
* "keytype", it actually specifies an encryption type. Previously,
* multiple cryptosystems that performed encryption differently but
* were capable of using keys with the same characteristics were
* permitted to share an assigned number to designate the type of
* key; this usage is now deprecated.
*
* keyvalue
* This field contains the key itself, encoded as an octet string.
*/
public class EncryptionKey
implements Cloneable {
public static final EncryptionKey NULL_KEY =
new EncryptionKey(new byte[] {}, EncryptedData.ETYPE_NULL, null);
private int keyType;
private byte[] keyValue;
private Integer kvno; // not part of ASN1 encoding;
private static final boolean DEBUG = Krb5.DEBUG;
public synchronized int getEType() {
return keyType;
}
public final Integer getKeyVersionNumber() {
return kvno;
}
/**
* Returns the raw key bytes, not in any ASN.1 encoding.
*/
public final byte[] getBytes() {
// This method cannot be called outside sun.security, hence no
// cloning. getEncoded() calls this method.
return keyValue;
}
public synchronized Object clone() {
return new EncryptionKey(keyValue, keyType, kvno);
}
/**
* Obtains all versions of the secret key of the principal from a
* keytab.
*
* @param princ the principal whose secret key is desired
* @param keytab the path to the keytab file. A value of null
* will be accepted to indicate that the default path should be
* searched.
* @return an array of secret keys or null if none were found.
*/
public static EncryptionKey[] acquireSecretKeys(PrincipalName princ,
String keytab) {
if (princ == null)
throw new IllegalArgumentException(
"Cannot have null pricipal name to look in keytab.");
// KeyTab getInstance(keytab) will call KeyTab.getInstance()
// if keytab is null
KeyTab ktab = KeyTab.getInstance(keytab);
return ktab.readServiceKeys(princ);
}
/**
* Obtains a key for a given etype of a principal with possible new salt
* and s2kparams
* @param cname NOT null
* @param password NOT null
* @param etype
* @param snp can be NULL
* @return never null
*/
public static EncryptionKey acquireSecretKey(PrincipalName cname,
char[] password, int etype, PAData.SaltAndParams snp)
throws KrbException {
String salt;
byte[] s2kparams;
if (snp != null) {
salt = snp.salt != null ? snp.salt : cname.getSalt();
s2kparams = snp.params;
} else {
salt = cname.getSalt();
s2kparams = null;
}
return acquireSecretKey(password, salt, etype, s2kparams);
}
/**
* Obtains a key for a given etype with salt and optional s2kparams
* @param password NOT null
* @param salt NOT null
* @param etype
* @param s2kparams can be NULL
* @return never null
*/
public static EncryptionKey acquireSecretKey(char[] password,
String salt, int etype, byte[] s2kparams)
throws KrbException {
return new EncryptionKey(
stringToKey(password, salt, s2kparams, etype),
etype, null);
}
/**
* Generate a list of keys using the given principal and password.
* Construct a key for each configured etype.
* Caller is responsible for clearing password.
*/
/*
* Usually, when keyType is decoded from ASN.1 it will contain a
* value indicating what the algorithm to be used is. However, when
* converting from a password to a key for the AS-EXCHANGE, this
* keyType will not be available. Use builtin list of default etypes
* as the default in that case. If default_tkt_enctypes was set in
* the libdefaults of krb5.conf, then use that sequence.
*/
public static EncryptionKey[] acquireSecretKeys(char[] password,
String salt) throws KrbException {
int[] etypes = EType.getDefaults("default_tkt_enctypes");
EncryptionKey[] encKeys = new EncryptionKey[etypes.length];
for (int i = 0; i < etypes.length; i++) {
if (EType.isSupported(etypes[i])) {
encKeys[i] = new EncryptionKey(
stringToKey(password, salt, null, etypes[i]),
etypes[i], null);
} else {
if (DEBUG) {
System.out.println("Encryption Type " +
EType.toString(etypes[i]) +
" is not supported/enabled");
}
}
}
return encKeys;
}
// Used in Krb5AcceptCredential, self
public EncryptionKey(byte[] keyValue,
int keyType,
Integer kvno) {
if (keyValue != null) {
this.keyValue = new byte[keyValue.length];
System.arraycopy(keyValue, 0, this.keyValue, 0, keyValue.length);
} else {
throw new IllegalArgumentException("EncryptionKey: " +
"Key bytes cannot be null!");
}
this.keyType = keyType;
this.kvno = kvno;
}
/**
* Constructs an EncryptionKey by using the specified key type and key
* value. It is used to recover the key when retrieving data from
* credential cache file.
*
*/
// Used in JSSE (KerberosWrapper), Credentials,
// javax.security.auth.kerberos.KeyImpl
public EncryptionKey(int keyType,
byte[] keyValue) {
this(keyValue, keyType, null);
}
private static byte[] stringToKey(char[] password, String salt,
byte[] s2kparams, int keyType) throws KrbCryptoException {
char[] slt = salt.toCharArray();
char[] pwsalt = new char[password.length + slt.length];
System.arraycopy(password, 0, pwsalt, 0, password.length);
System.arraycopy(slt, 0, pwsalt, password.length, slt.length);
Arrays.fill(slt, '0');
try {
switch (keyType) {
case EncryptedData.ETYPE_DES_CBC_CRC:
case EncryptedData.ETYPE_DES_CBC_MD5:
return Des.string_to_key_bytes(pwsalt);
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
return Des3.stringToKey(pwsalt);
case EncryptedData.ETYPE_ARCFOUR_HMAC:
return ArcFourHmac.stringToKey(password);
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
return Aes128.stringToKey(password, salt, s2kparams);
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
return Aes256.stringToKey(password, salt, s2kparams);
default:
throw new IllegalArgumentException("encryption type " +
EType.toString(keyType) + " not supported");
}
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
} finally {
Arrays.fill(pwsalt, '0');
}
}
// Used in javax.security.auth.kerberos.KeyImpl
public EncryptionKey(char[] password,
String salt,
String algorithm) throws KrbCryptoException {
if (algorithm == null || algorithm.equalsIgnoreCase("DES")
|| algorithm.equalsIgnoreCase("des-cbc-md5")) {
keyType = EncryptedData.ETYPE_DES_CBC_MD5;
} else if (algorithm.equalsIgnoreCase("des-cbc-crc")) {
keyType = EncryptedData.ETYPE_DES_CBC_CRC;
} else if (algorithm.equalsIgnoreCase("DESede")
|| algorithm.equalsIgnoreCase("des3-cbc-sha1-kd")) {
keyType = EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD;
} else if (algorithm.equalsIgnoreCase("AES128")
|| algorithm.equalsIgnoreCase("aes128-cts-hmac-sha1-96")) {
keyType = EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96;
} else if (algorithm.equalsIgnoreCase("ArcFourHmac")
|| algorithm.equalsIgnoreCase("rc4-hmac")) {
keyType = EncryptedData.ETYPE_ARCFOUR_HMAC;
} else if (algorithm.equalsIgnoreCase("AES256")
|| algorithm.equalsIgnoreCase("aes256-cts-hmac-sha1-96")) {
keyType = EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96;
// validate if AES256 is enabled
if (!EType.isSupported(keyType)) {
throw new IllegalArgumentException("Algorithm " + algorithm +
" not enabled");
}
} else {
throw new IllegalArgumentException("Algorithm " + algorithm +
" not supported");
}
keyValue = stringToKey(password, salt, null, keyType);
kvno = null;
}
/**
* Generates a sub-sessionkey from a given session key.
*
* Used in AcceptSecContextToken and KrbApReq by acceptor- and initiator-
* side respectively.
*/
public EncryptionKey(EncryptionKey key) throws KrbCryptoException {
// generate random sub-session key
keyValue = Confounder.bytes(key.keyValue.length);
for (int i = 0; i < keyValue.length; i++) {
keyValue[i] ^= key.keyValue[i];
}
keyType = key.keyType;
// check for key parity and weak keys
try {
// check for DES key
if ((keyType == EncryptedData.ETYPE_DES_CBC_MD5) ||
(keyType == EncryptedData.ETYPE_DES_CBC_CRC)) {
// fix DES key parity
if (!DESKeySpec.isParityAdjusted(keyValue, 0)) {
keyValue = Des.set_parity(keyValue);
}
// check for weak key
if (DESKeySpec.isWeak(keyValue, 0)) {
keyValue[7] = (byte)(keyValue[7] ^ 0xF0);
}
}
// check for 3DES key
if (keyType == EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD) {
// fix 3DES key parity
if (!DESedeKeySpec.isParityAdjusted(keyValue, 0)) {
keyValue = Des3.parityFix(keyValue);
}
// check for weak keys
byte[] oneKey = new byte[8];
for (int i=0; i<keyValue.length; i+=8) {
System.arraycopy(keyValue, i, oneKey, 0, 8);
if (DESKeySpec.isWeak(oneKey, 0)) {
keyValue[i+7] = (byte)(keyValue[i+7] ^ 0xF0);
}
}
}
} catch (GeneralSecurityException e) {
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
ke.initCause(e);
throw ke;
}
}
/**
* Constructs an instance of EncryptionKey type.
* @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.
*
*
*/
// Used in javax.security.auth.kerberos.KeyImpl
public EncryptionKey(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) {
keyType = der.getData().getBigInteger().intValue();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x01) {
keyValue = der.getData().getOctetString();
}
else
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
if (der.getData().available() > 0) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Returns the ASN.1 encoding of this EncryptionKey.
*
* <pre>{@code
* EncryptionKey ::= SEQUENCE {
* keytype[0] INTEGER,
* keyvalue[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>.
*
* @return byte array of encoded EncryptionKey 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 synchronized byte[] asn1Encode() throws Asn1Exception, IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(keyType);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
(byte)0x00), temp);
temp = new DerOutputStream();
temp.putOctetString(keyValue);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
(byte)0x01), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
public synchronized void destroy() {
if (keyValue != null)
for (int i = 0; i < keyValue.length; i++)
keyValue[i] = 0;
}
/**
* Parse (unmarshal) an Encryption key 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
* @exception Asn1Exception if an error occurs while decoding an ASN1
* encoded data.
* @exception IOException if an I/O error occurs while reading encoded
* data.
* @return an instance of EncryptionKey.
*
*/
public static EncryptionKey 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 EncryptionKey(subDer);
}
}
/**
* Writes key value 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 synchronized void writeKey(CCacheOutputStream cos)
throws IOException {
cos.write16(keyType);
// we use KRB5_FCC_FVNO_3
cos.write16(keyType); // key type is recorded twice.
cos.write32(keyValue.length);
for (int i = 0; i < keyValue.length; i++) {
cos.write8(keyValue[i]);
}
}
public String toString() {
return new String("EncryptionKey: keyType=" + keyType
+ " kvno=" + kvno
+ " keyValue (hex dump)="
+ (keyValue == null || keyValue.length == 0 ?
" Empty Key" : '\n'
+ Krb5.hexDumper.encodeBuffer(keyValue)
+ '\n'));
}
/**
* Find a key with given etype
*/
public static EncryptionKey findKey(int etype, EncryptionKey[] keys)
throws KrbException {
return findKey(etype, null, keys);
}
/**
* Determines if a kvno matches another kvno. Used in the method
* findKey(type, kvno, keys). Always returns true if either input
* is null or zero, in case any side does not have kvno info available.
*
* Note: zero is included because N/A is not a legal value for kvno
* in javax.security.auth.kerberos.KerberosKey. Therefore, the info
* that the kvno is N/A might be lost when converting between this
* class and KerberosKey.
*/
private static boolean versionMatches(Integer v1, Integer v2) {
if (v1 == null || v1 == 0 || v2 == null || v2 == 0) {
return true;
}
return v1.equals(v2);
}
/**
* Find a key with given etype and kvno
* @param kvno if null, return any (first?) key
*/
public static EncryptionKey findKey(int etype, Integer kvno, EncryptionKey[] keys)
throws KrbException {
// check if encryption type is supported
if (!EType.isSupported(etype)) {
throw new KrbException("Encryption type " +
EType.toString(etype) + " is not supported/enabled");
}
int ktype;
boolean etypeFound = false;
// When no matched kvno is found, returns tke key of the same
// etype with the highest kvno
int kvno_found = 0;
EncryptionKey key_found = null;
for (int i = 0; i < keys.length; i++) {
ktype = keys[i].getEType();
if (EType.isSupported(ktype)) {
Integer kv = keys[i].getKeyVersionNumber();
if (etype == ktype) {
etypeFound = true;
if (versionMatches(kvno, kv)) {
return keys[i];
} else if (kv > kvno_found) {
// kv is not null
key_found = keys[i];
kvno_found = kv;
}
}
}
}
// Key not found.
// allow DES key to be used for the DES etypes
if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
etype == EncryptedData.ETYPE_DES_CBC_MD5)) {
for (int i = 0; i < keys.length; i++) {
ktype = keys[i].getEType();
if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
Integer kv = keys[i].getKeyVersionNumber();
etypeFound = true;
if (versionMatches(kvno, kv)) {
return new EncryptionKey(etype, keys[i].getBytes());
} else if (kv > kvno_found) {
key_found = new EncryptionKey(etype, keys[i].getBytes());
kvno_found = kv;
}
}
}
}
if (etypeFound) {
return key_found;
// For compatibility, will not fail here.
//throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
}
return null;
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2011, 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;
import javax.security.auth.kerberos.KeyTab;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.PrincipalName;
/**
* An unsafe tunnel to get non-public access to classes in the
* javax.security.auth.kerberos package.
*/
public interface JavaxSecurityAuthKerberosAccess {
/**
* Returns a snapshot to the backing keytab
*/
public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot(
KeyTab ktab);
}

View file

@ -0,0 +1,555 @@
/*
* Copyright (c) 2000, 2014, 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;
import java.security.PrivilegedAction;
import java.security.Security;
import java.util.Locale;
import sun.security.krb5.internal.Krb5;
import sun.security.krb5.internal.NetClient;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.StringTokenizer;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import sun.security.krb5.internal.KRBError;
/**
* KDC-REQ/KDC-REP communication. No more base class for KrbAsReq and
* KrbTgsReq. This class is now communication only.
*/
public final class KdcComm {
// The following settings can be configured in [libdefaults]
// section of krb5.conf, which are global for all realms. Each of
// them can also be defined in a realm, which overrides value here.
/**
* max retry time for a single KDC, default Krb5.KDC_RETRY_LIMIT (3)
*/
private static int defaultKdcRetryLimit;
/**
* timeout requesting a ticket from KDC, in millisec, default 30 sec
*/
private static int defaultKdcTimeout;
/**
* max UDP packet size, default unlimited (-1)
*/
private static int defaultUdpPrefLimit;
private static final boolean DEBUG = Krb5.DEBUG;
private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy";
/**
* What to do when a KDC is unavailable, specified in the
* java.security file with key krb5.kdc.bad.policy.
* Possible values can be TRY_LAST or TRY_LESS. Reloaded when refreshed.
*/
private enum BpType {
NONE, TRY_LAST, TRY_LESS
}
private static int tryLessMaxRetries = 1;
private static int tryLessTimeout = 5000;
private static BpType badPolicy;
static {
initStatic();
}
/**
* Read global settings
*/
public static void initStatic() {
String value = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(BAD_POLICY_KEY);
}
});
if (value != null) {
value = value.toLowerCase(Locale.ENGLISH);
String[] ss = value.split(":");
if ("tryless".equals(ss[0])) {
if (ss.length > 1) {
String[] params = ss[1].split(",");
try {
int tmp0 = Integer.parseInt(params[0]);
if (params.length > 1) {
tryLessTimeout = Integer.parseInt(params[1]);
}
// Assign here in case of exception at params[1]
tryLessMaxRetries = tmp0;
} catch (NumberFormatException nfe) {
// Ignored. Please note that tryLess is recognized and
// used, parameters using default values
if (DEBUG) {
System.out.println("Invalid " + BAD_POLICY_KEY +
" parameter for tryLess: " +
value + ", use default");
}
}
}
badPolicy = BpType.TRY_LESS;
} else if ("trylast".equals(ss[0])) {
badPolicy = BpType.TRY_LAST;
} else {
badPolicy = BpType.NONE;
}
} else {
badPolicy = BpType.NONE;
}
int timeout = -1;
int max_retries = -1;
int udp_pref_limit = -1;
try {
Config cfg = Config.getInstance();
String temp = cfg.get("libdefaults", "kdc_timeout");
timeout = parseTimeString(temp);
temp = cfg.get("libdefaults", "max_retries");
max_retries = parsePositiveIntString(temp);
temp = cfg.get("libdefaults", "udp_preference_limit");
udp_pref_limit = parsePositiveIntString(temp);
} catch (Exception exc) {
// ignore any exceptions; use default values
if (DEBUG) {
System.out.println ("Exception in getting KDC communication " +
"settings, using default value " +
exc.getMessage());
}
}
defaultKdcTimeout = timeout > 0 ? timeout : 30*1000; // 30 seconds
defaultKdcRetryLimit =
max_retries > 0 ? max_retries : Krb5.KDC_RETRY_LIMIT;
if (udp_pref_limit < 0) {
defaultUdpPrefLimit = Krb5.KDC_DEFAULT_UDP_PREF_LIMIT;
} else if (udp_pref_limit > Krb5.KDC_HARD_UDP_LIMIT) {
defaultUdpPrefLimit = Krb5.KDC_HARD_UDP_LIMIT;
} else {
defaultUdpPrefLimit = udp_pref_limit;
}
KdcAccessibility.reset();
}
/**
* The instance fields
*/
private String realm;
public KdcComm(String realm) throws KrbException {
if (realm == null) {
realm = Config.getInstance().getDefaultRealm();
if (realm == null) {
throw new KrbException(Krb5.KRB_ERR_GENERIC,
"Cannot find default realm");
}
}
this.realm = realm;
}
public byte[] send(byte[] obuf)
throws IOException, KrbException {
int udpPrefLimit = getRealmSpecificValue(
realm, "udp_preference_limit", defaultUdpPrefLimit);
boolean useTCP = (udpPrefLimit > 0 &&
(obuf != null && obuf.length > udpPrefLimit));
return send(obuf, useTCP);
}
private byte[] send(byte[] obuf, boolean useTCP)
throws IOException, KrbException {
if (obuf == null)
return null;
Config cfg = Config.getInstance();
if (realm == null) {
realm = cfg.getDefaultRealm();
if (realm == null) {
throw new KrbException(Krb5.KRB_ERR_GENERIC,
"Cannot find default realm");
}
}
String kdcList = cfg.getKDCList(realm);
if (kdcList == null) {
throw new KrbException("Cannot get kdc for realm " + realm);
}
// tempKdc may include the port number also
Iterator<String> tempKdc = KdcAccessibility.list(kdcList).iterator();
if (!tempKdc.hasNext()) {
throw new KrbException("Cannot get kdc for realm " + realm);
}
byte[] ibuf = null;
try {
ibuf = sendIfPossible(obuf, tempKdc.next(), useTCP);
} catch(Exception first) {
boolean ok = false;
while(tempKdc.hasNext()) {
try {
ibuf = sendIfPossible(obuf, tempKdc.next(), useTCP);
ok = true;
break;
} catch(Exception ignore) {}
}
if (!ok) throw first;
}
if (ibuf == null) {
throw new IOException("Cannot get a KDC reply");
}
return ibuf;
}
// send the AS Request to the specified KDC
// failover to using TCP if useTCP is not set and response is too big
private byte[] sendIfPossible(byte[] obuf, String tempKdc, boolean useTCP)
throws IOException, KrbException {
try {
byte[] ibuf = send(obuf, tempKdc, useTCP);
KRBError ke = null;
try {
ke = new KRBError(ibuf);
} catch (Exception e) {
// OK
}
if (ke != null && ke.getErrorCode() ==
Krb5.KRB_ERR_RESPONSE_TOO_BIG) {
ibuf = send(obuf, tempKdc, true);
}
KdcAccessibility.removeBad(tempKdc);
return ibuf;
} catch(Exception e) {
if (DEBUG) {
System.out.println(">>> KrbKdcReq send: error trying " +
tempKdc);
e.printStackTrace(System.out);
}
KdcAccessibility.addBad(tempKdc);
throw e;
}
}
// send the AS Request to the specified KDC
private byte[] send(byte[] obuf, String tempKdc, boolean useTCP)
throws IOException, KrbException {
if (obuf == null)
return null;
int port = Krb5.KDC_INET_DEFAULT_PORT;
int retries = getRealmSpecificValue(
realm, "max_retries", defaultKdcRetryLimit);
int timeout = getRealmSpecificValue(
realm, "kdc_timeout", defaultKdcTimeout);
if (badPolicy == BpType.TRY_LESS &&
KdcAccessibility.isBad(tempKdc)) {
if (retries > tryLessMaxRetries) {
retries = tryLessMaxRetries; // less retries
}
if (timeout > tryLessTimeout) {
timeout = tryLessTimeout; // less time
}
}
String kdc = null;
String portStr = null;
if (tempKdc.charAt(0) == '[') { // Explicit IPv6 in []
int pos = tempKdc.indexOf(']', 1);
if (pos == -1) {
throw new IOException("Illegal KDC: " + tempKdc);
}
kdc = tempKdc.substring(1, pos);
if (pos != tempKdc.length() - 1) { // with port number
if (tempKdc.charAt(pos+1) != ':') {
throw new IOException("Illegal KDC: " + tempKdc);
}
portStr = tempKdc.substring(pos+2);
}
} else {
int colon = tempKdc.indexOf(':');
if (colon == -1) { // Hostname or IPv4 host only
kdc = tempKdc;
} else {
int nextColon = tempKdc.indexOf(':', colon+1);
if (nextColon > 0) { // >=2 ":", IPv6 with no port
kdc = tempKdc;
} else { // 1 ":", hostname or IPv4 with port
kdc = tempKdc.substring(0, colon);
portStr = tempKdc.substring(colon+1);
}
}
}
if (portStr != null) {
int tempPort = parsePositiveIntString(portStr);
if (tempPort > 0)
port = tempPort;
}
if (DEBUG) {
System.out.println(">>> KrbKdcReq send: kdc=" + kdc
+ (useTCP ? " TCP:":" UDP:")
+ port + ", timeout="
+ timeout
+ ", number of retries ="
+ retries
+ ", #bytes=" + obuf.length);
}
KdcCommunication kdcCommunication =
new KdcCommunication(kdc, port, useTCP, timeout, retries, obuf);
try {
byte[] ibuf = AccessController.doPrivileged(kdcCommunication);
if (DEBUG) {
System.out.println(">>> KrbKdcReq send: #bytes read="
+ (ibuf != null ? ibuf.length : 0));
}
return ibuf;
} catch (PrivilegedActionException e) {
Exception wrappedException = e.getException();
if (wrappedException instanceof IOException) {
throw (IOException) wrappedException;
} else {
throw (KrbException) wrappedException;
}
}
}
private static class KdcCommunication
implements PrivilegedExceptionAction<byte[]> {
private String kdc;
private int port;
private boolean useTCP;
private int timeout;
private int retries;
private byte[] obuf;
public KdcCommunication(String kdc, int port, boolean useTCP,
int timeout, int retries, byte[] obuf) {
this.kdc = kdc;
this.port = port;
this.useTCP = useTCP;
this.timeout = timeout;
this.retries = retries;
this.obuf = obuf;
}
// The caller only casts IOException and KrbException so don't
// add any new ones!
public byte[] run() throws IOException, KrbException {
byte[] ibuf = null;
for (int i=1; i <= retries; i++) {
String proto = useTCP?"TCP":"UDP";
if (DEBUG) {
System.out.println(">>> KDCCommunication: kdc=" + kdc
+ " " + proto + ":"
+ port + ", timeout="
+ timeout
+ ",Attempt =" + i
+ ", #bytes=" + obuf.length);
}
try (NetClient kdcClient = NetClient.getInstance(
proto, kdc, port, timeout)) {
kdcClient.send(obuf);
ibuf = kdcClient.receive();
break;
} catch (SocketTimeoutException se) {
if (DEBUG) {
System.out.println ("SocketTimeOutException with " +
"attempt: " + i);
}
if (i == retries) {
ibuf = null;
throw se;
}
}
}
return ibuf;
}
}
/**
* Parses a time value string. If it ends with "s", parses as seconds.
* Otherwise, parses as milliseconds.
* @param s the time string
* @return the integer value in milliseconds, or -1 if input is null or
* has an invalid format
*/
private static int parseTimeString(String s) {
if (s == null) {
return -1;
}
if (s.endsWith("s")) {
int seconds = parsePositiveIntString(s.substring(0, s.length()-1));
return (seconds < 0) ? -1 : (seconds*1000);
} else {
return parsePositiveIntString(s);
}
}
/**
* Returns krb5.conf setting of {@code key} for a specific realm,
* which can be:
* 1. defined in the sub-stanza for the given realm inside [realms], or
* 2. defined in [libdefaults], or
* 3. defValue
* @param realm the given realm in which the setting is requested. Returns
* the global setting if null
* @param key the key for the setting
* @param defValue default value
* @return a value for the key
*/
private int getRealmSpecificValue(String realm, String key, int defValue) {
int v = defValue;
if (realm == null) return v;
int temp = -1;
try {
String value =
Config.getInstance().get("realms", realm, key);
if (key.equals("kdc_timeout")) {
temp = parseTimeString(value);
} else {
temp = parsePositiveIntString(value);
}
} catch (Exception exc) {
// Ignored, defValue will be picked up
}
if (temp > 0) v = temp;
return v;
}
private static int parsePositiveIntString(String intString) {
if (intString == null)
return -1;
int ret = -1;
try {
ret = Integer.parseInt(intString);
} catch (Exception exc) {
return -1;
}
if (ret >= 0)
return ret;
return -1;
}
/**
* Maintains a KDC accessible list. Unavailable KDCs are put into a
* blacklist, when a KDC in the blacklist is available, it's removed
* from there. No insertion order in the blacklist.
*
* There are two methods to deal with KDCs in the blacklist. 1. Only try
* them when there's no KDC not on the blacklist. 2. Still try them, but
* with lesser number of retries and smaller timeout value.
*/
static class KdcAccessibility {
// Known bad KDCs
private static Set<String> bads = new HashSet<>();
private static synchronized void addBad(String kdc) {
if (DEBUG) {
System.out.println(">>> KdcAccessibility: add " + kdc);
}
bads.add(kdc);
}
private static synchronized void removeBad(String kdc) {
if (DEBUG) {
System.out.println(">>> KdcAccessibility: remove " + kdc);
}
bads.remove(kdc);
}
private static synchronized boolean isBad(String kdc) {
return bads.contains(kdc);
}
private static synchronized void reset() {
if (DEBUG) {
System.out.println(">>> KdcAccessibility: reset");
}
bads.clear();
}
// Returns a preferred KDC list by putting the bad ones at the end
private static synchronized List<String> list(String kdcList) {
StringTokenizer st = new StringTokenizer(kdcList);
List<String> list = new ArrayList<>();
if (badPolicy == BpType.TRY_LAST) {
List<String> badkdcs = new ArrayList<>();
while (st.hasMoreTokens()) {
String t = st.nextToken();
if (bads.contains(t)) badkdcs.add(t);
else list.add(t);
}
// Bad KDCs are put at last
list.addAll(badkdcs);
} else {
// All KDCs are returned in their original order,
// This include TRY_LESS and NONE
while (st.hasMoreTokens()) {
list.add(st.nextToken());
}
}
return list;
}
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 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.
*/
package sun.security.krb5;
import javax.security.auth.kerberos.KeyTab;
import jdk.internal.misc.Unsafe;
public class KerberosSecrets {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static JavaxSecurityAuthKerberosAccess javaxSecurityAuthKerberosAccess;
public static void setJavaxSecurityAuthKerberosAccess
(JavaxSecurityAuthKerberosAccess jsaka) {
javaxSecurityAuthKerberosAccess = jsaka;
}
public static JavaxSecurityAuthKerberosAccess
getJavaxSecurityAuthKerberosAccess() {
if (javaxSecurityAuthKerberosAccess == null)
unsafe.ensureClassInitialized(KeyTab.class);
return javaxSecurityAuthKerberosAccess;
}
}

View file

@ -0,0 +1,198 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.util.*;
import java.io.IOException;
/**
* This class encapsulates a KRB-AP-REP sent from the service to the
* client.
*/
public class KrbApRep {
private byte[] obuf;
private byte[] ibuf;
private EncAPRepPart encPart; // although in plain text
private APRep apRepMessg;
/**
* Constructs a KRB-AP-REP to send to a client.
* @throws KrbException
* @throws IOException
*/
// Used in AcceptSecContextToken
public KrbApRep(KrbApReq incomingReq,
boolean useSeqNumber,
EncryptionKey subKey)
throws KrbException, IOException {
SeqNumber seqNum = new LocalSeqNumber();
init(incomingReq, subKey, seqNum);
}
/**
* Constructs a KRB-AP-REQ from the bytes received from a service.
* @throws KrbException
* @throws IOException
*/
// Used in AcceptSecContextToken
public KrbApRep(byte[] message, Credentials tgtCreds,
KrbApReq outgoingReq) throws KrbException, IOException {
this(message, tgtCreds);
authenticate(outgoingReq);
}
private void init(KrbApReq apReq,
EncryptionKey subKey,
SeqNumber seqNumber)
throws KrbException, IOException {
createMessage(
apReq.getCreds().key,
apReq.getCtime(),
apReq.cusec(),
subKey,
seqNumber);
obuf = apRepMessg.asn1Encode();
}
/**
* Constructs a KrbApRep object.
* @param msg a byte array of reply message.
* @param tgs_creds client's credential.
* @exception KrbException
* @exception IOException
*/
private KrbApRep(byte[] msg, Credentials tgs_creds)
throws KrbException, IOException {
this(new DerValue(msg), tgs_creds);
}
/**
* Constructs a KrbApRep object.
* @param msg a byte array of reply message.
* @param tgs_creds client's credential.
* @exception KrbException
* @exception IOException
*/
private KrbApRep(DerValue encoding, Credentials tgs_creds)
throws KrbException, IOException {
APRep rep = null;
try {
rep = new APRep(encoding);
} catch (Asn1Exception e) {
rep = null;
KRBError err = new KRBError(encoding);
String errStr = err.getErrorString();
String eText;
if (errStr.charAt(errStr.length() - 1) == 0)
eText = errStr.substring(0, errStr.length() - 1);
else
eText = errStr;
KrbException ke = new KrbException(err.getErrorCode(), eText);
ke.initCause(e);
throw ke;
}
byte[] temp = rep.encPart.decrypt(tgs_creds.key,
KeyUsage.KU_ENC_AP_REP_PART);
byte[] enc_ap_rep_part = rep.encPart.reset(temp);
encoding = new DerValue(enc_ap_rep_part);
encPart = new EncAPRepPart(encoding);
}
private void authenticate(KrbApReq apReq)
throws KrbException, IOException {
if (encPart.ctime.getSeconds() != apReq.getCtime().getSeconds() ||
encPart.cusec != apReq.getCtime().getMicroSeconds())
throw new KrbApErrException(Krb5.KRB_AP_ERR_MUT_FAIL);
}
/**
* Returns the optional subkey stored in
* this message. Returns null if none is stored.
*/
public EncryptionKey getSubKey() {
// XXX Can encPart be null
return encPart.getSubKey();
}
/**
* Returns the optional sequence number stored in the
* this message. Returns null if none is stored.
*/
public Integer getSeqNumber() {
// XXX Can encPart be null
return encPart.getSeqNumber();
}
/**
* Returns the ASN.1 encoding that should be sent to the peer.
*/
public byte[] getMessage() {
return obuf;
}
private void createMessage(
EncryptionKey key,
KerberosTime ctime,
int cusec,
EncryptionKey subKey,
SeqNumber seqNumber)
throws Asn1Exception, IOException,
KdcErrException, KrbCryptoException {
Integer seqno = null;
if (seqNumber != null)
seqno = seqNumber.current();
encPart = new EncAPRepPart(ctime,
cusec,
subKey,
seqno);
byte[] encPartEncoding = encPart.asn1Encode();
EncryptedData encEncPart = new EncryptedData(key, encPartEncoding,
KeyUsage.KU_ENC_AP_REP_PART);
apRepMessg = new APRep(encEncPart);
}
}

View file

@ -0,0 +1,515 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import sun.security.jgss.krb5.Krb5AcceptCredential;
import java.net.InetAddress;
import sun.security.util.*;
import java.io.IOException;
import java.util.Arrays;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.security.krb5.internal.rcache.AuthTimeWithHash;
/**
* This class encapsulates a KRB-AP-REQ that a client sends to a
* server for authentication.
*/
public class KrbApReq {
private byte[] obuf;
private KerberosTime ctime;
private int cusec;
private Authenticator authenticator;
private Credentials creds;
private APReq apReqMessg;
// Used by acceptor side
private static ReplayCache rcache = ReplayCache.getInstance();
private static boolean DEBUG = Krb5.DEBUG;
private static final char[] hexConst = "0123456789ABCDEF".toCharArray();
/**
* Constructs an AP-REQ message to send to the peer.
* @param tgsCred the <code>Credentials</code> to be used to construct the
* AP Request protocol message.
* @param mutualRequired Whether mutual authentication is required
* @param useSubkey Whether the subkey is to be used to protect this
* specific application session. If this is not set then the
* session key from the ticket will be used.
* @throws KrbException for any Kerberos protocol specific error
* @throws IOException for any IO related errors
* (e.g. socket operations)
*/
/*
// Not Used
public KrbApReq(Credentials tgsCred,
boolean mutualRequired,
boolean useSubKey,
boolean useSeqNumber) throws Asn1Exception,
KrbCryptoException, KrbException, IOException {
this(tgsCred, mutualRequired, useSubKey, useSeqNumber, null);
}
*/
/**
* Constructs an AP-REQ message to send to the peer.
* @param tgsCred the <code>Credentials</code> to be used to construct the
* AP Request protocol message.
* @param mutualRequired Whether mutual authentication is required
* @param useSubKey Whether the subkey is to be used to protect this
* specific application session. If this is not set then the
* session key from the ticket will be used.
* @param cksum checksum of the application data that accompanies
* the KRB_AP_REQ.
* @throws KrbException for any Kerberos protocol specific error
* @throws IOException for any IO related errors
* (e.g. socket operations)
*/
// Used in InitSecContextToken
public KrbApReq(Credentials tgsCred,
boolean mutualRequired,
boolean useSubKey,
boolean useSeqNumber,
Checksum cksum) throws Asn1Exception,
KrbCryptoException, KrbException, IOException {
APOptions apOptions = (mutualRequired?
new APOptions(Krb5.AP_OPTS_MUTUAL_REQUIRED):
new APOptions());
if (DEBUG)
System.out.println(">>> KrbApReq: APOptions are " + apOptions);
EncryptionKey subKey = (useSubKey?
new EncryptionKey(tgsCred.getSessionKey()):
null);
SeqNumber seqNum = new LocalSeqNumber();
init(apOptions,
tgsCred,
cksum,
subKey,
seqNum,
null, // AuthorizationData authzData
KeyUsage.KU_AP_REQ_AUTHENTICATOR);
}
/**
* Constructs an AP-REQ message from the bytes received from the
* peer.
* @param message The message received from the peer
* @param cred <code>KrbAcceptCredential</code> containing keys to decrypt
* the message; key selected will depend on etype used to encrypt data
* @throws KrbException for any Kerberos protocol specific error
* @throws IOException for any IO related errors
* (e.g. socket operations)
*/
// Used in InitSecContextToken (for AP_REQ and not TGS REQ)
public KrbApReq(byte[] message,
Krb5AcceptCredential cred,
InetAddress initiator)
throws KrbException, IOException {
obuf = message;
if (apReqMessg == null)
decode();
authenticate(cred, initiator);
}
/**
* Constructs an AP-REQ message from the bytes received from the
* peer.
* @param value The <code>DerValue</code> that contains the
* DER enoded AP-REQ protocol message
* @param keys <code>EncrtyptionKey</code>s to decrypt the message;
*
* @throws KrbException for any Kerberos protocol specific error
* @throws IOException for any IO related errors
* (e.g. socket operations)
*/
/*
public KrbApReq(DerValue value, EncryptionKey[] key, InetAddress initiator)
throws KrbException, IOException {
obuf = value.toByteArray();
if (apReqMessg == null)
decode(value);
authenticate(keys, initiator);
}
KrbApReq(APOptions options,
Credentials tgs_creds,
Checksum cksum,
EncryptionKey subKey,
SeqNumber seqNumber,
AuthorizationData authorizationData)
throws KrbException, IOException {
init(options, tgs_creds, cksum, subKey, seqNumber, authorizationData);
}
*/
/** used by KrbTgsReq **/
KrbApReq(APOptions apOptions,
Ticket ticket,
EncryptionKey key,
PrincipalName cname,
Checksum cksum,
KerberosTime ctime,
EncryptionKey subKey,
SeqNumber seqNumber,
AuthorizationData authorizationData)
throws Asn1Exception, IOException,
KdcErrException, KrbCryptoException {
init(apOptions, ticket, key, cname,
cksum, ctime, subKey, seqNumber, authorizationData,
KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR);
}
private void init(APOptions options,
Credentials tgs_creds,
Checksum cksum,
EncryptionKey subKey,
SeqNumber seqNumber,
AuthorizationData authorizationData,
int usage)
throws KrbException, IOException {
ctime = KerberosTime.now();
init(options,
tgs_creds.ticket,
tgs_creds.key,
tgs_creds.client,
cksum,
ctime,
subKey,
seqNumber,
authorizationData,
usage);
}
private void init(APOptions apOptions,
Ticket ticket,
EncryptionKey key,
PrincipalName cname,
Checksum cksum,
KerberosTime ctime,
EncryptionKey subKey,
SeqNumber seqNumber,
AuthorizationData authorizationData,
int usage)
throws Asn1Exception, IOException,
KdcErrException, KrbCryptoException {
createMessage(apOptions, ticket, key, cname,
cksum, ctime, subKey, seqNumber, authorizationData,
usage);
obuf = apReqMessg.asn1Encode();
}
void decode() throws KrbException, IOException {
DerValue encoding = new DerValue(obuf);
decode(encoding);
}
void decode(DerValue encoding) throws KrbException, IOException {
apReqMessg = null;
try {
apReqMessg = new APReq(encoding);
} catch (Asn1Exception e) {
apReqMessg = null;
KRBError err = new KRBError(encoding);
String errStr = err.getErrorString();
String eText;
if (errStr.charAt(errStr.length() - 1) == 0)
eText = errStr.substring(0, errStr.length() - 1);
else
eText = errStr;
KrbException ke = new KrbException(err.getErrorCode(), eText);
ke.initCause(e);
throw ke;
}
}
private void authenticate(Krb5AcceptCredential cred, InetAddress initiator)
throws KrbException, IOException {
int encPartKeyType = apReqMessg.ticket.encPart.getEType();
Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
EncryptionKey[] keys = cred.getKrb5EncryptionKeys(apReqMessg.ticket.sname);
EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);
if (dkey == null) {
throw new KrbException(Krb5.API_INVALID_ARG,
"Cannot find key of appropriate type to decrypt AP-REQ - " +
EType.toString(encPartKeyType));
}
byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey,
KeyUsage.KU_TICKET);
byte[] temp = apReqMessg.ticket.encPart.reset(bytes);
EncTicketPart enc_ticketPart = new EncTicketPart(temp);
checkPermittedEType(enc_ticketPart.key.getEType());
byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key,
KeyUsage.KU_AP_REQ_AUTHENTICATOR);
byte[] temp2 = apReqMessg.authenticator.reset(bytes2);
authenticator = new Authenticator(temp2);
ctime = authenticator.ctime;
cusec = authenticator.cusec;
authenticator.ctime =
authenticator.ctime.withMicroSeconds(authenticator.cusec);
if (!authenticator.cname.equals(enc_ticketPart.cname)) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);
}
if (!authenticator.ctime.inClockSkew())
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
String alg = AuthTimeWithHash.DEFAULT_HASH_ALG;
byte[] hash;
try {
hash = MessageDigest.getInstance(AuthTimeWithHash.realAlg(alg))
.digest(apReqMessg.authenticator.cipher);
} catch (NoSuchAlgorithmException ex) {
throw new AssertionError("Impossible " + alg);
}
char[] h = new char[hash.length * 2];
for (int i=0; i<hash.length; i++) {
h[2*i] = hexConst[(hash[i]&0xff)>>4];
h[2*i+1] = hexConst[hash[i]&0xf];
}
AuthTimeWithHash time = new AuthTimeWithHash(
authenticator.cname.toString(),
apReqMessg.ticket.sname.toString(),
authenticator.ctime.getSeconds(),
authenticator.cusec,
alg,
new String(h));
rcache.checkAndStore(KerberosTime.now(), time);
if (initiator != null) {
// sender host address
HostAddress sender = new HostAddress(initiator);
if (enc_ticketPart.caddr != null
&& !enc_ticketPart.caddr.inList(sender)) {
if (DEBUG) {
System.out.println(">>> KrbApReq: initiator is "
+ sender.getInetAddress()
+ ", but caddr is "
+ Arrays.toString(
enc_ticketPart.caddr.getInetAddresses()));
}
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
}
}
// XXX check for repeated authenticator
// if found
// throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
// else
// save authenticator to check for later
KerberosTime now = KerberosTime.now();
if ((enc_ticketPart.starttime != null &&
enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) ||
enc_ticketPart.flags.get(Krb5.TKT_OPTS_INVALID))
throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_NYV);
// if the current time is later than end time by more
// than the allowable clock skew, throws ticket expired exception.
if (enc_ticketPart.endtime != null &&
now.greaterThanWRTClockSkew(enc_ticketPart.endtime)) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_EXPIRED);
}
creds = new Credentials(
apReqMessg.ticket,
authenticator.cname,
apReqMessg.ticket.sname,
enc_ticketPart.key,
enc_ticketPart.flags,
enc_ticketPart.authtime,
enc_ticketPart.starttime,
enc_ticketPart.endtime,
enc_ticketPart.renewTill,
enc_ticketPart.caddr,
enc_ticketPart.authorizationData);
if (DEBUG) {
System.out.println(">>> KrbApReq: authenticate succeed.");
}
}
/**
* Returns the credentials that are contained in the ticket that
* is part of this AP-REQ.
*/
public Credentials getCreds() {
return creds;
}
KerberosTime getCtime() {
if (ctime != null)
return ctime;
return authenticator.ctime;
}
int cusec() {
return cusec;
}
APOptions getAPOptions() throws KrbException, IOException {
if (apReqMessg == null)
decode();
if (apReqMessg != null)
return apReqMessg.apOptions;
return null;
}
/**
* Returns true if mutual authentication is required and hence an
* AP-REP will need to be generated.
* @throws KrbException
* @throws IOException
*/
public boolean getMutualAuthRequired() throws KrbException, IOException {
if (apReqMessg == null)
decode();
if (apReqMessg != null)
return apReqMessg.apOptions.get(Krb5.AP_OPTS_MUTUAL_REQUIRED);
return false;
}
boolean useSessionKey() throws KrbException, IOException {
if (apReqMessg == null)
decode();
if (apReqMessg != null)
return apReqMessg.apOptions.get(Krb5.AP_OPTS_USE_SESSION_KEY);
return false;
}
/**
* Returns the optional subkey stored in the Authenticator for
* this message. Returns null if none is stored.
*/
public EncryptionKey getSubKey() {
// XXX Can authenticator be null
return authenticator.getSubKey();
}
/**
* Returns the optional sequence number stored in the
* Authenticator for this message. Returns null if none is
* stored.
*/
public Integer getSeqNumber() {
// XXX Can authenticator be null
return authenticator.getSeqNumber();
}
/**
* Returns the optional Checksum stored in the
* Authenticator for this message. Returns null if none is
* stored.
*/
public Checksum getChecksum() {
return authenticator.getChecksum();
}
/**
* Returns the ASN.1 encoding that should be sent to the peer.
*/
public byte[] getMessage() {
return obuf;
}
/**
* Returns the principal name of the client that generated this
* message.
*/
public PrincipalName getClient() {
return creds.getClient();
}
private void createMessage(APOptions apOptions,
Ticket ticket,
EncryptionKey key,
PrincipalName cname,
Checksum cksum,
KerberosTime ctime,
EncryptionKey subKey,
SeqNumber seqNumber,
AuthorizationData authorizationData,
int usage)
throws Asn1Exception, IOException,
KdcErrException, KrbCryptoException {
Integer seqno = null;
if (seqNumber != null)
seqno = seqNumber.current();
authenticator =
new Authenticator(cname,
cksum,
ctime.getMicroSeconds(),
ctime,
subKey,
seqno,
authorizationData);
byte[] temp = authenticator.asn1Encode();
EncryptedData encAuthenticator =
new EncryptedData(key, temp, usage);
apReqMessg =
new APReq(apOptions, ticket, encAuthenticator);
}
// Check that key is one of the permitted types
private static void checkPermittedEType(int target) throws KrbException {
int[] etypes = EType.getDefaults("permitted_enctypes");
if (!EType.isSupported(target, etypes)) {
throw new KrbException(EType.toString(target) +
" encryption type not in permitted_enctypes list");
}
}
}

View file

@ -0,0 +1,115 @@
/*
* 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;
import sun.security.krb5.internal.*;
abstract class KrbAppMessage {
private static boolean DEBUG = Krb5.DEBUG;
/**
* Common checks for KRB-PRIV and KRB-SAFE
*/
void check(KerberosTime packetTimestamp,
Integer packetUsec,
Integer packetSeqNumber,
HostAddress packetSAddress,
HostAddress packetRAddress,
SeqNumber seqNumber,
HostAddress sAddress,
HostAddress rAddress,
boolean timestampRequired,
boolean seqNumberRequired,
PrincipalName packetPrincipal)
throws KrbApErrException {
if (!Krb5.AP_EMPTY_ADDRESSES_ALLOWED || sAddress != null) {
if (packetSAddress == null || sAddress == null ||
!packetSAddress.equals(sAddress)) {
if (DEBUG && packetSAddress == null) {
System.out.println("packetSAddress is null");
}
if (DEBUG && sAddress == null) {
System.out.println("sAddress is null");
}
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
}
}
if (!Krb5.AP_EMPTY_ADDRESSES_ALLOWED || rAddress != null) {
if (packetRAddress == null || rAddress == null ||
!packetRAddress.equals(rAddress))
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
}
if (packetTimestamp != null) {
if (packetUsec != null) {
packetTimestamp =
packetTimestamp.withMicroSeconds(packetUsec.intValue());
}
if (!packetTimestamp.inClockSkew()) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
}
} else {
if (timestampRequired) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
}
}
// XXX check replay cache
// if (rcache.repeated(packetTimestamp, packetUsec, packetSAddress))
// throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
// XXX consider moving up to api level
if (seqNumber == null && seqNumberRequired == true)
throw new KrbApErrException(Krb5.API_INVALID_ARG);
if (packetSeqNumber != null && seqNumber != null) {
if (packetSeqNumber.intValue() != seqNumber.current())
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADORDER);
// should be done only when no more exceptions are possible
seqNumber.step();
} else {
if (seqNumberRequired) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADORDER);
}
}
// Must not be relaxed, per RFC 4120
if (packetTimestamp == null && packetSeqNumber == null)
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
// XXX check replay cache
// rcache.save_identifier(packetTimestamp, packetUsec, packetSAddress,
// packetPrincipal, pcaketRealm);
}
}

View file

@ -0,0 +1,184 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.krb5.internal.crypto.EType;
import sun.security.util.*;
import java.io.IOException;
import java.util.Objects;
import javax.security.auth.kerberos.KeyTab;
import sun.security.jgss.krb5.Krb5Util;
/**
* This class encapsulates a AS-REP message that the KDC sends to the
* client.
*/
class KrbAsRep extends KrbKdcRep {
private ASRep rep; // The AS-REP message
private Credentials creds; // The Credentials provide by the AS-REP
// message, created by initiator after calling
// the decrypt() method
private boolean DEBUG = Krb5.DEBUG;
KrbAsRep(byte[] ibuf) throws
KrbException, Asn1Exception, IOException {
DerValue encoding = new DerValue(ibuf);
try {
rep = new ASRep(encoding);
} catch (Asn1Exception e) {
rep = null;
KRBError err = new KRBError(encoding);
String errStr = err.getErrorString();
String eText = null; // pick up text sent by the server (if any)
if (errStr != null && errStr.length() > 0) {
if (errStr.charAt(errStr.length() - 1) == 0)
eText = errStr.substring(0, errStr.length() - 1);
else
eText = errStr;
}
KrbException ke;
if (eText == null) {
// no text sent from server
ke = new KrbException(err);
} else {
if (DEBUG) {
System.out.println("KRBError received: " + eText);
}
// override default text with server text
ke = new KrbException(err, eText);
}
ke.initCause(e);
throw ke;
}
}
// KrbAsReqBuilder need to read back the PA for key generation
PAData[] getPA() {
return rep.pAData;
}
/**
* Called by KrbAsReqBuilder to resolve a AS-REP message using a keytab.
* @param ktab the keytab, not null
* @param asReq the original AS-REQ sent, used to validate AS-REP
* @param cname the user principal name, used to locate keys in ktab
*/
void decryptUsingKeyTab(KeyTab ktab, KrbAsReq asReq, PrincipalName cname)
throws KrbException, Asn1Exception, IOException {
EncryptionKey dkey = null;
int encPartKeyType = rep.encPart.getEType();
Integer encPartKvno = rep.encPart.kvno;
try {
dkey = EncryptionKey.findKey(encPartKeyType, encPartKvno,
Krb5Util.keysFromJavaxKeyTab(ktab, cname));
} catch (KrbException ke) {
if (ke.returnCode() == Krb5.KRB_AP_ERR_BADKEYVER) {
// Fallback to no kvno. In some cases, keytab is generated
// not by sysadmin but Java's ktab command
dkey = EncryptionKey.findKey(encPartKeyType,
Krb5Util.keysFromJavaxKeyTab(ktab, cname));
}
}
if (dkey == null) {
throw new KrbException(Krb5.API_INVALID_ARG,
"Cannot find key for type/kvno to decrypt AS REP - " +
EType.toString(encPartKeyType) + "/" + encPartKvno);
}
decrypt(dkey, asReq);
}
/**
* Called by KrbAsReqBuilder to resolve a AS-REP message using a password.
* @param password user provided password. not null
* @param asReq the original AS-REQ sent, used to validate AS-REP
* @param cname the user principal name, used to provide salt
*/
void decryptUsingPassword(char[] password,
KrbAsReq asReq, PrincipalName cname)
throws KrbException, Asn1Exception, IOException {
int encPartKeyType = rep.encPart.getEType();
EncryptionKey dkey = EncryptionKey.acquireSecretKey(
cname,
password,
encPartKeyType,
PAData.getSaltAndParams(encPartKeyType, rep.pAData));
decrypt(dkey, asReq);
}
/**
* Decrypts encrypted content inside AS-REP. Called by initiator.
* @param dkey the decryption key to use
* @param asReq the original AS-REQ sent, used to validate AS-REP
*/
private void decrypt(EncryptionKey dkey, KrbAsReq asReq)
throws KrbException, Asn1Exception, IOException {
byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey,
KeyUsage.KU_ENC_AS_REP_PART);
byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes);
DerValue encoding = new DerValue(enc_as_rep_part);
EncASRepPart enc_part = new EncASRepPart(encoding);
rep.encKDCRepPart = enc_part;
ASReq req = asReq.getMessage();
check(true, req, rep);
creds = new Credentials(
rep.ticket,
req.reqBody.cname,
enc_part.sname,
enc_part.key,
enc_part.flags,
enc_part.authtime,
enc_part.starttime,
enc_part.endtime,
enc_part.renewTill,
enc_part.caddr);
if (DEBUG) {
System.out.println(">>> KrbAsRep cons in KrbAsReq.getReply " +
req.reqBody.cname.getNameString());
}
}
Credentials getCreds() {
return Objects.requireNonNull(creds, "Creds not available yet.");
}
sun.security.krb5.internal.ccache.Credentials getCCreds() {
return new sun.security.krb5.internal.ccache.Credentials(rep);
}
}

View file

@ -0,0 +1,167 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.Nonce;
import sun.security.krb5.internal.crypto.KeyUsage;
import java.io.IOException;
import java.time.Instant;
/**
* This class encapsulates the KRB-AS-REQ message that the client
* sends to the KDC.
*/
public class KrbAsReq {
private ASReq asReqMessg;
private boolean DEBUG = Krb5.DEBUG;
/**
* Constructs an AS-REQ message.
*/
// Can be null? has default?
public KrbAsReq(EncryptionKey pakey, // ok
KDCOptions options, // ok, new KDCOptions()
PrincipalName cname, // NO and must have realm
PrincipalName sname, // ok, krgtgt@CREALM
KerberosTime from, // ok
KerberosTime till, // ok, will use
KerberosTime rtime, // ok
int[] eTypes, // NO
HostAddresses addresses // ok
)
throws KrbException, IOException {
if (options == null) {
options = new KDCOptions();
}
// check if they are valid arguments. The optional fields should be
// consistent with settings in KDCOptions. Mar 17 2000
if (options.get(KDCOptions.FORWARDED) ||
options.get(KDCOptions.PROXY) ||
options.get(KDCOptions.ENC_TKT_IN_SKEY) ||
options.get(KDCOptions.RENEW) ||
options.get(KDCOptions.VALIDATE)) {
// this option is only specified in a request to the
// ticket-granting server
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
}
if (options.get(KDCOptions.POSTDATED)) {
// if (from == null)
// throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
} else {
if (from != null) from = null;
}
PAData[] paData = null;
if (pakey != null) {
PAEncTSEnc ts = new PAEncTSEnc();
byte[] temp = ts.asn1Encode();
EncryptedData encTs = new EncryptedData(pakey, temp,
KeyUsage.KU_PA_ENC_TS);
paData = new PAData[1];
paData[0] = new PAData( Krb5.PA_ENC_TIMESTAMP,
encTs.asn1Encode());
}
if (cname.getRealm() == null) {
throw new RealmException(Krb5.REALM_NULL,
"default realm not specified ");
}
if (DEBUG) {
System.out.println(">>> KrbAsReq creating message");
}
Config cfg = Config.getInstance();
// check to use addresses in tickets
if (addresses == null && cfg.useAddresses()) {
addresses = HostAddresses.getLocalAddresses();
}
if (sname == null) {
String realm = cname.getRealmAsString();
sname = PrincipalName.tgsService(realm, realm);
}
if (till == null) {
String d = cfg.get("libdefaults", "ticket_lifetime");
if (d != null) {
till = new KerberosTime(Instant.now().plusSeconds(Config.duration(d)));
} else {
till = new KerberosTime(0); // Choose KDC maximum allowed
}
}
if (rtime == null) {
String d = cfg.get("libdefaults", "renew_lifetime");
if (d != null) {
rtime = new KerberosTime(Instant.now().plusSeconds(Config.duration(d)));
}
}
if (rtime != null) {
options.set(KDCOptions.RENEWABLE, true);
if (till.greaterThan(rtime)) {
rtime = till;
}
}
// enc-authorization-data and additional-tickets never in AS-REQ
KDCReqBody kdc_req_body = new KDCReqBody(options,
cname,
sname,
from,
till,
rtime,
Nonce.value(),
eTypes,
addresses,
null,
null);
asReqMessg = new ASReq(
paData,
kdc_req_body);
}
byte[] encoding() throws IOException, Asn1Exception {
return asReqMessg.asn1Encode();
}
// Used by KrbAsRep to validate AS-REP
ASReq getMessage() {
return asReqMessg;
}
}

View file

@ -0,0 +1,411 @@
/*
* Copyright (c) 2010, 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.
*/
package sun.security.krb5;
import java.io.IOException;
import java.util.Arrays;
import javax.security.auth.kerberos.KeyTab;
import sun.security.jgss.krb5.Krb5Util;
import sun.security.krb5.internal.HostAddresses;
import sun.security.krb5.internal.KDCOptions;
import sun.security.krb5.internal.KRBError;
import sun.security.krb5.internal.KerberosTime;
import sun.security.krb5.internal.Krb5;
import sun.security.krb5.internal.PAData;
import sun.security.krb5.internal.crypto.EType;
/**
* A manager class for AS-REQ communications.
*
* This class does:
* 1. Gather information to create AS-REQ
* 2. Create and send AS-REQ
* 3. Receive AS-REP and KRB-ERROR (-KRB_ERR_RESPONSE_TOO_BIG) and parse them
* 4. Emit credentials and secret keys (for JAAS storeKey=true with password)
*
* This class does not:
* 1. Deal with real communications (KdcComm does it, and TGS-REQ)
* a. Name of KDCs for a realm
* b. Server availability, timeout, UDP or TCP
* d. KRB_ERR_RESPONSE_TOO_BIG
* 2. Stores its own copy of password, this means:
* a. Do not change/wipe it before Builder finish
* b. Builder will not wipe it for you
*
* With this class:
* 1. KrbAsReq has only one constructor
* 2. Krb5LoginModule and Kinit call a single builder
* 3. Better handling of sensitive info
*
* @since 1.7
*/
public final class KrbAsReqBuilder {
// Common data for AS-REQ fields
private KDCOptions options;
private PrincipalName cname;
private PrincipalName sname;
private KerberosTime from;
private KerberosTime till;
private KerberosTime rtime;
private HostAddresses addresses;
// Secret source: can't be changed once assigned, only one (of the two
// sources) can be set to non-null
private final char[] password;
private final KeyTab ktab;
// Used to create a ENC-TIMESTAMP in the 2nd AS-REQ
private PAData[] paList; // PA-DATA from both KRB-ERROR and AS-REP.
// Used by getKeys() only.
// Only AS-REP should be enough per RFC,
// combined in case etypes are different.
// The generated and received:
private KrbAsReq req;
private KrbAsRep rep;
private static enum State {
INIT, // Initialized, can still add more initialization info
REQ_OK, // AS-REQ performed
DESTROYED, // Destroyed, not usable anymore
}
private State state;
// Called by other constructors
private void init(PrincipalName cname)
throws KrbException {
this.cname = cname;
state = State.INIT;
}
/**
* Creates a builder to be used by {@code cname} with existing keys.
*
* @param cname the client of the AS-REQ. Must not be null. Might have no
* realm, where default realm will be used. This realm will be the target
* realm for AS-REQ. I believe a client should only get initial TGT from
* its own realm.
* @param ktab must not be null. If empty, might be quite useless.
* This argument will neither be modified nor stored by the method.
* @throws KrbException
*/
public KrbAsReqBuilder(PrincipalName cname, KeyTab ktab)
throws KrbException {
init(cname);
this.ktab = ktab;
this.password = null;
}
/**
* Creates a builder to be used by {@code cname} with a known password.
*
* @param cname the client of the AS-REQ. Must not be null. Might have no
* realm, where default realm will be used. This realm will be the target
* realm for AS-REQ. I believe a client should only get initial TGT from
* its own realm.
* @param pass must not be null. This argument will neither be modified
* nor stored by the method.
* @throws KrbException
*/
public KrbAsReqBuilder(PrincipalName cname, char[] pass)
throws KrbException {
init(cname);
this.password = pass.clone();
this.ktab = null;
}
/**
* Retrieves an array of secret keys for the client. This is used when
* the client supplies password but need keys to act as an acceptor. For
* an initiator, it must be called after AS-REQ is performed (state is OK).
* For an acceptor, it can be called when this KrbAsReqBuilder object is
* constructed (state is INIT).
* @param isInitiator if the caller is an initiator
* @return generated keys from password. PA-DATA from server might be used.
* All "default_tkt_enctypes" keys will be generated, Never null.
* @throws IllegalStateException if not constructed from a password
* @throws KrbException
*/
public EncryptionKey[] getKeys(boolean isInitiator) throws KrbException {
checkState(isInitiator?State.REQ_OK:State.INIT, "Cannot get keys");
if (password != null) {
int[] eTypes = EType.getDefaults("default_tkt_enctypes");
EncryptionKey[] result = new EncryptionKey[eTypes.length];
/*
* Returns an array of keys. Before KrbAsReqBuilder, all etypes
* use the same salt which is either the default one or a new salt
* coming from PA-DATA. After KrbAsReqBuilder, each etype uses its
* own new salt from PA-DATA. For an etype with no PA-DATA new salt
* at all, what salt should it use?
*
* Commonly, the stored keys are only to be used by an acceptor to
* decrypt service ticket in AP-REQ. Most impls only allow keys
* from a keytab on acceptor, but unfortunately (?) Java supports
* acceptor using password. In this case, if the service ticket is
* encrypted using an etype which we don't have PA-DATA new salt,
* using the default salt might be wrong (say, case-insensitive
* user name). Instead, we would use the new salt of another etype.
*/
String salt = null; // the saved new salt
try {
for (int i=0; i<eTypes.length; i++) {
// First round, only calculate those have a PA entry
PAData.SaltAndParams snp =
PAData.getSaltAndParams(eTypes[i], paList);
if (snp != null) {
// Never uses a salt for rc4-hmac, it does not use
// a salt at all
if (eTypes[i] != EncryptedData.ETYPE_ARCFOUR_HMAC &&
snp.salt != null) {
salt = snp.salt;
}
result[i] = EncryptionKey.acquireSecretKey(cname,
password,
eTypes[i],
snp);
}
}
// No new salt from PA, maybe empty, maybe only rc4-hmac
if (salt == null) salt = cname.getSalt();
for (int i=0; i<eTypes.length; i++) {
// Second round, calculate those with no PA entry
if (result[i] == null) {
result[i] = EncryptionKey.acquireSecretKey(password,
salt,
eTypes[i],
null);
}
}
} catch (IOException ioe) {
KrbException ke = new KrbException(Krb5.ASN1_PARSE_ERROR);
ke.initCause(ioe);
throw ke;
}
return result;
} else {
throw new IllegalStateException("Required password not provided");
}
}
/**
* Sets or clears options. If cleared, default options will be used
* at creation time.
* @param options
*/
public void setOptions(KDCOptions options) {
checkState(State.INIT, "Cannot specify options");
this.options = options;
}
public void setTill(KerberosTime till) {
checkState(State.INIT, "Cannot specify till");
this.till = till;
}
public void setRTime(KerberosTime rtime) {
checkState(State.INIT, "Cannot specify rtime");
this.rtime = rtime;
}
/**
* Sets or clears target. If cleared, KrbAsReq might choose krbtgt
* for cname realm
* @param sname
*/
public void setTarget(PrincipalName sname) {
checkState(State.INIT, "Cannot specify target");
this.sname = sname;
}
/**
* Adds or clears addresses. KrbAsReq might add some if empty
* field not allowed
* @param addresses
*/
public void setAddresses(HostAddresses addresses) {
checkState(State.INIT, "Cannot specify addresses");
this.addresses = addresses;
}
/**
* Build a KrbAsReq object from all info fed above. Normally this method
* will be called twice: initial AS-REQ and second with pakey
* @param key null (initial AS-REQ) or pakey (with preauth)
* @return the KrbAsReq object
* @throws KrbException
* @throws IOException
*/
private KrbAsReq build(EncryptionKey key) throws KrbException, IOException {
int[] eTypes;
if (password != null) {
eTypes = EType.getDefaults("default_tkt_enctypes");
} else {
EncryptionKey[] ks = Krb5Util.keysFromJavaxKeyTab(ktab, cname);
eTypes = EType.getDefaults("default_tkt_enctypes",
ks);
for (EncryptionKey k: ks) k.destroy();
}
return new KrbAsReq(key,
options,
cname,
sname,
from,
till,
rtime,
eTypes,
addresses);
}
/**
* Parses AS-REP, decrypts enc-part, retrieves ticket and session key
* @throws KrbException
* @throws Asn1Exception
* @throws IOException
*/
private KrbAsReqBuilder resolve()
throws KrbException, Asn1Exception, IOException {
if (ktab != null) {
rep.decryptUsingKeyTab(ktab, req, cname);
} else {
rep.decryptUsingPassword(password, req, cname);
}
if (rep.getPA() != null) {
if (paList == null || paList.length == 0) {
paList = rep.getPA();
} else {
int extraLen = rep.getPA().length;
if (extraLen > 0) {
int oldLen = paList.length;
paList = Arrays.copyOf(paList, paList.length + extraLen);
System.arraycopy(rep.getPA(), 0, paList, oldLen, extraLen);
}
}
}
return this;
}
/**
* Communication until AS-REP or non preauth-related KRB-ERROR received
* @throws KrbException
* @throws IOException
*/
private KrbAsReqBuilder send() throws KrbException, IOException {
boolean preAuthFailedOnce = false;
KdcComm comm = new KdcComm(cname.getRealmAsString());
EncryptionKey pakey = null;
while (true) {
try {
req = build(pakey);
rep = new KrbAsRep(comm.send(req.encoding()));
return this;
} catch (KrbException ke) {
if (!preAuthFailedOnce && (
ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED ||
ke.returnCode() == Krb5.KDC_ERR_PREAUTH_REQUIRED)) {
if (Krb5.DEBUG) {
System.out.println("KrbAsReqBuilder: " +
"PREAUTH FAILED/REQ, re-send AS-REQ");
}
preAuthFailedOnce = true;
KRBError kerr = ke.getError();
int paEType = PAData.getPreferredEType(kerr.getPA(),
EType.getDefaults("default_tkt_enctypes")[0]);
if (password == null) {
EncryptionKey[] ks = Krb5Util.keysFromJavaxKeyTab(ktab, cname);
pakey = EncryptionKey.findKey(paEType, ks);
if (pakey != null) pakey = (EncryptionKey)pakey.clone();
for (EncryptionKey k: ks) k.destroy();
} else {
pakey = EncryptionKey.acquireSecretKey(cname,
password,
paEType,
PAData.getSaltAndParams(
paEType, kerr.getPA()));
}
paList = kerr.getPA(); // Update current paList
} else {
throw ke;
}
}
}
}
/**
* Performs AS-REQ send and AS-REP receive.
* Maybe a state is needed here, to divide prepare process and getCreds.
* @throws KrbException
* @throws Asn1Exception
* @throws IOException
*/
public KrbAsReqBuilder action()
throws KrbException, Asn1Exception, IOException {
checkState(State.INIT, "Cannot call action");
state = State.REQ_OK;
return send().resolve();
}
/**
* Gets Credentials object after action
*/
public Credentials getCreds() {
checkState(State.REQ_OK, "Cannot retrieve creds");
return rep.getCreds();
}
/**
* Gets another type of Credentials after action
*/
public sun.security.krb5.internal.ccache.Credentials getCCreds() {
checkState(State.REQ_OK, "Cannot retrieve CCreds");
return rep.getCCreds();
}
/**
* Destroys the object and clears keys and password info.
*/
public void destroy() {
state = State.DESTROYED;
if (password != null) {
Arrays.fill(password, (char)0);
}
}
/**
* Checks if the current state is the specified one.
* @param st the expected state
* @param msg error message if state is not correct
* @throws IllegalStateException if state is not correct
*/
private void checkState(State st, String msg) {
if (state != st) {
throw new IllegalStateException(msg + " at " + st + " state");
}
}
}

View file

@ -0,0 +1,174 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.KeyUsage;
import java.io.IOException;
import sun.security.util.DerValue;
/**
* This class encapsulates the KRB-CRED message that a client uses to
* send its delegated credentials to a server.
*
* Supports delegation of one ticket only.
* @author Mayank Upadhyay
*/
public class KrbCred {
private static boolean DEBUG = Krb5.DEBUG;
private byte[] obuf = null;
private KRBCred credMessg = null;
private Ticket ticket = null;
private EncKrbCredPart encPart = null;
private Credentials creds = null;
private KerberosTime timeStamp = null;
// Used in InitialToken with null key
public KrbCred(Credentials tgt,
Credentials serviceTicket,
EncryptionKey key)
throws KrbException, IOException {
PrincipalName client = tgt.getClient();
PrincipalName tgService = tgt.getServer();
if (!serviceTicket.getClient().equals(client))
throw new KrbException(Krb5.KRB_ERR_GENERIC,
"Client principal does not match");
// XXX Check Windows flag OK-TO-FORWARD-TO
// Invoke TGS-REQ to get a forwarded TGT for the peer
KDCOptions options = new KDCOptions();
options.set(KDCOptions.FORWARDED, true);
options.set(KDCOptions.FORWARDABLE, true);
KrbTgsReq tgsReq = new KrbTgsReq(options, tgt, tgService,
null, null, null, null,
null, // No easy way to get addresses right
null, null, null);
credMessg = createMessage(tgsReq.sendAndGetCreds(), key);
obuf = credMessg.asn1Encode();
}
KRBCred createMessage(Credentials delegatedCreds, EncryptionKey key)
throws KrbException, IOException {
EncryptionKey sessionKey
= delegatedCreds.getSessionKey();
PrincipalName princ = delegatedCreds.getClient();
PrincipalName tgService = delegatedCreds.getServer();
KrbCredInfo credInfo = new KrbCredInfo(sessionKey,
princ, delegatedCreds.flags, delegatedCreds.authTime,
delegatedCreds.startTime, delegatedCreds.endTime,
delegatedCreds.renewTill, tgService,
delegatedCreds.cAddr);
timeStamp = KerberosTime.now();
KrbCredInfo[] credInfos = {credInfo};
EncKrbCredPart encPart =
new EncKrbCredPart(credInfos,
timeStamp, null, null, null, null);
EncryptedData encEncPart = new EncryptedData(key,
encPart.asn1Encode(), KeyUsage.KU_ENC_KRB_CRED_PART);
Ticket[] tickets = {delegatedCreds.ticket};
credMessg = new KRBCred(tickets, encEncPart);
return credMessg;
}
// Used in InitialToken, NULL_KEY might be used
public KrbCred(byte[] asn1Message, EncryptionKey key)
throws KrbException, IOException {
credMessg = new KRBCred(asn1Message);
ticket = credMessg.tickets[0];
if (credMessg.encPart.getEType() == 0) {
key = EncryptionKey.NULL_KEY;
}
byte[] temp = credMessg.encPart.decrypt(key,
KeyUsage.KU_ENC_KRB_CRED_PART);
byte[] plainText = credMessg.encPart.reset(temp);
DerValue encoding = new DerValue(plainText);
EncKrbCredPart encPart = new EncKrbCredPart(encoding);
timeStamp = encPart.timeStamp;
KrbCredInfo credInfo = encPart.ticketInfo[0];
EncryptionKey credInfoKey = credInfo.key;
PrincipalName pname = credInfo.pname;
TicketFlags flags = credInfo.flags;
KerberosTime authtime = credInfo.authtime;
KerberosTime starttime = credInfo.starttime;
KerberosTime endtime = credInfo.endtime;
KerberosTime renewTill = credInfo.renewTill;
PrincipalName sname = credInfo.sname;
HostAddresses caddr = credInfo.caddr;
if (DEBUG) {
System.out.println(">>>Delegated Creds have pname=" + pname
+ " sname=" + sname
+ " authtime=" + authtime
+ " starttime=" + starttime
+ " endtime=" + endtime
+ "renewTill=" + renewTill);
}
creds = new Credentials(ticket, pname, sname, credInfoKey,
flags, authtime, starttime, endtime, renewTill, caddr);
}
/**
* Returns the delegated credentials from the peer.
*/
public Credentials[] getDelegatedCreds() {
Credentials[] allCreds = {creds};
return allCreds;
}
/**
* Returns the ASN.1 encoding that should be sent to the peer.
*/
public byte[] getMessage() {
return obuf;
}
}

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;
/**
* KrbCryptoExceptoin is a wrapper exception for exceptions thrown by JCE.
*
* @author Yanni Zhang
*/
public class KrbCryptoException extends KrbException {
private static final long serialVersionUID = -1657367919979982250L;
public KrbCryptoException (String s) {
super(s);
}
}

View file

@ -0,0 +1,160 @@
/*
* 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;
import sun.security.krb5.internal.Krb5;
import sun.security.krb5.internal.KRBError;
public class KrbException extends Exception {
private static final long serialVersionUID = -4993302876451928596L;
private int returnCode;
private KRBError error;
public KrbException(String s) {
super(s);
}
public KrbException(Throwable cause) {
super(cause);
}
public KrbException(int i) {
returnCode = i;
}
public KrbException(int i, String s) {
this(s);
returnCode = i;
}
public KrbException(KRBError e) {
returnCode = e.getErrorCode();
error = e;
}
public KrbException(KRBError e, String s) {
this(s);
returnCode = e.getErrorCode();
error = e;
}
public KRBError getError() {
return error;
}
public int returnCode() {
return returnCode;
}
public String returnCodeSymbol() {
return returnCodeSymbol(returnCode);
}
public static String returnCodeSymbol(int i) {
return "not yet implemented";
}
public String returnCodeMessage() {
return Krb5.getErrorMessage(returnCode);
}
public static String errorMessage(int i) {
return Krb5.getErrorMessage(i);
}
public String krbErrorMessage() {
StringBuilder sb = new StringBuilder();
sb.append("krb_error ").append(returnCode);
String msg = getMessage();
if (msg != null) {
sb.append(" ");
sb.append(msg);
}
return sb.toString();
}
/**
* Returns messages like:
* "Integrity check on decrypted field failed (31) - \
* Could not decrypt service ticket"
* If the error code is 0 then the first half is skipped.
*/
public String getMessage() {
StringBuilder message = new StringBuilder();
int returnCode = returnCode();
if (returnCode != 0) {
message.append(returnCodeMessage());
message.append(" (").append(returnCode()).append(')');
}
String consMessage = super.getMessage();
if (consMessage != null && consMessage.length() != 0) {
if (returnCode != 0)
message.append(" - ");
message.append(consMessage);
}
return message.toString();
}
public String toString() {
return ("KrbException: " + getMessage());
}
@Override public int hashCode() {
int result = 17;
result = 37 * result + returnCode;
if (error != null) {
result = 37 * result + error.hashCode();
}
return result;
}
@Override public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof KrbException)) {
return false;
}
KrbException other = (KrbException)obj;
if (returnCode != other.returnCode) {
return false;
}
return (error == null)?(other.error == null):
(error.equals(other.error));
}
}

View file

@ -0,0 +1,122 @@
/*
* 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;
import sun.security.krb5.internal.*;
abstract class KrbKdcRep {
static void check(
boolean isAsReq,
KDCReq req,
KDCRep rep
) throws KrbApErrException {
if (isAsReq && !req.reqBody.cname.equals(rep.cname)) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
if (!req.reqBody.sname.equals(rep.encKDCRepPart.sname)) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
if (req.reqBody.getNonce() != rep.encKDCRepPart.nonce) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
if (
((req.reqBody.addresses != null && rep.encKDCRepPart.caddr != null) &&
!req.reqBody.addresses.equals(rep.encKDCRepPart.caddr))) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
// We allow KDC to return a non-forwardable ticket if request has -f
for (int i = 2; i < 6; i++) {
if (req.reqBody.kdcOptions.get(i) !=
rep.encKDCRepPart.flags.get(i)) {
if (Krb5.DEBUG) {
System.out.println("> KrbKdcRep.check: at #" + i
+ ". request for " + req.reqBody.kdcOptions.get(i)
+ ", received " + rep.encKDCRepPart.flags.get(i));
}
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
}
// Reply to a renewable request should be renewable, but if request does
// not contain renewable, KDC is free to issue a renewable ticket (for
// example, if ticket_lifetime is too big).
if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) &&
!rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
if ((req.reqBody.from == null) || req.reqBody.from.isZero()) {
// verify this is allowed
if ((rep.encKDCRepPart.starttime != null) &&
!rep.encKDCRepPart.starttime.inClockSkew()) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
}
}
if ((req.reqBody.from != null) && !req.reqBody.from.isZero()) {
// verify this is allowed
if ((rep.encKDCRepPart.starttime != null) &&
!req.reqBody.from.equals(rep.encKDCRepPart.starttime)) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
}
if (!req.reqBody.till.isZero() &&
rep.encKDCRepPart.endtime.greaterThan(req.reqBody.till)) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE)) {
if (req.reqBody.rtime != null && !req.reqBody.rtime.isZero()) {
// verify this is required
if ((rep.encKDCRepPart.renewTill == null) ||
rep.encKDCRepPart.renewTill.greaterThan(req.reqBody.rtime)
) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
}
}
}
}

View file

@ -0,0 +1,178 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import sun.security.util.*;
import java.io.IOException;
/** XXX This class does not appear to be used. **/
class KrbPriv extends KrbAppMessage {
private byte[] obuf;
private byte[] userData;
private KrbPriv(byte[] userData,
Credentials creds,
EncryptionKey subKey,
KerberosTime timestamp,
SeqNumber seqNumber,
HostAddress saddr,
HostAddress raddr
) throws KrbException, IOException {
EncryptionKey reqKey = null;
if (subKey != null)
reqKey = subKey;
else
reqKey = creds.key;
obuf = mk_priv(
userData,
reqKey,
timestamp,
seqNumber,
saddr,
raddr
);
}
private KrbPriv(byte[] msg,
Credentials creds,
EncryptionKey subKey,
SeqNumber seqNumber,
HostAddress saddr,
HostAddress raddr,
boolean timestampRequired,
boolean seqNumberRequired
) throws KrbException, IOException {
KRBPriv krb_priv = new KRBPriv(msg);
EncryptionKey reqKey = null;
if (subKey != null)
reqKey = subKey;
else
reqKey = creds.key;
userData = rd_priv(krb_priv,
reqKey,
seqNumber,
saddr,
raddr,
timestampRequired,
seqNumberRequired,
creds.client
);
}
public byte[] getMessage() throws KrbException {
return obuf;
}
public byte[] getData() {
return userData;
}
private byte[] mk_priv(byte[] userData,
EncryptionKey key,
KerberosTime timestamp,
SeqNumber seqNumber,
HostAddress sAddress,
HostAddress rAddress
) throws Asn1Exception, IOException,
KdcErrException, KrbCryptoException {
Integer usec = null;
Integer seqno = null;
if (timestamp != null)
usec = timestamp.getMicroSeconds();
if (seqNumber != null) {
seqno = seqNumber.current();
seqNumber.step();
}
EncKrbPrivPart unenc_encKrbPrivPart =
new EncKrbPrivPart(userData,
timestamp,
usec,
seqno,
sAddress,
rAddress
);
byte[] temp = unenc_encKrbPrivPart.asn1Encode();
EncryptedData encKrbPrivPart =
new EncryptedData(key, temp,
KeyUsage.KU_ENC_KRB_PRIV_PART);
KRBPriv krb_priv = new KRBPriv(encKrbPrivPart);
temp = krb_priv.asn1Encode();
return krb_priv.asn1Encode();
}
private byte[] rd_priv(KRBPriv krb_priv,
EncryptionKey key,
SeqNumber seqNumber,
HostAddress sAddress,
HostAddress rAddress,
boolean timestampRequired,
boolean seqNumberRequired,
PrincipalName cname
) throws Asn1Exception, KdcErrException,
KrbApErrException, IOException, KrbCryptoException {
byte[] bytes = krb_priv.encPart.decrypt(key,
KeyUsage.KU_ENC_KRB_PRIV_PART);
byte[] temp = krb_priv.encPart.reset(bytes);
DerValue ref = new DerValue(temp);
EncKrbPrivPart enc_part = new EncKrbPrivPart(ref);
check(enc_part.timestamp,
enc_part.usec,
enc_part.seqNumber,
enc_part.sAddress,
enc_part.rAddress,
seqNumber,
sAddress,
rAddress,
timestampRequired,
seqNumberRequired,
cname
);
return enc_part.userData;
}
}

View file

@ -0,0 +1,183 @@
/*
* 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;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.io.IOException;
class KrbSafe extends KrbAppMessage {
private byte[] obuf;
private byte[] userData;
public KrbSafe(byte[] userData,
Credentials creds,
EncryptionKey subKey,
KerberosTime timestamp,
SeqNumber seqNumber,
HostAddress saddr,
HostAddress raddr
) throws KrbException, IOException {
EncryptionKey reqKey = null;
if (subKey != null)
reqKey = subKey;
else
reqKey = creds.key;
obuf = mk_safe(userData,
reqKey,
timestamp,
seqNumber,
saddr,
raddr
);
}
public KrbSafe(byte[] msg,
Credentials creds,
EncryptionKey subKey,
SeqNumber seqNumber,
HostAddress saddr,
HostAddress raddr,
boolean timestampRequired,
boolean seqNumberRequired
) throws KrbException, IOException {
KRBSafe krb_safe = new KRBSafe(msg);
EncryptionKey reqKey = null;
if (subKey != null)
reqKey = subKey;
else
reqKey = creds.key;
userData = rd_safe(
krb_safe,
reqKey,
seqNumber,
saddr,
raddr,
timestampRequired,
seqNumberRequired,
creds.client
);
}
public byte[] getMessage() {
return obuf;
}
public byte[] getData() {
return userData;
}
private byte[] mk_safe(byte[] userData,
EncryptionKey key,
KerberosTime timestamp,
SeqNumber seqNumber,
HostAddress sAddress,
HostAddress rAddress
) throws Asn1Exception, IOException, KdcErrException,
KrbApErrException, KrbCryptoException {
Integer usec = null;
Integer seqno = null;
if (timestamp != null)
usec = timestamp.getMicroSeconds();
if (seqNumber != null) {
seqno = seqNumber.current();
seqNumber.step();
}
KRBSafeBody krb_safeBody =
new KRBSafeBody(userData,
timestamp,
usec,
seqno,
sAddress,
rAddress
);
byte[] temp = krb_safeBody.asn1Encode();
Checksum cksum = new Checksum(
Checksum.SAFECKSUMTYPE_DEFAULT,
temp,
key,
KeyUsage.KU_KRB_SAFE_CKSUM
);
KRBSafe krb_safe = new KRBSafe(krb_safeBody, cksum);
temp = krb_safe.asn1Encode();
return krb_safe.asn1Encode();
}
private byte[] rd_safe(KRBSafe krb_safe,
EncryptionKey key,
SeqNumber seqNumber,
HostAddress sAddress,
HostAddress rAddress,
boolean timestampRequired,
boolean seqNumberRequired,
PrincipalName cname
) throws Asn1Exception, KdcErrException,
KrbApErrException, IOException, KrbCryptoException {
byte[] temp = krb_safe.safeBody.asn1Encode();
if (!krb_safe.cksum.verifyKeyedChecksum(temp, key,
KeyUsage.KU_KRB_SAFE_CKSUM)) {
throw new KrbApErrException(
Krb5.KRB_AP_ERR_MODIFIED);
}
check(krb_safe.safeBody.timestamp,
krb_safe.safeBody.usec,
krb_safe.safeBody.seqNumber,
krb_safe.safeBody.sAddress,
krb_safe.safeBody.rAddress,
seqNumber,
sAddress,
rAddress,
timestampRequired,
seqNumberRequired,
cname
);
return krb_safe.safeBody.userData;
}
}

View file

@ -0,0 +1,338 @@
/*
* Copyright (c) 2006, 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.
*/
package sun.security.krb5;
import sun.security.krb5.internal.Krb5;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Random;
import java.util.StringTokenizer;
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.NamingManager;
/**
* This class discovers the location of Kerberos services by querying DNS,
* as defined in RFC 4120.
*
* @author Seema Malkani
* @since 1.7
*/
class KrbServiceLocator {
private static final String SRV_RR = "SRV";
private static final String[] SRV_RR_ATTR = new String[] {SRV_RR};
private static final String SRV_TXT = "TXT";
private static final String[] SRV_TXT_ATTR = new String[] {SRV_TXT};
private static final Random random = new Random();
private static final boolean DEBUG = Krb5.DEBUG;
private KrbServiceLocator() {
}
/**
* Locates the KERBEROS service for a given domain.
* Queries DNS for a list of KERBEROS Service Text Records (TXT) for a
* given domain name.
* Information on the mapping of DNS hostnames and domain names
* to Kerberos realms is stored using DNS TXT records
*
* @param realmName A string realm name.
* @return An ordered list of hostports for the Kerberos service or null if
* the service has not been located.
*/
static String[] getKerberosService(String realmName) {
// search realm in SRV TXT records
String dnsUrl = "dns:///_kerberos." + realmName;
String[] records = null;
try {
// Create the DNS context using NamingManager rather than using
// the initial context constructor. This avoids having the initial
// context constructor call itself (when processing the URL
// argument in the getAttributes call).
Context ctx = NamingManager.getURLContext("dns", new Hashtable<>(0));
if (!(ctx instanceof DirContext)) {
return null; // cannot create a DNS context
}
Attributes attrs = null;
try {
// both connect and accept are needed since DNS is thru UDP
attrs = AccessController.doPrivileged(
(PrivilegedExceptionAction<Attributes>)
() -> ((DirContext)ctx).getAttributes(
dnsUrl, SRV_TXT_ATTR),
null,
new java.net.SocketPermission("*", "connect,accept"));
} catch (PrivilegedActionException e) {
throw (NamingException)e.getCause();
}
Attribute attr;
if (attrs != null && ((attr = attrs.get(SRV_TXT)) != null)) {
int numValues = attr.size();
int numRecords = 0;
String[] txtRecords = new String[numValues];
// gather the text records
int i = 0;
int j = 0;
while (i < numValues) {
try {
txtRecords[j] = (String)attr.get(i);
j++;
} catch (Exception e) {
// ignore bad value
}
i++;
}
numRecords = j;
// trim
if (numRecords < numValues) {
String[] trimmed = new String[numRecords];
System.arraycopy(txtRecords, 0, trimmed, 0, numRecords);
records = trimmed;
} else {
records = txtRecords;
}
}
} catch (NamingException e) {
// ignore
}
return records;
}
/**
* Locates the KERBEROS service for a given domain.
* Queries DNS for a list of KERBEROS Service Location Records (SRV) for a
* given domain name.
*
* @param realmName A string realm name.
* @param protocol the protocol string, can be "_udp" or "_tcp"
* @return An ordered list of hostports for the Kerberos service or null if
* the service has not been located.
*/
static String[] getKerberosService(String realmName, String protocol) {
String dnsUrl = "dns:///_kerberos." + protocol + "." + realmName;
String[] hostports = null;
try {
// Create the DNS context using NamingManager rather than using
// the initial context constructor. This avoids having the initial
// context constructor call itself (when processing the URL
// argument in the getAttributes call).
Context ctx = NamingManager.getURLContext("dns", new Hashtable<>(0));
if (!(ctx instanceof DirContext)) {
return null; // cannot create a DNS context
}
Attributes attrs = null;
try {
// both connect and accept are needed since DNS is thru UDP
attrs = AccessController.doPrivileged(
(PrivilegedExceptionAction<Attributes>)
() -> ((DirContext)ctx).getAttributes(
dnsUrl, SRV_RR_ATTR),
null,
new java.net.SocketPermission("*", "connect,accept"));
} catch (PrivilegedActionException e) {
throw (NamingException)e.getCause();
}
Attribute attr;
if (attrs != null && ((attr = attrs.get(SRV_RR)) != null)) {
int numValues = attr.size();
int numRecords = 0;
SrvRecord[] srvRecords = new SrvRecord[numValues];
// create the service records
int i = 0;
int j = 0;
while (i < numValues) {
try {
srvRecords[j] = new SrvRecord((String) attr.get(i));
j++;
} catch (Exception e) {
// ignore bad value
}
i++;
}
numRecords = j;
// trim
if (numRecords < numValues) {
SrvRecord[] trimmed = new SrvRecord[numRecords];
System.arraycopy(srvRecords, 0, trimmed, 0, numRecords);
srvRecords = trimmed;
}
// Sort the service records in ascending order of their
// priority value. For records with equal priority, move
// those with weight 0 to the top of the list.
if (numRecords > 1) {
Arrays.sort(srvRecords);
}
// extract the host and port number from each service record
hostports = extractHostports(srvRecords);
}
} catch (NamingException e) {
// e.printStackTrace();
// ignore
}
return hostports;
}
/**
* Extract hosts and port numbers from a list of SRV records.
* An array of hostports is returned or null if none were found.
*/
private static String[] extractHostports(SrvRecord[] srvRecords) {
String[] hostports = null;
int head = 0;
int tail = 0;
int sublistLength = 0;
int k = 0;
for (int i = 0; i < srvRecords.length; i++) {
if (hostports == null) {
hostports = new String[srvRecords.length];
}
// find the head and tail of the list of records having the same
// priority value.
head = i;
while (i < srvRecords.length - 1 &&
srvRecords[i].priority == srvRecords[i + 1].priority) {
i++;
}
tail = i;
// select hostports from the sublist
sublistLength = (tail - head) + 1;
for (int j = 0; j < sublistLength; j++) {
hostports[k++] = selectHostport(srvRecords, head, tail);
}
}
return hostports;
}
/*
* Randomly select a service record in the range [head, tail] and return
* its hostport value. Follows the algorithm in RFC 2782.
*/
private static String selectHostport(SrvRecord[] srvRecords, int head,
int tail) {
if (head == tail) {
return srvRecords[head].hostport;
}
// compute the running sum for records between head and tail
int sum = 0;
for (int i = head; i <= tail; i++) {
if (srvRecords[i] != null) {
sum += srvRecords[i].weight;
srvRecords[i].sum = sum;
}
}
String hostport = null;
// If all records have zero weight, select first available one;
// otherwise, randomly select a record according to its weight
int target = (sum == 0 ? 0 : random.nextInt(sum + 1));
for (int i = head; i <= tail; i++) {
if (srvRecords[i] != null && srvRecords[i].sum >= target) {
hostport = srvRecords[i].hostport;
srvRecords[i] = null; // make this record unavailable
break;
}
}
return hostport;
}
/**
* This class holds a DNS service (SRV) record.
* See http://www.ietf.org/rfc/rfc2782.txt
*/
static class SrvRecord implements Comparable<SrvRecord> {
int priority;
int weight;
int sum;
String hostport;
/**
* Creates a service record object from a string record.
* DNS supplies the string record in the following format:
* <pre>
* <Priority> " " <Weight> " " <Port> " " <Host>
* </pre>
*/
SrvRecord(String srvRecord) throws Exception {
StringTokenizer tokenizer = new StringTokenizer(srvRecord, " ");
String port;
if (tokenizer.countTokens() == 4) {
priority = Integer.parseInt(tokenizer.nextToken());
weight = Integer.parseInt(tokenizer.nextToken());
port = tokenizer.nextToken();
hostport = tokenizer.nextToken() + ":" + port;
} else {
throw new IllegalArgumentException();
}
}
/*
* Sort records in ascending order of priority value. For records with
* equal priority move those with weight 0 to the top of the list.
*/
public int compareTo(SrvRecord that) {
if (priority > that.priority) {
return 1; // this > that
} else if (priority < that.priority) {
return -1; // this < that
} else if (weight == 0 && that.weight != 0) {
return -1; // this < that
} else if (weight != 0 && that.weight == 0) {
return 1; // this > that
} else {
return 0; // this == that
}
}
}
}

View file

@ -0,0 +1,114 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.util.*;
import java.io.IOException;
/**
* This class encapsulates a TGS-REP that is sent from the KDC to the
* Kerberos client.
*/
public class KrbTgsRep extends KrbKdcRep {
private TGSRep rep;
private Credentials creds;
private Ticket secondTicket;
private static final boolean DEBUG = Krb5.DEBUG;
KrbTgsRep(byte[] ibuf, KrbTgsReq tgsReq)
throws KrbException, IOException {
DerValue ref = new DerValue(ibuf);
TGSReq req = tgsReq.getMessage();
TGSRep rep = null;
try {
rep = new TGSRep(ref);
} catch (Asn1Exception e) {
rep = null;
KRBError err = new KRBError(ref);
String errStr = err.getErrorString();
String eText = null; // pick up text sent by the server (if any)
if (errStr != null && errStr.length() > 0) {
if (errStr.charAt(errStr.length() - 1) == 0)
eText = errStr.substring(0, errStr.length() - 1);
else
eText = errStr;
}
KrbException ke;
if (eText == null) {
// no text sent from server
ke = new KrbException(err.getErrorCode());
} else {
// override default text with server text
ke = new KrbException(err.getErrorCode(), eText);
}
ke.initCause(e);
throw ke;
}
byte[] enc_tgs_rep_bytes = rep.encPart.decrypt(tgsReq.tgsReqKey,
tgsReq.usedSubkey() ? KeyUsage.KU_ENC_TGS_REP_PART_SUBKEY :
KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes);
ref = new DerValue(enc_tgs_rep_part);
EncTGSRepPart enc_part = new EncTGSRepPart(ref);
rep.encKDCRepPart = enc_part;
check(false, req, rep);
this.creds = new Credentials(rep.ticket,
rep.cname,
enc_part.sname,
enc_part.key,
enc_part.flags,
enc_part.authtime,
enc_part.starttime,
enc_part.endtime,
enc_part.renewTill,
enc_part.caddr
);
this.rep = rep;
this.secondTicket = tgsReq.getSecondTicket();
}
/**
* Return the credentials that were contained in this KRB-TGS-REP.
*/
public Credentials getCreds() {
return creds;
}
sun.security.krb5.internal.ccache.Credentials setCredentials() {
return new sun.security.krb5.internal.ccache.Credentials(rep, secondTicket);
}
}

View file

@ -0,0 +1,406 @@
/*
* Copyright (c) 2000, 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;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.crypto.*;
import java.io.IOException;
import java.net.UnknownHostException;
import java.time.Instant;
/**
* This class encapsulates a Kerberos TGS-REQ that is sent from the
* client to the KDC.
*/
public class KrbTgsReq {
private PrincipalName princName;
private PrincipalName servName;
private TGSReq tgsReqMessg;
private KerberosTime ctime;
private Ticket secondTicket = null;
private boolean useSubkey = false;
EncryptionKey tgsReqKey;
private static final boolean DEBUG = Krb5.DEBUG;
private byte[] obuf;
private byte[] ibuf;
// Used in CredentialsUtil
public KrbTgsReq(Credentials asCreds,
PrincipalName sname)
throws KrbException, IOException {
this(new KDCOptions(),
asCreds,
sname,
null, // KerberosTime from
null, // KerberosTime till
null, // KerberosTime rtime
null, // eTypes, // null, // int[] eTypes
null, // HostAddresses addresses
null, // AuthorizationData authorizationData
null, // Ticket[] additionalTickets
null); // EncryptionKey subSessionKey
}
// S4U2proxy
public KrbTgsReq(Credentials asCreds,
Ticket second,
PrincipalName sname)
throws KrbException, IOException {
this(KDCOptions.with(KDCOptions.CNAME_IN_ADDL_TKT,
KDCOptions.FORWARDABLE),
asCreds,
sname,
null,
null,
null,
null,
null,
null,
new Ticket[] {second}, // the service ticket
null);
}
// S4U2user
public KrbTgsReq(Credentials asCreds,
PrincipalName sname,
PAData extraPA)
throws KrbException, IOException {
this(KDCOptions.with(KDCOptions.FORWARDABLE),
asCreds,
asCreds.getClient(),
sname,
null,
null,
null,
null,
null,
null,
null,
null,
extraPA); // the PA-FOR-USER
}
// Called by Credentials, KrbCred
KrbTgsReq(
KDCOptions options,
Credentials asCreds,
PrincipalName sname,
KerberosTime from,
KerberosTime till,
KerberosTime rtime,
int[] eTypes,
HostAddresses addresses,
AuthorizationData authorizationData,
Ticket[] additionalTickets,
EncryptionKey subKey) throws KrbException, IOException {
this(options, asCreds, asCreds.getClient(), sname,
from, till, rtime, eTypes, addresses,
authorizationData, additionalTickets, subKey, null);
}
private KrbTgsReq(
KDCOptions options,
Credentials asCreds,
PrincipalName cname,
PrincipalName sname,
KerberosTime from,
KerberosTime till,
KerberosTime rtime,
int[] eTypes,
HostAddresses addresses,
AuthorizationData authorizationData,
Ticket[] additionalTickets,
EncryptionKey subKey,
PAData extraPA) throws KrbException, IOException {
princName = cname;
servName = sname;
ctime = KerberosTime.now();
// check if they are valid arguments. The optional fields
// should be consistent with settings in KDCOptions.
if (options.get(KDCOptions.FORWARDABLE) &&
(!(asCreds.flags.get(Krb5.TKT_OPTS_FORWARDABLE)))) {
options.set(KDCOptions.FORWARDABLE, false);
}
if (options.get(KDCOptions.FORWARDED)) {
if (!(asCreds.flags.get(KDCOptions.FORWARDABLE)))
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
}
if (options.get(KDCOptions.PROXIABLE) &&
(!(asCreds.flags.get(Krb5.TKT_OPTS_PROXIABLE)))) {
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
}
if (options.get(KDCOptions.PROXY)) {
if (!(asCreds.flags.get(KDCOptions.PROXIABLE)))
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
}
if (options.get(KDCOptions.ALLOW_POSTDATE) &&
(!(asCreds.flags.get(Krb5.TKT_OPTS_MAY_POSTDATE)))) {
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
}
if (options.get(KDCOptions.RENEWABLE) &&
(!(asCreds.flags.get(Krb5.TKT_OPTS_RENEWABLE)))) {
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
}
if (options.get(KDCOptions.POSTDATED)) {
if (!(asCreds.flags.get(KDCOptions.POSTDATED)))
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
} else {
if (from != null) from = null;
}
if (options.get(KDCOptions.RENEWABLE)) {
if (!(asCreds.flags.get(KDCOptions.RENEWABLE)))
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
} else {
if (rtime != null) rtime = null;
}
if (options.get(KDCOptions.ENC_TKT_IN_SKEY) || options.get(KDCOptions.CNAME_IN_ADDL_TKT)) {
if (additionalTickets == null)
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
// in TGS_REQ there could be more than one additional
// tickets, but in file-based credential cache,
// there is only one additional ticket field.
secondTicket = additionalTickets[0];
} else {
if (additionalTickets != null)
additionalTickets = null;
}
tgsReqMessg = createRequest(
options,
asCreds.ticket,
asCreds.key,
ctime,
princName,
servName,
from,
till,
rtime,
eTypes,
addresses,
authorizationData,
additionalTickets,
subKey,
extraPA);
obuf = tgsReqMessg.asn1Encode();
// XXX We need to revisit this to see if can't move it
// up such that FORWARDED flag set in the options
// is included in the marshaled request.
/*
* If this is based on a forwarded ticket, record that in the
* options, because the returned TgsRep will contain the
* FORWARDED flag set.
*/
if (asCreds.flags.get(KDCOptions.FORWARDED))
options.set(KDCOptions.FORWARDED, true);
}
/**
* Sends a TGS request to the realm of the target.
* @throws KrbException
* @throws IOException
*/
public void send() throws IOException, KrbException {
String realmStr = null;
if (servName != null)
realmStr = servName.getRealmString();
KdcComm comm = new KdcComm(realmStr);
ibuf = comm.send(obuf);
}
public KrbTgsRep getReply()
throws KrbException, IOException {
return new KrbTgsRep(ibuf, this);
}
/**
* Sends the request, waits for a reply, and returns the Credentials.
* Used in Credentials, KrbCred, and internal/CredentialsUtil.
*/
public Credentials sendAndGetCreds() throws IOException, KrbException {
KrbTgsRep tgs_rep = null;
String kdc = null;
send();
tgs_rep = getReply();
return tgs_rep.getCreds();
}
KerberosTime getCtime() {
return ctime;
}
private TGSReq createRequest(
KDCOptions kdc_options,
Ticket ticket,
EncryptionKey key,
KerberosTime ctime,
PrincipalName cname,
PrincipalName sname,
KerberosTime from,
KerberosTime till,
KerberosTime rtime,
int[] eTypes,
HostAddresses addresses,
AuthorizationData authorizationData,
Ticket[] additionalTickets,
EncryptionKey subKey,
PAData extraPA)
throws IOException, KrbException, UnknownHostException {
KerberosTime req_till = null;
if (till == null) {
String d = Config.getInstance().get("libdefaults", "ticket_lifetime");
if (d != null) {
req_till = new KerberosTime(Instant.now().plusSeconds(Config.duration(d)));
} else {
req_till = new KerberosTime(0); // Choose KDC maximum allowed
}
} else {
req_till = till;
}
/*
* RFC 4120, Section 5.4.2.
* For KRB_TGS_REP, the ciphertext is encrypted in the
* sub-session key from the Authenticator, or if absent,
* the session key from the ticket-granting ticket used
* in the request.
*
* To support this, use tgsReqKey to remember which key to use.
*/
tgsReqKey = key;
int[] req_eTypes = null;
if (eTypes == null) {
req_eTypes = EType.getDefaults("default_tgs_enctypes");
} else {
req_eTypes = eTypes;
}
EncryptionKey reqKey = null;
EncryptedData encAuthorizationData = null;
if (authorizationData != null) {
byte[] ad = authorizationData.asn1Encode();
if (subKey != null) {
reqKey = subKey;
tgsReqKey = subKey; // Key to use to decrypt reply
useSubkey = true;
encAuthorizationData = new EncryptedData(reqKey, ad,
KeyUsage.KU_TGS_REQ_AUTH_DATA_SUBKEY);
} else
encAuthorizationData = new EncryptedData(key, ad,
KeyUsage.KU_TGS_REQ_AUTH_DATA_SESSKEY);
}
KDCReqBody reqBody = new KDCReqBody(
kdc_options,
cname,
sname,
from,
req_till,
rtime,
Nonce.value(),
req_eTypes,
addresses,
encAuthorizationData,
additionalTickets);
byte[] temp = reqBody.asn1Encode(Krb5.KRB_TGS_REQ);
// if the checksum type is one of the keyed checksum types,
// use session key.
Checksum cksum;
switch (Checksum.CKSUMTYPE_DEFAULT) {
case Checksum.CKSUMTYPE_RSA_MD4_DES:
case Checksum.CKSUMTYPE_DES_MAC:
case Checksum.CKSUMTYPE_DES_MAC_K:
case Checksum.CKSUMTYPE_RSA_MD4_DES_K:
case Checksum.CKSUMTYPE_RSA_MD5_DES:
case Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD:
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128:
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
KeyUsage.KU_PA_TGS_REQ_CKSUM);
break;
case Checksum.CKSUMTYPE_CRC32:
case Checksum.CKSUMTYPE_RSA_MD4:
case Checksum.CKSUMTYPE_RSA_MD5:
default:
cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp);
}
// Usage will be KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR
byte[] tgs_ap_req = new KrbApReq(
new APOptions(),
ticket,
key,
cname,
cksum,
ctime,
reqKey,
null,
null).getMessage();
PAData tgsPAData = new PAData(Krb5.PA_TGS_REQ, tgs_ap_req);
return new TGSReq(
extraPA != null ?
new PAData[] {extraPA, tgsPAData } :
new PAData[] {tgsPAData},
reqBody);
}
TGSReq getMessage() {
return tgsReqMessg;
}
Ticket getSecondTicket() {
return secondTicket;
}
private static void debug(String message) {
// System.err.println(">>> KrbTgsReq: " + message);
}
boolean usedSubkey() {
return useSubkey;
}
}

View file

@ -0,0 +1,698 @@
/*
* 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;
import sun.security.krb5.internal.*;
import sun.security.util.*;
import java.net.*;
import java.util.Vector;
import java.util.Locale;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import sun.security.krb5.internal.ccache.CCacheOutputStream;
import sun.security.krb5.internal.util.KerberosString;
/**
* Implements the ASN.1 PrincipalName type and its realm in a single class.
* <pre>{@code
* Realm ::= KerberosString
*
* PrincipalName ::= SEQUENCE {
* name-type [0] Int32,
* name-string [1] SEQUENCE OF KerberosString
* }
* }</pre>
* This class is immutable.
* @see Realm
*/
public class PrincipalName implements Cloneable {
//name types
/**
* Name type not known
*/
public static final int KRB_NT_UNKNOWN = 0;
/**
* Just the name of the principal as in DCE, or for users
*/
public static final int KRB_NT_PRINCIPAL = 1;
/**
* Service and other unique instance (krbtgt)
*/
public static final int KRB_NT_SRV_INST = 2;
/**
* Service with host name as instance (telnet, rcommands)
*/
public static final int KRB_NT_SRV_HST = 3;
/**
* Service with host as remaining components
*/
public static final int KRB_NT_SRV_XHST = 4;
/**
* Unique ID
*/
public static final int KRB_NT_UID = 5;
/**
* TGS Name
*/
public static final String TGS_DEFAULT_SRV_NAME = "krbtgt";
public static final int TGS_DEFAULT_NT = KRB_NT_SRV_INST;
public static final char NAME_COMPONENT_SEPARATOR = '/';
public static final char NAME_REALM_SEPARATOR = '@';
public static final char REALM_COMPONENT_SEPARATOR = '.';
public static final String NAME_COMPONENT_SEPARATOR_STR = "/";
public static final String NAME_REALM_SEPARATOR_STR = "@";
public static final String REALM_COMPONENT_SEPARATOR_STR = ".";
// Instance fields.
/**
* The name type, from PrincipalName's name-type field.
*/
private final int nameType;
/**
* The name strings, from PrincipalName's name-strings field. This field
* must be neither null nor empty. Each entry of it must also be neither
* null nor empty. Make sure to clone the field when it's passed in or out.
*/
private final String[] nameStrings;
/**
* The realm this principal belongs to.
*/
private final Realm nameRealm; // not null
/**
* When constructing a PrincipalName, whether the realm is included in
* the input, or deduced from default realm or domain-realm mapping.
*/
private final boolean realmDeduced;
// cached default salt, not used in clone
private transient String salt = null;
// There are 3 basic constructors. All other constructors must call them.
// All basic constructors must call validateNameStrings.
// 1. From name components
// 2. From name
// 3. From DER encoding
/**
* Creates a PrincipalName.
*/
public PrincipalName(int nameType, String[] nameStrings, Realm nameRealm) {
if (nameRealm == null) {
throw new IllegalArgumentException("Null realm not allowed");
}
validateNameStrings(nameStrings);
this.nameType = nameType;
this.nameStrings = nameStrings.clone();
this.nameRealm = nameRealm;
this.realmDeduced = false;
}
// This method is called by Windows NativeCred.c
public PrincipalName(String[] nameParts, String realm) throws RealmException {
this(KRB_NT_UNKNOWN, nameParts, new Realm(realm));
}
// Validate a nameStrings argument
private static void validateNameStrings(String[] ns) {
if (ns == null) {
throw new IllegalArgumentException("Null nameStrings not allowed");
}
if (ns.length == 0) {
throw new IllegalArgumentException("Empty nameStrings not allowed");
}
for (String s: ns) {
if (s == null) {
throw new IllegalArgumentException("Null nameString not allowed");
}
if (s.isEmpty()) {
throw new IllegalArgumentException("Empty nameString not allowed");
}
}
}
public Object clone() {
try {
PrincipalName pName = (PrincipalName) super.clone();
UNSAFE.putObject(this, NAME_STRINGS_OFFSET, nameStrings.clone());
return pName;
} catch (CloneNotSupportedException ex) {
throw new AssertionError("Should never happen");
}
}
private static final long NAME_STRINGS_OFFSET;
private static final jdk.internal.misc.Unsafe UNSAFE;
static {
try {
jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
NAME_STRINGS_OFFSET = unsafe.objectFieldOffset(
PrincipalName.class.getDeclaredField("nameStrings"));
UNSAFE = unsafe;
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof PrincipalName) {
PrincipalName other = (PrincipalName)o;
return nameRealm.equals(other.nameRealm) &&
Arrays.equals(nameStrings, other.nameStrings);
}
return false;
}
/**
* Returns the ASN.1 encoding of the
* <pre>{@code
* PrincipalName ::= SEQUENCE {
* name-type [0] Int32,
* name-string [1] SEQUENCE OF KerberosString
* }
*
* KerberosString ::= GeneralString (IA5String)
* }</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>.
*
* @param encoding DER-encoded PrincipalName (without Realm)
* @param realm the realm for this name
* @exception Asn1Exception if an error occurs while decoding
* an ASN1 encoded data.
* @exception Asn1Exception if there is an ASN1 encoding error
* @exception IOException if an I/O error occurs
* @exception IllegalArgumentException if encoding is null
* reading encoded data.
*/
public PrincipalName(DerValue encoding, Realm realm)
throws Asn1Exception, IOException {
if (realm == null) {
throw new IllegalArgumentException("Null realm not allowed");
}
realmDeduced = false;
nameRealm = realm;
DerValue der;
if (encoding == null) {
throw new IllegalArgumentException("Null encoding not allowed");
}
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();
nameType = bint.intValue();
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
if ((der.getTag() & 0x01F) == 0x01) {
DerValue subDer = der.getData().getDerValue();
if (subDer.getTag() != DerValue.tag_SequenceOf) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
Vector<String> v = new Vector<>();
DerValue subSubDer;
while(subDer.getData().available() > 0) {
subSubDer = subDer.getData().getDerValue();
String namePart = new KerberosString(subSubDer).toString();
v.addElement(namePart);
}
nameStrings = new String[v.size()];
v.copyInto(nameStrings);
validateNameStrings(nameStrings);
} else {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
}
/**
* Parse (unmarshal) a <code>PrincipalName</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 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
* @param realm the realm for the name
* @return an instance of <code>PrincipalName</code>, or null if the
* field is optional and missing.
*/
public static PrincipalName parse(DerInputStream data,
byte explicitTag, boolean
optional,
Realm realm)
throws Asn1Exception, IOException, RealmException {
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();
if (realm == null) {
realm = Realm.getDefault();
}
return new PrincipalName(subDer, realm);
}
}
// XXX Error checkin consistent with MIT krb5_parse_name
// Code repetition, realm parsed again by class Realm
private static String[] parseName(String name) {
Vector<String> tempStrings = new Vector<>();
String temp = name;
int i = 0;
int componentStart = 0;
String component;
while (i < temp.length()) {
if (temp.charAt(i) == NAME_COMPONENT_SEPARATOR) {
/*
* If this separator is escaped then don't treat it
* as a separator
*/
if (i > 0 && temp.charAt(i - 1) == '\\') {
temp = temp.substring(0, i - 1) +
temp.substring(i, temp.length());
continue;
}
else {
if (componentStart <= i) {
component = temp.substring(componentStart, i);
tempStrings.addElement(component);
}
componentStart = i + 1;
}
} else {
if (temp.charAt(i) == NAME_REALM_SEPARATOR) {
/*
* If this separator is escaped then don't treat it
* as a separator
*/
if (i > 0 && temp.charAt(i - 1) == '\\') {
temp = temp.substring(0, i - 1) +
temp.substring(i, temp.length());
continue;
} else {
if (componentStart < i) {
component = temp.substring(componentStart, i);
tempStrings.addElement(component);
}
componentStart = i + 1;
break;
}
}
}
i++;
}
if (i == temp.length()) {
component = temp.substring(componentStart, i);
tempStrings.addElement(component);
}
String[] result = new String[tempStrings.size()];
tempStrings.copyInto(result);
return result;
}
/**
* Constructs a PrincipalName from a string.
* @param name the name
* @param type the type
* @param realm the realm, null if not known. Note that when realm is not
* null, it will be always used even if there is a realm part in name. When
* realm is null, will read realm part from name, or try to map a realm
* (for KRB_NT_SRV_HST), or use the default realm, or fail
* @throws RealmException
*/
public PrincipalName(String name, int type, String realm)
throws RealmException {
if (name == null) {
throw new IllegalArgumentException("Null name not allowed");
}
String[] nameParts = parseName(name);
validateNameStrings(nameParts);
if (realm == null) {
realm = Realm.parseRealmAtSeparator(name);
}
// No realm info from parameter and string, must deduce later
realmDeduced = realm == null;
switch (type) {
case KRB_NT_SRV_HST:
if (nameParts.length >= 2) {
String hostName = nameParts[1];
try {
// RFC4120 does not recommend canonicalizing a hostname.
// However, for compatibility reason, we will try
// canonicalize it and see if the output looks better.
String canonicalized = (InetAddress.getByName(hostName)).
getCanonicalHostName();
// Looks if canonicalized is a longer format of hostName,
// we accept cases like
// bunny -> bunny.rabbit.hole
if (canonicalized.toLowerCase(Locale.ENGLISH).startsWith(
hostName.toLowerCase(Locale.ENGLISH)+".")) {
hostName = canonicalized;
}
} catch (UnknownHostException | SecurityException e) {
// not canonicalized or no permission to do so, use old
}
if (hostName.endsWith(".")) {
hostName = hostName.substring(0, hostName.length() - 1);
}
nameParts[1] = hostName.toLowerCase(Locale.ENGLISH);
}
nameStrings = nameParts;
nameType = type;
if (realm != null) {
nameRealm = new Realm(realm);
} else {
// We will try to get realm name from the mapping in
// the configuration. If it is not specified
// we will use the default realm. This nametype does
// not allow a realm to be specified. The name string must of
// the form service@host and this is internally changed into
// service/host by Kerberos
String mapRealm = mapHostToRealm(nameParts[1]);
if (mapRealm != null) {
nameRealm = new Realm(mapRealm);
} else {
nameRealm = Realm.getDefault();
}
}
break;
case KRB_NT_UNKNOWN:
case KRB_NT_PRINCIPAL:
case KRB_NT_SRV_INST:
case KRB_NT_SRV_XHST:
case KRB_NT_UID:
nameStrings = nameParts;
nameType = type;
if (realm != null) {
nameRealm = new Realm(realm);
} else {
nameRealm = Realm.getDefault();
}
break;
default:
throw new IllegalArgumentException("Illegal name type");
}
}
public PrincipalName(String name, int type) throws RealmException {
this(name, type, (String)null);
}
public PrincipalName(String name) throws RealmException {
this(name, KRB_NT_UNKNOWN);
}
public PrincipalName(String name, String realm) throws RealmException {
this(name, KRB_NT_UNKNOWN, realm);
}
public static PrincipalName tgsService(String r1, String r2)
throws KrbException {
return new PrincipalName(PrincipalName.KRB_NT_SRV_INST,
new String[] {PrincipalName.TGS_DEFAULT_SRV_NAME, r1},
new Realm(r2));
}
public String getRealmAsString() {
return getRealmString();
}
public String getPrincipalNameAsString() {
StringBuilder temp = new StringBuilder(nameStrings[0]);
for (int i = 1; i < nameStrings.length; i++)
temp.append(nameStrings[i]);
return temp.toString();
}
public int hashCode() {
return toString().hashCode();
}
public String getName() {
return toString();
}
public int getNameType() {
return nameType;
}
public String[] getNameStrings() {
return nameStrings.clone();
}
public byte[][] toByteArray() {
byte[][] result = new byte[nameStrings.length][];
for (int i = 0; i < nameStrings.length; i++) {
result[i] = new byte[nameStrings[i].length()];
result[i] = nameStrings[i].getBytes();
}
return result;
}
public String getRealmString() {
return nameRealm.toString();
}
public Realm getRealm() {
return nameRealm;
}
public String getSalt() {
if (salt == null) {
StringBuilder salt = new StringBuilder();
salt.append(nameRealm.toString());
for (int i = 0; i < nameStrings.length; i++) {
salt.append(nameStrings[i]);
}
return salt.toString();
}
return salt;
}
public String toString() {
StringBuilder str = new StringBuilder();
for (int i = 0; i < nameStrings.length; i++) {
if (i > 0)
str.append("/");
str.append(nameStrings[i]);
}
str.append("@");
str.append(nameRealm.toString());
return str.toString();
}
public String getNameString() {
StringBuilder str = new StringBuilder();
for (int i = 0; i < nameStrings.length; i++) {
if (i > 0)
str.append("/");
str.append(nameStrings[i]);
}
return str.toString();
}
/**
* Encodes a <code>PrincipalName</code> object. Note that only the type and
* names are encoded. To encode the realm, call getRealm().asn1Encode().
* @return the byte array of the encoded PrncipalName 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();
BigInteger bint = BigInteger.valueOf(this.nameType);
temp.putInteger(bint);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
temp = new DerOutputStream();
DerValue[] der = new DerValue[nameStrings.length];
for (int i = 0; i < nameStrings.length; i++) {
der[i] = new KerberosString(nameStrings[i]).toDerValue();
}
temp.putSequence(der);
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
return temp.toByteArray();
}
/**
* Checks if two <code>PrincipalName</code> objects have identical values in their corresponding data fields.
*
* @param pname the other <code>PrincipalName</code> object.
* @return true if two have identical values, otherwise, return false.
*/
// It is used in <code>sun.security.krb5.internal.ccache</code> package.
public boolean match(PrincipalName pname) {
boolean matched = true;
//name type is just a hint, no two names can be the same ignoring name type.
// if (this.nameType != pname.nameType) {
// matched = false;
// }
if ((this.nameRealm != null) && (pname.nameRealm != null)) {
if (!(this.nameRealm.toString().equalsIgnoreCase(pname.nameRealm.toString()))) {
matched = false;
}
}
if (this.nameStrings.length != pname.nameStrings.length) {
matched = false;
} else {
for (int i = 0; i < this.nameStrings.length; i++) {
if (!(this.nameStrings[i].equalsIgnoreCase(pname.nameStrings[i]))) {
matched = false;
}
}
}
return matched;
}
/**
* Writes data field values of <code>PrincipalName</code> in FCC format to an output stream.
*
* @param cos a <code>CCacheOutputStream</code> for writing data.
* @exception IOException if an I/O exception occurs.
* @see sun.security.krb5.internal.ccache.CCacheOutputStream
*/
public void writePrincipal(CCacheOutputStream cos) throws IOException {
cos.write32(nameType);
cos.write32(nameStrings.length);
byte[] realmBytes = null;
realmBytes = nameRealm.toString().getBytes();
cos.write32(realmBytes.length);
cos.write(realmBytes, 0, realmBytes.length);
byte[] bytes = null;
for (int i = 0; i < nameStrings.length; i++) {
bytes = nameStrings[i].getBytes();
cos.write32(bytes.length);
cos.write(bytes, 0, bytes.length);
}
}
/**
* Returns the instance component of a name.
* In a multi-component name such as a KRB_NT_SRV_INST
* name, the second component is returned.
* Null is returned if there are not two or more
* components in the name.
*
* @return instance component of a multi-component name.
*/
public String getInstanceComponent()
{
if (nameStrings != null && nameStrings.length >= 2)
{
return new String(nameStrings[1]);
}
return null;
}
static String mapHostToRealm(String name) {
String result = null;
try {
String subname = null;
Config c = Config.getInstance();
if ((result = c.get("domain_realm", name)) != null)
return result;
else {
for (int i = 1; i < name.length(); i++) {
if ((name.charAt(i) == '.') && (i != name.length() - 1)) { //mapping could be .ibm.com = AUSTIN.IBM.COM
subname = name.substring(i);
result = c.get("domain_realm", subname);
if (result != null) {
break;
}
else {
subname = name.substring(i + 1); //or mapping could be ibm.com = AUSTIN.IBM.COM
result = c.get("domain_realm", subname);
if (result != null) {
break;
}
}
}
}
}
} catch (KrbException e) {
}
return result;
}
public boolean isRealmDeduced() {
return realmDeduced;
}
}

View file

@ -0,0 +1,419 @@
/*
* 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;
import sun.security.krb5.internal.Krb5;
import sun.security.util.*;
import java.io.IOException;
import java.util.*;
import sun.security.krb5.internal.util.KerberosString;
/**
* Implements the ASN.1 Realm type.
*
* {@code Realm ::= GeneralString}
*
* This class is immutable.
*/
public class Realm implements Cloneable {
public static final boolean AUTODEDUCEREALM =
java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
"sun.security.krb5.autodeducerealm"));
private final String realm; // not null nor empty
public Realm(String name) throws RealmException {
realm = parseRealm(name);
}
public static Realm getDefault() throws RealmException {
try {
return new Realm(Config.getInstance().getDefaultRealm());
} catch (RealmException re) {
throw re;
} catch (KrbException ke) {
throw new RealmException(ke);
}
}
// Immutable class, no need to clone
public Object clone() {
return this;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Realm)) {
return false;
}
Realm that = (Realm)obj;
return this.realm.equals(that.realm);
}
public int hashCode() {
return realm.hashCode();
}
/**
* Constructs a Realm 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 Realm(DerValue encoding)
throws Asn1Exception, RealmException, IOException {
if (encoding == null) {
throw new IllegalArgumentException("encoding can not be null");
}
realm = new KerberosString(encoding).toString();
if (realm == null || realm.length() == 0)
throw new RealmException(Krb5.REALM_NULL);
if (!isValidRealmString(realm))
throw new RealmException(Krb5.REALM_ILLCHAR);
}
public String toString() {
return realm;
}
// Extract realm from a string like dummy@REALM
public static String parseRealmAtSeparator(String name)
throws RealmException {
if (name == null) {
throw new IllegalArgumentException
("null input name is not allowed");
}
String temp = new String(name);
String result = null;
int i = 0;
while (i < temp.length()) {
if (temp.charAt(i) == PrincipalName.NAME_REALM_SEPARATOR) {
if (i == 0 || temp.charAt(i - 1) != '\\') {
if (i + 1 < temp.length()) {
result = temp.substring(i + 1, temp.length());
} else {
throw new IllegalArgumentException
("empty realm part not allowed");
}
break;
}
}
i++;
}
if (result != null) {
if (result.length() == 0)
throw new RealmException(Krb5.REALM_NULL);
if (!isValidRealmString(result))
throw new RealmException(Krb5.REALM_ILLCHAR);
}
return result;
}
public static String parseRealmComponent(String name) {
if (name == null) {
throw new IllegalArgumentException
("null input name is not allowed");
}
String temp = new String(name);
String result = null;
int i = 0;
while (i < temp.length()) {
if (temp.charAt(i) == PrincipalName.REALM_COMPONENT_SEPARATOR) {
if (i == 0 || temp.charAt(i - 1) != '\\') {
if (i + 1 < temp.length())
result = temp.substring(i + 1, temp.length());
break;
}
}
i++;
}
return result;
}
protected static String parseRealm(String name) throws RealmException {
String result = parseRealmAtSeparator(name);
if (result == null)
result = name;
if (result == null || result.length() == 0)
throw new RealmException(Krb5.REALM_NULL);
if (!isValidRealmString(result))
throw new RealmException(Krb5.REALM_ILLCHAR);
return result;
}
// This is protected because the definition of a realm
// string is fixed
protected static boolean isValidRealmString(String name) {
if (name == null)
return false;
if (name.length() == 0)
return false;
for (int i = 0; i < name.length(); i++) {
if (name.charAt(i) == '/' ||
name.charAt(i) == ':' ||
name.charAt(i) == '\0') {
return false;
}
}
return true;
}
/**
* Encodes a Realm 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 {
DerOutputStream out = new DerOutputStream();
out.putDerValue(new KerberosString(this.realm).toDerValue());
return out.toByteArray();
}
/**
* Parse (unmarshal) a realm 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 Realm.
*
*/
public static Realm parse(DerInputStream data, byte explicitTag, boolean optional)
throws Asn1Exception, IOException, RealmException {
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 Realm(subDer);
}
}
/**
* Returns an array of realms that may be traversed to obtain
* a TGT from the initiating realm cRealm to the target realm
* sRealm.
* <br>
* This method would read [capaths] to create a path, or generate a
* hierarchical path if [capaths] does not contain a sub-stanza for cRealm
* or the sub-stanza does not contain a tag for sRealm.
* <br>
* The returned list would never be null, and it always contains
* cRealm as the head entry. sRealm is not included as the tail.
*
* @param cRealm the initiating realm, not null
* @param sRealm the target realm, not null, not equals to cRealm
* @return array of realms including at least cRealm as the first
* element
*/
public static String[] getRealmsList(String cRealm, String sRealm) {
try {
// Try [capaths]
return parseCapaths(cRealm, sRealm);
} catch (KrbException ke) {
// Now assume the realms are organized hierarchically.
return parseHierarchy(cRealm, sRealm);
}
}
/**
* Parses the [capaths] stanza of the configuration file for a
* list of realms to traverse to obtain credentials from the
* initiating realm cRealm to the target realm sRealm.
*
* For a given client realm C there is a tag C in [capaths] whose
* subtag S has a value which is a (possibly partial) path from C
* to S. When the path is partial, it contains only the tail of the
* full path. Values of other subtags will be used to build the full
* path. The value "." means a direct path from C to S. If realm S
* does not appear as a subtag, there is no path defined here.
*
* The implementation ignores all values which equals to C or S, or
* a "." in multiple values, or any duplicated realm names.
*
* When a path value has more than two realms, they can be specified
* with multiple key-value pairs each having a single value, but the
* order must not change.
*
* For example:
*
* [capaths]
* TIVOLI.COM = {
* IBM.COM = IBM_LDAPCENTRAL.COM MOONLITE.ORG
* IBM_LDAPCENTRAL.COM = LDAPCENTRAL.NET
* LDAPCENTRAL.NET = .
* }
*
* TIVOLI.COM has a direct path to LDAPCENTRAL.NET, which has a direct
* path to IBM_LDAPCENTRAL.COM. It also has a partial path to IBM.COM
* being "IBM_LDAPCENTRAL.COM MOONLITE.ORG". Merging these info together,
* a full path from TIVOLI.COM to IBM.COM will be
*
* TIVOLI.COM -> LDAPCENTRAL.NET -> IBM_LDAPCENTRAL.COM
* -> IBM_LDAPCENTRAL.COM -> MOONLITE.ORG
*
* Please note the sRealm IBM.COM does not appear in the path.
*
* @param cRealm the initiating realm
* @param sRealm the target realm, not the same as cRealm
* @return array of realms including at least cRealm as the first
* element
* @throws KrbException if the config does not contain a sub-stanza
* for cRealm in [capaths] or the sub-stanza does not contain
* sRealm as a tag
*/
private static String[] parseCapaths(String cRealm, String sRealm)
throws KrbException {
// This line could throw a KrbException
Config cfg = Config.getInstance();
if (!cfg.exists("capaths", cRealm, sRealm)) {
throw new KrbException("No conf");
}
LinkedList<String> path = new LinkedList<>();
String head = sRealm;
while (true) {
String value = cfg.getAll("capaths", cRealm, head);
if (value == null) {
break;
}
String[] more = value.split("\\s+");
boolean changed = false;
for (int i=more.length-1; i>=0; i--) {
if (path.contains(more[i])
|| more[i].equals(".")
|| more[i].equals(cRealm)
|| more[i].equals(sRealm)
|| more[i].equals(head)) {
// Ignore invalid values
continue;
}
changed = true;
path.addFirst(more[i]);
}
if (!changed) break;
head = path.getFirst();
}
path.addFirst(cRealm);
return path.toArray(new String[path.size()]);
}
/**
* Build a list of realm that can be traversed
* to obtain credentials from the initiating realm cRealm
* for a service in the target realm sRealm.
* @param cRealm the initiating realm
* @param sRealm the target realm, not the same as cRealm
* @return array of realms including cRealm as the first element
*/
private static String[] parseHierarchy(String cRealm, String sRealm) {
String[] cComponents = cRealm.split("\\.");
String[] sComponents = sRealm.split("\\.");
int cPos = cComponents.length;
int sPos = sComponents.length;
boolean hasCommon = false;
for (sPos--, cPos--; sPos >=0 && cPos >= 0 &&
sComponents[sPos].equals(cComponents[cPos]);
sPos--, cPos--) {
hasCommon = true;
}
// For those with common components:
// length pos
// SITES1.SALES.EXAMPLE.COM 4 1
// EVERYWHERE.EXAMPLE.COM 3 0
// For those without common components:
// length pos
// DEVEL.EXAMPLE.COM 3 2
// PROD.EXAMPLE.ORG 3 2
LinkedList<String> path = new LinkedList<>();
// Un-common ones for client side
for (int i=0; i<=cPos; i++) {
path.addLast(subStringFrom(cComponents, i));
}
// Common one
if (hasCommon) {
path.addLast(subStringFrom(cComponents, cPos+1));
}
// Un-common ones for server side
for (int i=sPos; i>=0; i--) {
path.addLast(subStringFrom(sComponents, i));
}
// Remove sRealm from path. Note that it might be added at last loop
// or as a common component, if sRealm is a parent of cRealm
path.removeLast();
return path.toArray(new String[path.size()]);
}
/**
* Creates a realm name using components from the given position.
* For example, subStringFrom({"A", "B", "C"}, 1) is "B.C".
*/
private static String subStringFrom(String[] components, int from) {
StringBuilder sb = new StringBuilder();
for (int i=from; i<components.length; i++) {
if (sb.length() != 0) sb.append('.');
sb.append(components[i]);
}
return sb.toString();
}
}

View file

@ -0,0 +1,53 @@
/*
* 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;
public class RealmException extends KrbException {
private static final long serialVersionUID = -9100385213693792864L;
public RealmException(int i) {
super(i);
}
public RealmException(String s) {
super(s);
}
public RealmException(int i, String s) {
super(i,s);
}
public RealmException(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2011, 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.
*/
package sun.security.krb5;
import java.io.IOException;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Vector;
public class SCDynamicStoreConfig {
private static native void installNotificationCallback();
private static native Hashtable<String, Object> getKerberosConfig();
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
static {
boolean isMac = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
public Boolean run() {
String osname = System.getProperty("os.name");
if (osname.contains("OS X")) {
System.loadLibrary("osxkrb5");
return true;
}
return false;
}
});
if (isMac) installNotificationCallback();
}
private static Vector<String> unwrapHost(
Collection<Hashtable<String, String>> c) {
Vector<String> vector = new Vector<String>();
for (Hashtable<String, String> m : c) {
vector.add(m.get("host"));
}
return vector;
}
/**
* convertRealmConfigs: Maps the Object graph that we get from JNI to the
* object graph that Config expects. Also the items inside the kdc array
* are wrapped inside Hashtables
*/
@SuppressWarnings("unchecked")
private static Hashtable<String, Object>
convertRealmConfigs(Hashtable<String, ?> configs) {
Hashtable<String, Object> realmsTable = new Hashtable<String, Object>();
for (String realm : configs.keySet()) {
// get the kdc
Hashtable<String, Collection<?>> map =
(Hashtable<String, Collection<?>>) configs.get(realm);
Hashtable<String, Vector<String>> realmMap =
new Hashtable<String, Vector<String>>();
// put the kdc into the realmMap
Collection<Hashtable<String, String>> kdc =
(Collection<Hashtable<String, String>>) map.get("kdc");
if (kdc != null) realmMap.put("kdc", unwrapHost(kdc));
// put the admin server into the realmMap
Collection<Hashtable<String, String>> kadmin =
(Collection<Hashtable<String, String>>) map.get("kadmin");
if (kadmin != null) realmMap.put("admin_server", unwrapHost(kadmin));
// add the full entry to the realmTable
realmsTable.put(realm, realmMap);
}
return realmsTable;
}
/**
* Calls down to JNI to get the raw Kerberos Config and maps the object
* graph to the one that Kerberos Config in Java expects
*
* @return
* @throws IOException
*/
public static Hashtable<String, Object> getConfig() throws IOException {
Hashtable<String, Object> stanzaTable = getKerberosConfig();
if (stanzaTable == null) {
throw new IOException(
"Could not load configuration from SCDynamicStore");
}
if (DEBUG) System.out.println("Raw map from JNI: " + stanzaTable);
return convertNativeConfig(stanzaTable);
}
@SuppressWarnings("unchecked")
private static Hashtable<String, Object> convertNativeConfig(
Hashtable<String, Object> stanzaTable) throws IOException {
// convert SCDynamicStore realm structure to Java realm structure
Hashtable<String, ?> realms =
(Hashtable<String, ?>) stanzaTable.get("realms");
if (realms == null || realms.isEmpty()) {
throw new IOException(
"SCDynamicStore contains an empty Kerberos setting");
}
stanzaTable.remove("realms");
Hashtable<String, Object> realmsTable = convertRealmConfigs(realms);
stanzaTable.put("realms", realmsTable);
WrapAllStringInVector(stanzaTable);
if (DEBUG) System.out.println("stanzaTable : " + stanzaTable);
return stanzaTable;
}
@SuppressWarnings("unchecked")
private static void WrapAllStringInVector(
Hashtable<String, Object> stanzaTable) {
for (String s: stanzaTable.keySet()) {
Object v = stanzaTable.get(s);
if (v instanceof Hashtable) {
WrapAllStringInVector((Hashtable<String,Object>)v);
} else if (v instanceof String) {
Vector<String> vec = new Vector<>();
vec.add((String)v);
stanzaTable.put(s, vec);
}
}
}
}

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 = 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,310 @@
/*
* Copyright (c) 2001, 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;
import sun.security.krb5.*;
import java.io.IOException;
/**
* 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;
/**
* Used by a middle server to acquire credentials on behalf of a
* client to itself using the S4U2self extension.
* @param client the client to impersonate
* @param ccreds the TGT of the middle service
* @return the new creds (cname=client, sname=middle)
*/
public static Credentials acquireS4U2selfCreds(PrincipalName client,
Credentials ccreds) throws KrbException, IOException {
String uRealm = client.getRealmString();
String localRealm = ccreds.getClient().getRealmString();
if (!uRealm.equals(localRealm)) {
// TODO: we do not support kerberos referral now
throw new KrbException("Cross realm impersonation not supported");
}
if (!ccreds.isForwardable()) {
throw new KrbException("S4U2self needs a FORWARDABLE ticket");
}
KrbTgsReq req = new KrbTgsReq(
ccreds,
ccreds.getClient(),
new PAData(Krb5.PA_FOR_USER,
new PAForUserEnc(client,
ccreds.getSessionKey()).asn1Encode()));
Credentials creds = req.sendAndGetCreds();
if (!creds.getClient().equals(client)) {
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 {
KrbTgsReq req = new KrbTgsReq(
ccreds,
second,
new PrincipalName(backend));
Credentials creds = req.sendAndGetCreds();
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);
String serviceRealm = sname.getRealmString();
String localRealm = ccreds.getClient().getRealmString();
if (localRealm.equals(serviceRealm)) {
if (DEBUG) {
System.out.println(
">>> Credentials acquireServiceCreds: same realm");
}
return serviceCreds(sname, ccreds);
}
Credentials theCreds = null;
boolean[] okAsDelegate = new boolean[1];
Credentials theTgt = getTGTforRealm(localRealm, serviceRealm,
ccreds, okAsDelegate);
if (theTgt != null) {
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
+ "got right tgt");
System.out.println(">>> Credentials acquireServiceCreds: "
+ "obtaining service creds for " + sname);
}
try {
theCreds = serviceCreds(sname, theTgt);
} catch (Exception exc) {
if (DEBUG) {
System.out.println(exc);
}
theCreds = null;
}
}
if (theCreds != null) {
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
+ "returning creds:");
Credentials.printDebug(theCreds);
}
if (!okAsDelegate[0]) {
theCreds.resetDelegate();
}
return theCreds;
}
throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED,
"No service creds");
}
/**
* 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 new KrbTgsReq(ccreds, service).sendAndGetCreds();
}
}

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 = 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,88 @@
/*
* 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) {
super(
new_key,
new_lastReq,
new_nonce,
new_keyExpiration,
new_flags,
new_authtime,
new_starttime,
new_endtime,
new_renewTill,
new_sname,
new_caddr,
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,224 @@
/*
* 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.krb5.EncryptionKey;
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
* }
* }</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 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,
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;
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);
}
// 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 temp = new DerOutputStream();
DerOutputStream bytes = new DerOutputStream();
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), key.asn1Encode());
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x01), lastReq.asn1Encode());
temp.putInteger(BigInteger.valueOf(nonce));
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x02), temp);
if (keyExpiration != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x03), keyExpiration.asn1Encode());
}
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x04), flags.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());
}
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 (caddr != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x0B), caddr.asn1Encode());
}
//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, bytes);
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 = 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 = 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 = subDer.getData().getBigInteger().intValue();
} else {
usec = null;
}
if ((der.getData().peekByte() & 0x1F) == 0x03) {
subDer = der.getData().getDerValue();
seqNumber = 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,84 @@
/*
* 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) {
super(
new_key,
new_lastReq,
new_nonce,
new_keyExpiration,
new_flags,
new_authtime,
new_starttime,
new_endtime,
new_renewTill,
new_sname,
new_caddr,
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 {
StringBuilder sb = new StringBuilder();
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,330 @@
/*
* 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 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;
null,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,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.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;
private int pvno;
private int msgType;
private PAData[] pAData = null; //optional
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);
}
if ((der.getData().peekByte() & 0x1F) == 0x03) {
subDer = der.getData().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 = new PAData[v.size()];
v.copyInto(pAData);
}
} else {
pAData = null;
}
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,518 @@
/*
* 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;
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 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;
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;
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.security.util.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.security.util.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 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 = 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 = 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);
Realm 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 (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 (cname != null) {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), cname.getRealm().asn1Encode());
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(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 (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 = der.getData().getBigInteger().intValue();
}
if ((encoding.getData().peekByte() & 0x1F) == 0x03) {
der = encoding.getData().getDerValue();
seqNumber = 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,314 @@
/*
* 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() {
int temp_int = (int) ((kerberosTime % 1000L) * 1000L);
return temp_int + 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() {
return (int) (kerberosTime / 1000L);
}
/**
* 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,395 @@
/*
* 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;
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_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;
//-------------------------------+-------------
//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_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"));
public static final sun.security.util.HexDumpEncoder hexDumper =
new sun.security.util.HexDumpEncoder();
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,223 @@
/*
* 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;
import java.io.*;
import java.net.*;
import sun.security.util.IOUtils;
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.readFully(in, len, true);
} 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,327 @@
/*
* 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.KrbException;
import sun.security.util.*;
import sun.security.krb5.Asn1Exception;
import java.io.IOException;
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());
}
/**
* 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 (tmp.getParams() == null) {
// we don't support non-null s2kparams
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.getParams() == null && tmp.getEType() == eType) {
// we don't support non-null s2kparams
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.security.util.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 = 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 = 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,190 @@
/*
* Copyright (c) 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.
*/
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 {
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 String toString() {
return "PA-FOR-USER: " + name;
}
}

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,190 @@
/*
* 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)
* }
*/
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() {
StringBuilder sb = new StringBuilder();
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;
}
}
}
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,408 @@
/*
* 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.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.util.KrbDataInputStream;
import sun.security.util.IOUtils;
/**
* 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 = read(4);
usec_offset = 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.readFully(this, namelength, true);
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.readFully(this, keyLen, true);
return new EncryptionKey(bytes, keyType, 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.readFully(this, adlength, true);
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.readFully(this, length, true);
}
}
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 in stream.
* @return the next cred, null if ticket or second_ticket unparseable.
*
* Note: MIT krb5 1.8.1 might generate a config entry with server principal
* X-CACHECONF:/krb5_ccache_conf_data/fast_avail/krbtgt/REALM@REALM. The
* entry is used by KDC to inform the client that it support certain
* features. Its ticket is not a valid krb5 ticket and thus this method
* returns null.
*/
Credentials 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 {
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.
return null;
}
}
}

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.ccache;
import java.io.IOException;
import java.io.FileOutputStream;
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);
}
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,214 @@
/*
* 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 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, sname, 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 int getTktEType() {
return ticket.encPart.getEType();
}
}

View file

@ -0,0 +1,125 @@
/*
* 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.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;
/**
* 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 Credentials getCreds(PrincipalName sname);
public abstract Credentials getCreds(LoginOptions options, PrincipalName sname);
}

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,528 @@
/*
* 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.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
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;
/**
* 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) {
Credentials cred = cis.readCred(version);
if (cred != null) {
credentialsList.addElement(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]);
}
}
}
}
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;
}
}
/**
* 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 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.
// http://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/krb5cc_uid ; for all other platforms we use
* {user_home}/krb5cc_{user_name}
* Please note that for Windows we will use LSA to get
* the TGT from the default cache even before we come here;
* however when we create cache we will create a cache under
* {user_home}/krb5cc_{user_name} for non-Unix platforms including
* Windows.
*/
if (osname != null && !osname.startsWith("Windows")) {
long uid = jdk.internal.misc.VM.getuid();
if (uid != -1) {
name = File.separator + "tmp" +
File.separator + stdCacheNameComponent + "_" + uid;
if (DEBUG) {
System.out.println(">>>KinitOptions cache name is " +
name);
}
return name;
} else {
if (DEBUG) {
System.out.println("Error in obtaining uid " +
"for Unix platforms " +
"Using user's home directory");
}
}
}
// 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,176 @@
/*
* 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.crypto;
import sun.security.krb5.Config;
import sun.security.krb5.Checksum;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.KrbException;
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;
}
/**
* Returns default checksum type.
*/
public static CksumType getInstance() throws KdcErrException {
// this method provided for Kerberos applications.
int cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
try {
Config c = Config.getInstance();
if ((cksumType = (Config.getType(c.get("libdefaults",
"ap_req_checksum_type")))) == - 1) {
if ((cksumType = Config.getType(c.get("libdefaults",
"checksum_type"))) == -1) {
cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
}
}
} catch (KrbException e) {
}
return getInstance(cksumType);
}
public abstract int confounderSize();
public abstract int cksumType();
public abstract boolean isSafe();
public abstract int cksumSize();
public abstract int keyType();
public abstract int keySize();
public abstract byte[] calculateChecksum(byte[] data, int size)
throws KrbCryptoException;
public abstract byte[] calculateKeyedChecksum(byte[] data, int size,
byte[] key, int usage) throws KrbCryptoException;
public abstract boolean verifyKeyedChecksum(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,97 @@
/*
* 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.*;
import java.util.zip.CRC32;
public class Crc32CksumType extends CksumType {
public Crc32CksumType() {
}
public int confounderSize() {
return 0;
}
public int cksumType() {
return Checksum.CKSUMTYPE_CRC32;
}
public boolean isSafe() {
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) {
return crc32.byte2crc32sum_bytes(data, size);
}
public byte[] calculateKeyedChecksum(byte[] data, int size,
byte[] key, int usage) {
return null;
}
public boolean verifyKeyedChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) {
return false;
}
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;
}
}

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