mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8196584: TLS 1.3 Implementation
Co-authored-by: Adam Petcher <adam.petcher@oracle.com> Co-authored-by: Amanda Jiang <amanda.jiang@oracle.com> Co-authored-by: Anthony Scarpino <anthony.scarpino@oracle.com> Co-authored-by: Bradford Wetmore <bradford.wetmore@oracle.com> Co-authored-by: Jamil Nimeh <jamil.j.nimeh@oracle.com> Co-authored-by: John Jiang <sha.jiang@oracle.com> Co-authored-by: Rajan Halade <rajan.halade@oracle.com> Co-authored-by: Sibabrata Sahoo <sibabrata.sahoo@oracle.com> Co-authored-by: Valerie Peng <valerie.peng@oracle.com> Co-authored-by: Weijun Wang <weijun.wang@oracle.com> Reviewed-by: ascarpino, coffeys, dfuchs, jjiang, jnimeh, mullan, rhalade, ssahoo, valeriep, weijun, wetmore, xuelei
This commit is contained in:
parent
c7c819cd8b
commit
87c6761704
262 changed files with 44368 additions and 32552 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -22,36 +22,31 @@
|
|||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.security.ssl;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Queue;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
import javax.net.ssl.SSLSessionBindingListener;
|
||||
import javax.net.ssl.SSLSessionBindingEvent;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLPermission;
|
||||
import javax.net.ssl.ExtendedSSLSession;
|
||||
import javax.net.ssl.SNIServerName;
|
||||
|
||||
import static sun.security.ssl.CipherSuite.KeyExchange.*;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLPermission;
|
||||
import javax.net.ssl.SSLSessionBindingEvent;
|
||||
import javax.net.ssl.SSLSessionBindingListener;
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
|
||||
/**
|
||||
* Implements the SSL session interface, and exposes the session context
|
||||
|
@ -78,9 +73,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
*/
|
||||
static final SSLSessionImpl nullSession = new SSLSessionImpl();
|
||||
|
||||
// compression methods
|
||||
private static final byte compression_null = 0;
|
||||
|
||||
/*
|
||||
* The state of a single session, as described in section 7.1
|
||||
* of the SSLv3 spec.
|
||||
|
@ -88,35 +80,37 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
private final ProtocolVersion protocolVersion;
|
||||
private final SessionId sessionId;
|
||||
private X509Certificate[] peerCerts;
|
||||
private byte compressionMethod;
|
||||
private CipherSuite cipherSuite;
|
||||
private SecretKey masterSecret;
|
||||
private final boolean useExtendedMasterSecret;
|
||||
final boolean useExtendedMasterSecret;
|
||||
|
||||
/*
|
||||
* Information not part of the SSLv3 protocol spec, but used
|
||||
* to support session management policies.
|
||||
*/
|
||||
private final long creationTime = System.currentTimeMillis();
|
||||
private final long creationTime;
|
||||
private long lastUsedTime = 0;
|
||||
private final String host;
|
||||
private final int port;
|
||||
private SSLSessionContextImpl context;
|
||||
private int sessionCount;
|
||||
private boolean invalidated;
|
||||
private X509Certificate[] localCerts;
|
||||
private PrivateKey localPrivateKey;
|
||||
private String[] localSupportedSignAlgs;
|
||||
private String[] peerSupportedSignAlgs;
|
||||
private List<SNIServerName> requestedServerNames;
|
||||
private final String[] localSupportedSignAlgs;
|
||||
private String[] peerSupportedSignAlgs; // for certificate
|
||||
private boolean useDefaultPeerSignAlgs = false;
|
||||
private List<byte[]> statusResponses;
|
||||
private SecretKey resumptionMasterSecret;
|
||||
private SecretKey preSharedKey;
|
||||
private byte[] pskIdentity;
|
||||
private final long ticketCreationTime = System.currentTimeMillis();
|
||||
private int ticketAgeAdd;
|
||||
|
||||
private int negotiatedMaxFragLen;
|
||||
private int negotiatedMaxFragLen = -1;
|
||||
private int maximumPacketSize;
|
||||
|
||||
// Principals for non-certificate based cipher suites
|
||||
private Principal peerPrincipal;
|
||||
private Principal localPrincipal;
|
||||
private final Queue<SSLSessionImpl> childSessions =
|
||||
new ConcurrentLinkedQueue<>();
|
||||
|
||||
/*
|
||||
* Is the session currently re-established with a session-resumption
|
||||
|
@ -126,20 +120,17 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
*/
|
||||
private boolean isSessionResumption = false;
|
||||
|
||||
/*
|
||||
* We count session creations, eventually for statistical data but
|
||||
* also since counters make shorter debugging IDs than the big ones
|
||||
* we use in the protocol for uniqueness-over-time.
|
||||
*/
|
||||
private static volatile int counter;
|
||||
|
||||
/*
|
||||
* Use of session caches is globally enabled/disabled.
|
||||
*/
|
||||
private static boolean defaultRejoinable = true;
|
||||
|
||||
/* Class and subclass dynamic debugging support */
|
||||
private static final Debug debug = Debug.getInstance("ssl");
|
||||
// server name indication
|
||||
final SNIServerName serverNameIndication;
|
||||
private final List<SNIServerName> requestedServerNames;
|
||||
|
||||
// Counter used to create unique nonces in NewSessionTicket
|
||||
private BigInteger ticketNonceCounter = BigInteger.ONE;
|
||||
|
||||
/*
|
||||
* Create a new non-rejoinable session, using the default (null)
|
||||
|
@ -148,8 +139,16 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* first opened and before handshaking begins.
|
||||
*/
|
||||
private SSLSessionImpl() {
|
||||
this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
|
||||
new SessionId(false, null), null, -1, false);
|
||||
this.protocolVersion = ProtocolVersion.NONE;
|
||||
this.cipherSuite = CipherSuite.C_NULL;
|
||||
this.sessionId = new SessionId(false, null);
|
||||
this.host = null;
|
||||
this.port = -1;
|
||||
this.localSupportedSignAlgs = new String[0];
|
||||
this.serverNameIndication = null;
|
||||
this.requestedServerNames = Collections.<SNIServerName>emptyList();
|
||||
this.useExtendedMasterSecret = false;
|
||||
this.creationTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -157,48 +156,81 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* be rejoinable if session caching is enabled; the constructor
|
||||
* is intended mostly for use by serves.
|
||||
*/
|
||||
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
|
||||
Collection<SignatureAndHashAlgorithm> algorithms,
|
||||
SecureRandom generator, String host, int port,
|
||||
boolean useExtendedMasterSecret) {
|
||||
this(protocolVersion, cipherSuite, algorithms,
|
||||
new SessionId(defaultRejoinable, generator), host, port,
|
||||
useExtendedMasterSecret);
|
||||
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite) {
|
||||
this(hc, cipherSuite,
|
||||
new SessionId(defaultRejoinable, hc.sslContext.getSecureRandom()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Record a new session, using a given cipher spec and session ID.
|
||||
*/
|
||||
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
|
||||
Collection<SignatureAndHashAlgorithm> algorithms,
|
||||
SessionId id, String host, int port,
|
||||
boolean useExtendedMasterSecret) {
|
||||
this.protocolVersion = protocolVersion;
|
||||
sessionId = id;
|
||||
peerCerts = null;
|
||||
compressionMethod = compression_null;
|
||||
this.cipherSuite = cipherSuite;
|
||||
masterSecret = null;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
sessionCount = ++counter;
|
||||
localSupportedSignAlgs =
|
||||
SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
|
||||
negotiatedMaxFragLen = -1;
|
||||
statusResponses = null;
|
||||
this.useExtendedMasterSecret = useExtendedMasterSecret;
|
||||
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id) {
|
||||
this(hc, cipherSuite, id, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("session")) {
|
||||
System.out.println("%% Initialized: " + this);
|
||||
/*
|
||||
* Record a new session, using a given cipher spec, session ID,
|
||||
* and creation time
|
||||
*/
|
||||
SSLSessionImpl(HandshakeContext hc,
|
||||
CipherSuite cipherSuite, SessionId id, long creationTime) {
|
||||
this.protocolVersion = hc.negotiatedProtocol;
|
||||
this.cipherSuite = cipherSuite;
|
||||
this.sessionId = id;
|
||||
this.host = hc.conContext.transport.getPeerHost();
|
||||
this.port = hc.conContext.transport.getPeerPort();
|
||||
this.localSupportedSignAlgs =
|
||||
SignatureScheme.getAlgorithmNames(hc.localSupportedSignAlgs);
|
||||
this.serverNameIndication = hc.negotiatedServerName;
|
||||
this.requestedServerNames = Collections.<SNIServerName>unmodifiableList(
|
||||
hc.getRequestedServerNames());
|
||||
if (hc.sslConfig.isClientMode) {
|
||||
this.useExtendedMasterSecret =
|
||||
(hc.handshakeExtensions.get(
|
||||
SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) &&
|
||||
(hc.handshakeExtensions.get(
|
||||
SSLExtension.SH_EXTENDED_MASTER_SECRET) != null);
|
||||
} else {
|
||||
this.useExtendedMasterSecret =
|
||||
(hc.handshakeExtensions.get(
|
||||
SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) &&
|
||||
(!hc.negotiatedProtocol.useTLS13PlusSpec());
|
||||
}
|
||||
this.creationTime = creationTime;
|
||||
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("session")) {
|
||||
SSLLogger.finest("Session initialized: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
void setMasterSecret(SecretKey secret) {
|
||||
if (masterSecret == null) {
|
||||
masterSecret = secret;
|
||||
} else {
|
||||
throw new RuntimeException("setMasterSecret() error");
|
||||
}
|
||||
masterSecret = secret;
|
||||
}
|
||||
|
||||
void setResumptionMasterSecret(SecretKey secret) {
|
||||
resumptionMasterSecret = secret;
|
||||
}
|
||||
|
||||
void setPreSharedKey(SecretKey key) {
|
||||
preSharedKey = key;
|
||||
}
|
||||
|
||||
void addChild(SSLSessionImpl session) {
|
||||
childSessions.add(session);
|
||||
}
|
||||
|
||||
void setTicketAgeAdd(int ticketAgeAdd) {
|
||||
this.ticketAgeAdd = ticketAgeAdd;
|
||||
}
|
||||
|
||||
void setPskIdentity(byte[] pskIdentity) {
|
||||
this.pskIdentity = pskIdentity;
|
||||
}
|
||||
|
||||
BigInteger incrTicketNonceCounter() {
|
||||
BigInteger result = ticketNonceCounter;
|
||||
ticketNonceCounter = ticketNonceCounter.add(BigInteger.valueOf(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -208,8 +240,39 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
return masterSecret;
|
||||
}
|
||||
|
||||
boolean getUseExtendedMasterSecret() {
|
||||
return useExtendedMasterSecret;
|
||||
Optional<SecretKey> getResumptionMasterSecret() {
|
||||
return Optional.ofNullable(resumptionMasterSecret);
|
||||
}
|
||||
|
||||
synchronized Optional<SecretKey> getPreSharedKey() {
|
||||
return Optional.ofNullable(preSharedKey);
|
||||
}
|
||||
|
||||
synchronized Optional<SecretKey> consumePreSharedKey() {
|
||||
Optional<SecretKey> result = Optional.ofNullable(preSharedKey);
|
||||
preSharedKey = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
int getTicketAgeAdd() {
|
||||
return ticketAgeAdd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the PSK identity. Take care not to use it in multiple connections.
|
||||
*/
|
||||
synchronized Optional<byte[]> getPskIdentity() {
|
||||
return Optional.ofNullable(pskIdentity);
|
||||
}
|
||||
|
||||
/* PSK identities created from new_session_ticket messages should only
|
||||
* be used once. This method will return the identity and then clear it
|
||||
* so it cannot be used again.
|
||||
*/
|
||||
synchronized Optional<byte[]> consumePskIdentity() {
|
||||
Optional<byte[]> result = Optional.ofNullable(pskIdentity);
|
||||
pskIdentity = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
void setPeerCertificates(X509Certificate[] peer) {
|
||||
|
@ -227,13 +290,35 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
}
|
||||
|
||||
void setPeerSupportedSignatureAlgorithms(
|
||||
Collection<SignatureAndHashAlgorithm> algorithms) {
|
||||
Collection<SignatureScheme> signatureSchemes) {
|
||||
peerSupportedSignAlgs =
|
||||
SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
|
||||
SignatureScheme.getAlgorithmNames(signatureSchemes);
|
||||
}
|
||||
|
||||
void setRequestedServerNames(List<SNIServerName> requestedServerNames) {
|
||||
this.requestedServerNames = new ArrayList<>(requestedServerNames);
|
||||
// TLS 1.2 only
|
||||
//
|
||||
// Per RFC 5246, If the client supports only the default hash
|
||||
// and signature algorithms, it MAY omit the
|
||||
// signature_algorithms extension. If the client does not
|
||||
// support the default algorithms, or supports other hash
|
||||
// and signature algorithms (and it is willing to use them
|
||||
// for verifying messages sent by the server, i.e., server
|
||||
// certificates and server key exchange), it MUST send the
|
||||
// signature_algorithms extension, listing the algorithms it
|
||||
// is willing to accept.
|
||||
void setUseDefaultPeerSignAlgs() {
|
||||
useDefaultPeerSignAlgs = true;
|
||||
peerSupportedSignAlgs = new String[] {
|
||||
"SHA1withRSA", "SHA1withDSA", "SHA1withECDSA"};
|
||||
}
|
||||
|
||||
// Returns the connection session.
|
||||
SSLSessionImpl finish() {
|
||||
if (useDefaultPeerSignAlgs) {
|
||||
this.peerSupportedSignAlgs = new String[0];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,22 +334,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the peer principal.
|
||||
*/
|
||||
void setPeerPrincipal(Principal principal) {
|
||||
if (peerPrincipal == null) {
|
||||
peerPrincipal = principal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the local principal.
|
||||
*/
|
||||
void setLocalPrincipal(Principal principal) {
|
||||
localPrincipal = principal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff this session may be resumed ... sessions are
|
||||
* usually resumable. Security policies may suggest otherwise,
|
||||
|
@ -286,7 +355,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* Check if the authentication used when establishing this session
|
||||
* is still valid. Returns true if no authentication was used
|
||||
*/
|
||||
boolean isLocalAuthenticationValid() {
|
||||
private boolean isLocalAuthenticationValid() {
|
||||
if (localPrivateKey != null) {
|
||||
try {
|
||||
// if the private key is no longer valid, getAlgorithm()
|
||||
|
@ -298,6 +367,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -354,8 +424,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
void setSuite(CipherSuite suite) {
|
||||
cipherSuite = suite;
|
||||
|
||||
if (debug != null && Debug.isOn("session")) {
|
||||
System.out.println("%% Negotiating: " + this);
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("session")) {
|
||||
SSLLogger.finest("Negotiating session: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,13 +465,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
return getProtocolVersion().name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the compression technique used in this session
|
||||
*/
|
||||
byte getCompression() {
|
||||
return compressionMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashcode for this session
|
||||
*/
|
||||
|
@ -410,7 +473,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
return sessionId.hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if sessions have same ids, false otherwise.
|
||||
*/
|
||||
|
@ -435,8 +497,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* Return the cert chain presented by the peer in the
|
||||
* java.security.cert format.
|
||||
* Note: This method can be used only when using certificate-based
|
||||
* cipher suites; using it with non-certificate-based cipher suites,
|
||||
* such as Kerberos, will throw an SSLPeerUnverifiedException.
|
||||
* cipher suites; using it with non-certificate-based cipher suites
|
||||
* will throw an SSLPeerUnverifiedException.
|
||||
*
|
||||
* @return array of peer X.509 certs, with the peer's own cert
|
||||
* first in the chain, and with the "root" CA last.
|
||||
|
@ -449,10 +511,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
// change record of peer identity even by accident, much
|
||||
// less do it intentionally.
|
||||
//
|
||||
if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) {
|
||||
throw new SSLPeerUnverifiedException("no certificates expected"
|
||||
+ " for " + cipherSuite.keyExchange + " cipher suites");
|
||||
}
|
||||
if (peerCerts == null) {
|
||||
throw new SSLPeerUnverifiedException("peer not authenticated");
|
||||
}
|
||||
|
@ -485,8 +543,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* Return the cert chain presented by the peer in the
|
||||
* javax.security.cert format.
|
||||
* Note: This method can be used only when using certificate-based
|
||||
* cipher suites; using it with non-certificate-based cipher suites,
|
||||
* such as Kerberos, will throw an SSLPeerUnverifiedException.
|
||||
* cipher suites; using it with non-certificate-based cipher suites
|
||||
* will throw an SSLPeerUnverifiedException.
|
||||
*
|
||||
* @return array of peer X.509 certs, with the peer's own cert
|
||||
* first in the chain, and with the "root" CA last.
|
||||
|
@ -504,10 +562,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
// change record of peer identity even by accident, much
|
||||
// less do it intentionally.
|
||||
//
|
||||
if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) {
|
||||
throw new SSLPeerUnverifiedException("no certificates expected"
|
||||
+ " for " + cipherSuite.keyExchange + " cipher suites");
|
||||
}
|
||||
if (peerCerts == null) {
|
||||
throw new SSLPeerUnverifiedException("peer not authenticated");
|
||||
}
|
||||
|
@ -531,8 +585,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
/**
|
||||
* Return the cert chain presented by the peer.
|
||||
* Note: This method can be used only when using certificate-based
|
||||
* cipher suites; using it with non-certificate-based cipher suites,
|
||||
* such as Kerberos, will throw an SSLPeerUnverifiedException.
|
||||
* cipher suites; using it with non-certificate-based cipher suites
|
||||
* will throw an SSLPeerUnverifiedException.
|
||||
*
|
||||
* @return array of peer X.509 certs, with the peer's own cert
|
||||
* first in the chain, and with the "root" CA last.
|
||||
|
@ -544,10 +598,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* change record of peer identity even by accident, much
|
||||
* less do it intentionally.
|
||||
*/
|
||||
if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) {
|
||||
throw new SSLPeerUnverifiedException("no certificates expected"
|
||||
+ " for " + cipherSuite.keyExchange + " cipher suites");
|
||||
}
|
||||
if (peerCerts != null) {
|
||||
return peerCerts.clone();
|
||||
} else {
|
||||
|
@ -584,8 +634,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* defining the session.
|
||||
*
|
||||
* @return the peer's principal. Returns an X500Principal of the
|
||||
* end-entity certificate for X509-based cipher suites, and
|
||||
* Principal for Kerberos cipher suites, etc.
|
||||
* end-entity certificate for X509-based cipher suites.
|
||||
*
|
||||
* @throws SSLPeerUnverifiedException if the peer's identity has not
|
||||
* been verified
|
||||
|
@ -594,13 +643,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
public Principal getPeerPrincipal()
|
||||
throws SSLPeerUnverifiedException
|
||||
{
|
||||
if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) {
|
||||
if (peerPrincipal == null) {
|
||||
throw new SSLPeerUnverifiedException("peer not authenticated");
|
||||
} else {
|
||||
return peerPrincipal;
|
||||
}
|
||||
}
|
||||
if (peerCerts == null) {
|
||||
throw new SSLPeerUnverifiedException("peer not authenticated");
|
||||
}
|
||||
|
@ -611,20 +653,22 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* Returns the principal that was sent to the peer during handshaking.
|
||||
*
|
||||
* @return the principal sent to the peer. Returns an X500Principal
|
||||
* of the end-entity certificate for X509-based cipher suites, and
|
||||
* Principal for Kerberos cipher suites, etc. If no principal was
|
||||
* sent, then null is returned.
|
||||
* of the end-entity certificate for X509-based cipher suites.
|
||||
* If no principal was sent, then null is returned.
|
||||
*/
|
||||
@Override
|
||||
public Principal getLocalPrincipal() {
|
||||
|
||||
if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) {
|
||||
return (localPrincipal == null ? null : localPrincipal);
|
||||
}
|
||||
return (localCerts == null ? null :
|
||||
return ((localCerts == null && localCerts.length != 0) ? null :
|
||||
localCerts[0].getSubjectX500Principal());
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the time the ticket for this session was created.
|
||||
*/
|
||||
public long getTicketCreationTime() {
|
||||
return ticketCreationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time this session was created.
|
||||
*/
|
||||
|
@ -695,14 +739,21 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
if (this == nullSession) {
|
||||
return;
|
||||
}
|
||||
invalidated = true;
|
||||
if (debug != null && Debug.isOn("session")) {
|
||||
System.out.println("%% Invalidated: " + this);
|
||||
}
|
||||
|
||||
if (context != null) {
|
||||
context.remove(sessionId);
|
||||
context = null;
|
||||
}
|
||||
if (invalidated) {
|
||||
return;
|
||||
}
|
||||
invalidated = true;
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("session")) {
|
||||
SSLLogger.finest("Invalidated session: " + this);
|
||||
}
|
||||
for (SSLSessionImpl child : childSessions) {
|
||||
child.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -710,7 +761,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* key and the calling security context. This is important since
|
||||
* sessions can be shared across different protection domains.
|
||||
*/
|
||||
private Hashtable<SecureKey, Object> table = new Hashtable<>();
|
||||
private final ConcurrentHashMap<SecureKey, Object> boundValues =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Assigns a session value. Session change events are given if
|
||||
|
@ -723,7 +775,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
}
|
||||
|
||||
SecureKey secureKey = new SecureKey(key);
|
||||
Object oldValue = table.put(secureKey, value);
|
||||
Object oldValue = boundValues.put(secureKey, value);
|
||||
|
||||
if (oldValue instanceof SSLSessionBindingListener) {
|
||||
SSLSessionBindingEvent e;
|
||||
|
@ -739,7 +791,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the specified session value.
|
||||
*/
|
||||
|
@ -750,7 +801,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
}
|
||||
|
||||
SecureKey secureKey = new SecureKey(key);
|
||||
return table.get(secureKey);
|
||||
return boundValues.get(secureKey);
|
||||
}
|
||||
|
||||
|
||||
|
@ -765,7 +816,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
}
|
||||
|
||||
SecureKey secureKey = new SecureKey(key);
|
||||
Object value = table.remove(secureKey);
|
||||
Object value = boundValues.remove(secureKey);
|
||||
|
||||
if (value instanceof SSLSessionBindingListener) {
|
||||
SSLSessionBindingEvent e;
|
||||
|
@ -781,22 +832,17 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
*/
|
||||
@Override
|
||||
public String[] getValueNames() {
|
||||
Enumeration<SecureKey> e;
|
||||
Vector<Object> v = new Vector<>();
|
||||
SecureKey key;
|
||||
ArrayList<Object> v = new ArrayList<>();
|
||||
Object securityCtx = SecureKey.getCurrentSecurityContext();
|
||||
|
||||
for (e = table.keys(); e.hasMoreElements(); ) {
|
||||
key = e.nextElement();
|
||||
|
||||
for (Enumeration<SecureKey> e = boundValues.keys();
|
||||
e.hasMoreElements(); ) {
|
||||
SecureKey key = e.nextElement();
|
||||
if (securityCtx.equals(key.getSecurityContext())) {
|
||||
v.addElement(key.getAppKey());
|
||||
v.add(key.getAppKey());
|
||||
}
|
||||
}
|
||||
String[] names = new String[v.size()];
|
||||
v.copyInto(names);
|
||||
|
||||
return names;
|
||||
return v.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -813,7 +859,8 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
* to "true".
|
||||
*/
|
||||
private boolean acceptLargeFragments =
|
||||
Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false);
|
||||
Utilities.getBooleanProperty(
|
||||
"jsse.SSLEngine.acceptLargeFragments", false);
|
||||
|
||||
/**
|
||||
* Expand the buffer size of both SSL/TLS network packet and
|
||||
|
@ -835,7 +882,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
if (negotiatedMaxFragLen > 0) {
|
||||
packetSize = cipherSuite.calculatePacketSize(
|
||||
negotiatedMaxFragLen, protocolVersion,
|
||||
protocolVersion.isDTLSProtocol());
|
||||
protocolVersion.isDTLS);
|
||||
}
|
||||
|
||||
if (maximumPacketSize > 0) {
|
||||
|
@ -847,7 +894,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
return packetSize;
|
||||
}
|
||||
|
||||
if (protocolVersion.isDTLSProtocol()) {
|
||||
if (protocolVersion.isDTLS) {
|
||||
return DTLSRecord.maxRecordSize;
|
||||
} else {
|
||||
return acceptLargeFragments ?
|
||||
|
@ -867,7 +914,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
if (maximumPacketSize > 0) {
|
||||
fragmentSize = cipherSuite.calculateFragSize(
|
||||
maximumPacketSize, protocolVersion,
|
||||
protocolVersion.isDTLSProtocol());
|
||||
protocolVersion.isDTLS);
|
||||
}
|
||||
|
||||
if (negotiatedMaxFragLen > 0) {
|
||||
|
@ -879,7 +926,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
return fragmentSize;
|
||||
}
|
||||
|
||||
if (protocolVersion.isDTLSProtocol()) {
|
||||
if (protocolVersion.isDTLS) {
|
||||
return Record.maxDataSize;
|
||||
} else {
|
||||
int maxPacketSize = acceptLargeFragments ?
|
||||
|
@ -953,33 +1000,24 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||
*/
|
||||
@Override
|
||||
public List<SNIServerName> getRequestedServerNames() {
|
||||
if (requestedServerNames != null && !requestedServerNames.isEmpty()) {
|
||||
return Collections.<SNIServerName>unmodifiableList(
|
||||
requestedServerNames);
|
||||
}
|
||||
|
||||
return Collections.<SNIServerName>emptyList();
|
||||
return requestedServerNames;
|
||||
}
|
||||
|
||||
/** Returns a string representation of this SSL session */
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Session-" + sessionCount
|
||||
+ ", " + getCipherSuite()
|
||||
+ "]";
|
||||
return "Session(" + creationTime + "|" + getCipherSuite() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This "struct" class serves as a Hash Key that combines an
|
||||
* application-specific key and a security context.
|
||||
*/
|
||||
class SecureKey {
|
||||
private static Object nullObject = new Object();
|
||||
private Object appKey;
|
||||
private Object securityCtx;
|
||||
private static final Object nullObject = new Object();
|
||||
private final Object appKey;
|
||||
private final Object securityCtx;
|
||||
|
||||
static Object getCurrentSecurityContext() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue