/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* This is Kerberos option in the client key exchange message
* (CLIENT -> SERVER). It holds the Kerberos ticket and the encrypted
* premaster secret encrypted with the session key sealed in the ticket.
* From RFC 2712:
* struct
* {
* opaque Ticket;
* opaque authenticator; // optional
* opaque EncryptedPreMasterSecret; // encrypted with the session key
* // which is sealed in the ticket
* } KerberosWrapper;
*
*
* Ticket and authenticator are encrypted as per RFC 1510 (in ASN.1)
* Encrypted pre-master secret has the same structure as it does for RSA
* except for Kerberos, the encryption key is the session key instead of
* the RSA public key.
*
* XXX authenticator currently ignored
*
*/
public final class KerberosClientKeyExchangeImpl
private byte[] encodedTicket;
public KerberosClientKeyExchangeImpl() {
}
/**
* Creates an instance of KerberosClientKeyExchange consisting of the
* Kerberos service ticket, authenticator and encrypted premaster secret.
* Called by client handshaker.
*
* @param serverName name of server with which to do handshake;
* this is used to get the Kerberos service ticket
* @param protocolVersion Maximum version supported by client (i.e,
* version it requested in client hello)
* @param rand random number generator to use for generating pre-master
* secret
*/
// Get service ticket
// Record the Kerberos principals
// Optional authenticator, encrypted using session key,
// currently ignored
// Generate premaster secret and encrypt it using session key
rand, sessionKey);
}
/**
* Creates an instance of KerberosClientKeyExchange from its ASN.1 encoding.
* Used by ServerHandshaker to verify and obtain premaster secret.
*
* @param protocolVersion current protocol version
* @param clientVersion version requested by client in its ClientHello;
* used by premaster secret version check
* @param rand random number generator used for generating random
* @param input inputstream from which to get ASN.1-encoded KerberosWrapper
* @param serverKey server's master secret key
*/
throws IOException {
// Read ticket
"encoded Kerberos service ticket", encodedTicket);
}
try {
/*
* permission to access and use the secret key of the Kerberized
* "host" service is done in ServerHandshaker.getKerberosKeys()
* to ensure server has the permission to use the secret key
* before promising the client
*/
// Check that ticket Sname matches serverPrincipal
ticketRealm.toString());
+ " match associated principal in KerberosKey");
throw new IOException("Server principal is " +
serverPrincipal + " but ticket is for " +
}
// See if we have the right key to decrypt the ticket to get
// the session key.
try {
throw new IOException(
"Cannot find key matching version number", ke);
}
// %%% Should print string repr of etype
throw new IOException(
"Cannot find key of appropriate type to decrypt ticket - need etype " +
}
dkey.getEncoded());
// Decrypt encPart using server's secret key
// Reset data stream after decryption, remove redundant bytes
// Record the Kerberos Principals
}
} catch (IOException e) {
throw e;
} catch (Exception e) {
}
sessionKey = null;
}
if (sessionKey != null) {
} else {
// Generate bogus premaster secret
}
}
public int messageLength() {
}
}
s.println("*** ClientKeyExchange, Kerberos");
}
}
// Similar to sun.security.jgss.krb5.Krb5InitCredenetial/Krb5Context
// get the local hostname if srvName is loopback address
if (isLoopback) {
try {
hostname = "localhost";
}
return hostname;
}
});
}
// Resolve serverName (possibly in IP addr form) to Kerberos principal
// name for service with hostname
try {
} catch (SecurityException se) {
throw se;
} catch (Exception e) {
" name: " + serviceName);
throw ioe;
}
// check permission to obtain a service ticket to initiate a
// context with the "host" service
"initiate"), acc);
}
try {
new PrivilegedExceptionAction<KerberosTicket>() {
return Krb5Util.getTicketFromSubjectAndTgs(
tgsPrincipal, acc);
}});
throw new IOException("Failed to find any kerberos service" +
" ticket for " + serverPrincipal);
}
return ticket;
} catch (PrivilegedActionException e) {
"Attempt to obtain kerberos service ticket for " +
serverPrincipal + " failed!");
throw ioe;
}
}
public byte[] getUnencryptedPreMasterSecret() {
return preMaster.getUnencrypted();
}
return peerPrincipal;
}
return localPrincipal;
}
/**
* Determines if a kvno matches another kvno. Used in the method
* findKey(etype, version, 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
* EncryptionKey and KerberosKey.
*/
return true;
}
}
int ktype;
boolean etypeFound = false;
etypeFound = true;
return keys[i];
}
}
}
// Key not found.
// %%% kludge to allow DES keys to be used for diff etypes
etypeFound = true;
keys[i].getEncoded(),
keys[i].getVersionNumber());
}
}
}
}
if (etypeFound) {
}
return null;
}
}