|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package sun.security.ssl; |
|
|
|
import static sun.security.ssl.CipherSuite.KeyExchange.K_KRB5; |
|
import static sun.security.ssl.CipherSuite.KeyExchange.K_KRB5_EXPORT; |
|
|
|
import java.math.BigInteger; |
|
import java.net.InetAddress; |
|
import java.security.Principal; |
|
import java.security.PrivateKey; |
|
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.concurrent.ConcurrentHashMap; |
|
import java.util.concurrent.ConcurrentLinkedQueue; |
|
import javax.crypto.SecretKey; |
|
import javax.net.ssl.ExtendedSSLSession; |
|
import javax.net.ssl.SNIServerName; |
|
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; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
final class SSLSessionImpl extends ExtendedSSLSession { |
|
|
|
|
|
|
|
|
|
*/ |
|
private final ProtocolVersion protocolVersion; |
|
private final SessionId sessionId; |
|
private X509Certificate[] peerCerts; |
|
private Principal peerPrincipal; |
|
private CipherSuite cipherSuite; |
|
private SecretKey masterSecret; |
|
final boolean useExtendedMasterSecret; |
|
|
|
|
|
|
|
|
|
*/ |
|
private final long creationTime; |
|
private long lastUsedTime = 0; |
|
private final String host; |
|
private final int port; |
|
private SSLSessionContextImpl context; |
|
private boolean invalidated; |
|
private X509Certificate[] localCerts; |
|
private Principal localPrincipal; |
|
private PrivateKey localPrivateKey; |
|
private final Collection<SignatureScheme> localSupportedSignAlgs; |
|
private String[] peerSupportedSignAlgs; |
|
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 = -1; |
|
private int maximumPacketSize; |
|
|
|
private final Queue<SSLSessionImpl> childSessions = |
|
new ConcurrentLinkedQueue<>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean isSessionResumption = false; |
|
|
|
|
|
|
|
*/ |
|
private static boolean defaultRejoinable = true; |
|
|
|
|
|
final SNIServerName serverNameIndication; |
|
private final List<SNIServerName> requestedServerNames; |
|
|
|
|
|
private BigInteger ticketNonceCounter = BigInteger.ONE; |
|
|
|
// The endpoint identification algorithm used to check certificates |
|
|
|
private final String identificationProtocol; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
SSLSessionImpl() { |
|
this.protocolVersion = ProtocolVersion.NONE; |
|
this.cipherSuite = CipherSuite.C_NULL; |
|
this.sessionId = new SessionId(false, null); |
|
this.host = null; |
|
this.port = -1; |
|
this.localSupportedSignAlgs = Collections.emptySet(); |
|
this.serverNameIndication = null; |
|
this.requestedServerNames = Collections.<SNIServerName>emptyList(); |
|
this.useExtendedMasterSecret = false; |
|
this.creationTime = System.currentTimeMillis(); |
|
this.identificationProtocol = null; |
|
this.boundValues = new ConcurrentHashMap<>(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite) { |
|
this(hc, cipherSuite, |
|
new SessionId(defaultRejoinable, hc.sslContext.getSecureRandom())); |
|
} |
|
|
|
|
|
|
|
*/ |
|
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id) { |
|
this(hc, cipherSuite, id, System.currentTimeMillis()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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 = hc.localSupportedSignAlgs == null ? |
|
Collections.emptySet() : |
|
Collections.unmodifiableCollection( |
|
new ArrayList<>(hc.localSupportedSignAlgs)); |
|
this.serverNameIndication = hc.negotiatedServerName; |
|
this.requestedServerNames = Collections.unmodifiableList( |
|
new ArrayList<>(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; |
|
this.identificationProtocol = hc.sslConfig.identificationProtocol; |
|
this.boundValues = new ConcurrentHashMap<>(); |
|
|
|
if (SSLLogger.isOn && SSLLogger.isOn("session")) { |
|
SSLLogger.finest("Session initialized: " + this); |
|
} |
|
} |
|
|
|
SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId) { |
|
this.protocolVersion = baseSession.getProtocolVersion(); |
|
this.cipherSuite = baseSession.cipherSuite; |
|
this.sessionId = newId; |
|
this.host = baseSession.getPeerHost(); |
|
this.port = baseSession.getPeerPort(); |
|
this.localSupportedSignAlgs = |
|
baseSession.localSupportedSignAlgs == null ? |
|
Collections.emptySet() : baseSession.localSupportedSignAlgs; |
|
this.peerSupportedSignAlgs = |
|
baseSession.getPeerSupportedSignatureAlgorithms(); |
|
this.serverNameIndication = baseSession.serverNameIndication; |
|
this.requestedServerNames = baseSession.getRequestedServerNames(); |
|
this.masterSecret = baseSession.getMasterSecret(); |
|
this.useExtendedMasterSecret = baseSession.useExtendedMasterSecret; |
|
this.creationTime = baseSession.getCreationTime(); |
|
this.lastUsedTime = System.currentTimeMillis(); |
|
this.identificationProtocol = baseSession.getIdentificationProtocol(); |
|
this.localCerts = baseSession.localCerts; |
|
this.peerCerts = baseSession.peerCerts; |
|
this.localPrincipal = baseSession.localPrincipal; |
|
this.peerPrincipal = baseSession.peerPrincipal; |
|
this.statusResponses = baseSession.statusResponses; |
|
this.resumptionMasterSecret = baseSession.resumptionMasterSecret; |
|
this.context = baseSession.context; |
|
this.negotiatedMaxFragLen = baseSession.negotiatedMaxFragLen; |
|
this.maximumPacketSize = baseSession.maximumPacketSize; |
|
this.boundValues = baseSession.boundValues; |
|
|
|
if (SSLLogger.isOn && SSLLogger.isOn("session")) { |
|
SSLLogger.finest("Session initialized: " + this); |
|
} |
|
} |
|
|
|
void setMasterSecret(SecretKey secret) { |
|
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; |
|
} |
|
|
|
|
|
|
|
*/ |
|
SecretKey getMasterSecret() { |
|
return masterSecret; |
|
} |
|
|
|
SecretKey getResumptionMasterSecret() { |
|
return resumptionMasterSecret; |
|
} |
|
|
|
synchronized SecretKey getPreSharedKey() { |
|
return preSharedKey; |
|
} |
|
|
|
synchronized SecretKey consumePreSharedKey() { |
|
try { |
|
return preSharedKey; |
|
} finally { |
|
preSharedKey = null; |
|
} |
|
} |
|
|
|
int getTicketAgeAdd() { |
|
return ticketAgeAdd; |
|
} |
|
|
|
String getIdentificationProtocol() { |
|
return this.identificationProtocol; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
synchronized byte[] consumePskIdentity() { |
|
try { |
|
return pskIdentity; |
|
} finally { |
|
pskIdentity = null; |
|
} |
|
} |
|
|
|
void setPeerCertificates(X509Certificate[] peer) { |
|
if (peerCerts == null) { |
|
peerCerts = peer; |
|
} |
|
} |
|
|
|
void setPeerPrincipal(Principal peer) { |
|
if (peerPrincipal == null) { |
|
peerPrincipal = peer; |
|
} |
|
} |
|
|
|
void setLocalCertificates(X509Certificate[] local) { |
|
localCerts = local; |
|
} |
|
|
|
void setLocalPrincipal(Principal local) { |
|
localPrincipal = local; |
|
} |
|
|
|
void setLocalPrivateKey(PrivateKey privateKey) { |
|
localPrivateKey = privateKey; |
|
} |
|
|
|
void setPeerSupportedSignatureAlgorithms( |
|
Collection<SignatureScheme> signatureSchemes) { |
|
peerSupportedSignAlgs = |
|
SignatureScheme.getAlgorithmNames(signatureSchemes); |
|
} |
|
|
|
// 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 |
|
|
|
void setUseDefaultPeerSignAlgs() { |
|
useDefaultPeerSignAlgs = true; |
|
peerSupportedSignAlgs = new String[] { |
|
"SHA1withRSA", "SHA1withDSA", "SHA1withECDSA"}; |
|
} |
|
|
|
|
|
SSLSessionImpl finish() { |
|
if (useDefaultPeerSignAlgs) { |
|
this.peerSupportedSignAlgs = new String[0]; |
|
} |
|
|
|
return this; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void setStatusResponses(List<byte[]> responses) { |
|
if (responses != null && !responses.isEmpty()) { |
|
statusResponses = responses; |
|
} else { |
|
statusResponses = Collections.emptyList(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
boolean isRejoinable() { |
|
return sessionId != null && sessionId.length() != 0 && |
|
!invalidated && isLocalAuthenticationValid(); |
|
} |
|
|
|
@Override |
|
public synchronized boolean isValid() { |
|
return isRejoinable(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean isLocalAuthenticationValid() { |
|
if (localPrivateKey != null) { |
|
try { |
|
// if the private key is no longer valid, getAlgorithm() |
|
// should throw an exception |
|
|
|
localPrivateKey.getAlgorithm(); |
|
} catch (Exception e) { |
|
invalidate(); |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public byte[] getId() { |
|
return sessionId.getId(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public SSLSessionContext getSessionContext() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
SecurityManager sm; |
|
if ((sm = System.getSecurityManager()) != null) { |
|
sm.checkPermission(new SSLPermission("getSSLSessionContext")); |
|
} |
|
|
|
return context; |
|
} |
|
|
|
|
|
SessionId getSessionId() { |
|
return sessionId; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
CipherSuite getSuite() { |
|
return cipherSuite; |
|
} |
|
|
|
|
|
|
|
*/ |
|
void setSuite(CipherSuite suite) { |
|
cipherSuite = suite; |
|
|
|
if (SSLLogger.isOn && SSLLogger.isOn("session")) { |
|
SSLLogger.finest("Negotiating session: " + this); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
boolean isSessionResumption() { |
|
return isSessionResumption; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
void setAsSessionResumption(boolean flag) { |
|
isSessionResumption = flag; |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public String getCipherSuite() { |
|
return getSuite().name; |
|
} |
|
|
|
ProtocolVersion getProtocolVersion() { |
|
return protocolVersion; |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public String getProtocol() { |
|
return getProtocolVersion().name; |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public int hashCode() { |
|
return sessionId.hashCode(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public boolean equals(Object obj) { |
|
|
|
if (obj == this) { |
|
return true; |
|
} |
|
|
|
if (obj instanceof SSLSessionImpl) { |
|
SSLSessionImpl sess = (SSLSessionImpl) obj; |
|
return (sessionId != null) && (sessionId.equals( |
|
sess.getSessionId())); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public java.security.cert.Certificate[] getPeerCertificates() |
|
throws SSLPeerUnverifiedException { |
|
// |
|
// clone to preserve integrity of session ... caller can't |
|
// change record of peer identity even by accident, much |
|
// less do it intentionally. |
|
|
|
if ((cipherSuite.keyExchange == K_KRB5) || |
|
(cipherSuite.keyExchange == K_KRB5_EXPORT)) { |
|
throw new SSLPeerUnverifiedException("no certificates expected" |
|
+ " for Kerberos cipher suites"); |
|
} |
|
if (peerCerts == null) { |
|
throw new SSLPeerUnverifiedException("peer not authenticated"); |
|
} |
|
// Certs are immutable objects, therefore we don't clone them. |
|
// But do need to clone the array, so that nothing is inserted |
|
|
|
return (java.security.cert.Certificate[])peerCerts.clone(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public java.security.cert.Certificate[] getLocalCertificates() { |
|
// |
|
// clone to preserve integrity of session ... caller can't |
|
// change record of peer identity even by accident, much |
|
|
|
return (localCerts == null ? null : |
|
(java.security.cert.Certificate[])localCerts.clone()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
@Deprecated |
|
public javax.security.cert.X509Certificate[] getPeerCertificateChain() |
|
throws SSLPeerUnverifiedException { |
|
// |
|
// clone to preserve integrity of session ... caller can't |
|
// change record of peer identity even by accident, much |
|
// less do it intentionally. |
|
|
|
if ((cipherSuite.keyExchange == K_KRB5) || |
|
(cipherSuite.keyExchange == K_KRB5_EXPORT)) { |
|
throw new SSLPeerUnverifiedException("no certificates expected" |
|
+ " for Kerberos cipher suites"); |
|
} |
|
if (peerCerts == null) { |
|
throw new SSLPeerUnverifiedException("peer not authenticated"); |
|
} |
|
javax.security.cert.X509Certificate[] certs; |
|
certs = new javax.security.cert.X509Certificate[peerCerts.length]; |
|
for (int i = 0; i < peerCerts.length; i++) { |
|
byte[] der = null; |
|
try { |
|
der = peerCerts[i].getEncoded(); |
|
certs[i] = javax.security.cert.X509Certificate.getInstance(der); |
|
} catch (CertificateEncodingException e) { |
|
throw new SSLPeerUnverifiedException(e.getMessage()); |
|
} catch (javax.security.cert.CertificateException e) { |
|
throw new SSLPeerUnverifiedException(e.getMessage()); |
|
} |
|
} |
|
|
|
return certs; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public X509Certificate[] getCertificateChain() |
|
throws SSLPeerUnverifiedException { |
|
|
|
|
|
|
|
|
|
*/ |
|
if ((cipherSuite.keyExchange == K_KRB5) || |
|
(cipherSuite.keyExchange == K_KRB5_EXPORT)) { |
|
throw new SSLPeerUnverifiedException("no certificates expected" |
|
+ " for Kerberos cipher suites"); |
|
} |
|
if (peerCerts != null) { |
|
return peerCerts.clone(); |
|
} else { |
|
throw new SSLPeerUnverifiedException("peer not authenticated"); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public List<byte[]> getStatusResponses() { |
|
if (statusResponses == null || statusResponses.isEmpty()) { |
|
return Collections.emptyList(); |
|
} else { |
|
|
|
List<byte[]> responses = new ArrayList<>(statusResponses.size()); |
|
for (byte[] respBytes : statusResponses) { |
|
responses.add(respBytes.clone()); |
|
} |
|
return Collections.unmodifiableList(responses); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public Principal getPeerPrincipal() |
|
throws SSLPeerUnverifiedException |
|
{ |
|
if (peerCerts == null) { |
|
if (peerPrincipal != null) |
|
return peerPrincipal; |
|
throw new SSLPeerUnverifiedException("peer not authenticated"); |
|
} |
|
return peerCerts[0].getSubjectX500Principal(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public Principal getLocalPrincipal() { |
|
if (localCerts != null && localCerts.length != 0) |
|
return localCerts[0].getSubjectX500Principal(); |
|
else if (localPrincipal != null) |
|
return localPrincipal; |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public long getTicketCreationTime() { |
|
return ticketCreationTime; |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public long getCreationTime() { |
|
return creationTime; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public long getLastAccessedTime() { |
|
return (lastUsedTime != 0) ? lastUsedTime : creationTime; |
|
} |
|
|
|
void setLastAccessedTime(long time) { |
|
lastUsedTime = time; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public InetAddress getPeerAddress() { |
|
try { |
|
return InetAddress.getByName(host); |
|
} catch (java.net.UnknownHostException e) { |
|
return null; |
|
} |
|
} |
|
|
|
@Override |
|
public String getPeerHost() { |
|
return host; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public int getPeerPort() { |
|
return port; |
|
} |
|
|
|
void setContext(SSLSessionContextImpl ctx) { |
|
if (context == null) { |
|
context = ctx; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public synchronized void invalidate() { |
|
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(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private final ConcurrentHashMap<SecureKey, Object> boundValues; |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public void putValue(String key, Object value) { |
|
if ((key == null) || (value == null)) { |
|
throw new IllegalArgumentException("arguments can not be null"); |
|
} |
|
|
|
SecureKey secureKey = new SecureKey(key); |
|
Object oldValue = boundValues.put(secureKey, value); |
|
|
|
if (oldValue instanceof SSLSessionBindingListener) { |
|
SSLSessionBindingEvent e; |
|
|
|
e = new SSLSessionBindingEvent(this, key); |
|
((SSLSessionBindingListener)oldValue).valueUnbound(e); |
|
} |
|
if (value instanceof SSLSessionBindingListener) { |
|
SSLSessionBindingEvent e; |
|
|
|
e = new SSLSessionBindingEvent(this, key); |
|
((SSLSessionBindingListener)value).valueBound(e); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public Object getValue(String key) { |
|
if (key == null) { |
|
throw new IllegalArgumentException("argument can not be null"); |
|
} |
|
|
|
SecureKey secureKey = new SecureKey(key); |
|
return boundValues.get(secureKey); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public void removeValue(String key) { |
|
if (key == null) { |
|
throw new IllegalArgumentException("argument can not be null"); |
|
} |
|
|
|
SecureKey secureKey = new SecureKey(key); |
|
Object value = boundValues.remove(secureKey); |
|
|
|
if (value instanceof SSLSessionBindingListener) { |
|
SSLSessionBindingEvent e; |
|
|
|
e = new SSLSessionBindingEvent(this, key); |
|
((SSLSessionBindingListener)value).valueUnbound(e); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public String[] getValueNames() { |
|
ArrayList<Object> v = new ArrayList<>(); |
|
Object securityCtx = SecureKey.getCurrentSecurityContext(); |
|
for (Enumeration<SecureKey> e = boundValues.keys(); |
|
e.hasMoreElements(); ) { |
|
SecureKey key = e.nextElement(); |
|
if (securityCtx.equals(key.getSecurityContext())) { |
|
v.add(key.getAppKey()); |
|
} |
|
} |
|
|
|
return v.toArray(new String[0]); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean acceptLargeFragments = |
|
Utilities.getBooleanProperty( |
|
"jsse.SSLEngine.acceptLargeFragments", false); |
|
|
|
|
|
|
|
|
|
*/ |
|
protected synchronized void expandBufferSizes() { |
|
acceptLargeFragments = true; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public synchronized int getPacketBufferSize() { |
|
// Use the bigger packet size calculated from maximumPacketSize |
|
|
|
int packetSize = 0; |
|
if (negotiatedMaxFragLen > 0) { |
|
packetSize = cipherSuite.calculatePacketSize( |
|
negotiatedMaxFragLen, protocolVersion); |
|
} |
|
|
|
if (maximumPacketSize > 0) { |
|
return (maximumPacketSize > packetSize) ? |
|
maximumPacketSize : packetSize; |
|
} |
|
|
|
if (packetSize != 0) { |
|
return packetSize; |
|
} |
|
|
|
return acceptLargeFragments ? |
|
SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public synchronized int getApplicationBufferSize() { |
|
// Use the bigger fragment size calculated from maximumPacketSize |
|
|
|
int fragmentSize = 0; |
|
if (maximumPacketSize > 0) { |
|
fragmentSize = cipherSuite.calculateFragSize( |
|
maximumPacketSize, protocolVersion); |
|
} |
|
|
|
if (negotiatedMaxFragLen > 0) { |
|
return (negotiatedMaxFragLen > fragmentSize) ? |
|
negotiatedMaxFragLen : fragmentSize; |
|
} |
|
|
|
if (fragmentSize != 0) { |
|
return fragmentSize; |
|
} |
|
|
|
int maxPacketSize = acceptLargeFragments ? |
|
SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; |
|
return (maxPacketSize - SSLRecord.headerSize); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
synchronized void setNegotiatedMaxFragSize( |
|
int negotiatedMaxFragLen) { |
|
|
|
this.negotiatedMaxFragLen = negotiatedMaxFragLen; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
synchronized int getNegotiatedMaxFragSize() { |
|
return negotiatedMaxFragLen; |
|
} |
|
|
|
synchronized void setMaximumPacketSize(int maximumPacketSize) { |
|
this.maximumPacketSize = maximumPacketSize; |
|
} |
|
|
|
synchronized int getMaximumPacketSize() { |
|
return maximumPacketSize; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public String[] getLocalSupportedSignatureAlgorithms() { |
|
return SignatureScheme.getAlgorithmNames(localSupportedSignAlgs); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public Collection<SignatureScheme> getLocalSupportedSignatureSchemes() { |
|
return localSupportedSignAlgs; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public String[] getPeerSupportedSignatureAlgorithms() { |
|
if (peerSupportedSignAlgs != null) { |
|
return peerSupportedSignAlgs.clone(); |
|
} |
|
|
|
return new String[0]; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public List<SNIServerName> getRequestedServerNames() { |
|
return requestedServerNames; |
|
} |
|
|
|
|
|
@Override |
|
public String toString() { |
|
return "Session(" + creationTime + "|" + getCipherSuite() + ")"; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
class SecureKey { |
|
private static final Object nullObject = new Object(); |
|
private final Object appKey; |
|
private final Object securityCtx; |
|
|
|
static Object getCurrentSecurityContext() { |
|
SecurityManager sm = System.getSecurityManager(); |
|
Object context = null; |
|
|
|
if (sm != null) |
|
context = sm.getSecurityContext(); |
|
if (context == null) |
|
context = nullObject; |
|
return context; |
|
} |
|
|
|
SecureKey(Object key) { |
|
this.appKey = key; |
|
this.securityCtx = getCurrentSecurityContext(); |
|
} |
|
|
|
Object getAppKey() { |
|
return appKey; |
|
} |
|
|
|
Object getSecurityContext() { |
|
return securityCtx; |
|
} |
|
|
|
@Override |
|
public int hashCode() { |
|
return appKey.hashCode() ^ securityCtx.hashCode(); |
|
} |
|
|
|
@Override |
|
public boolean equals(Object o) { |
|
return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey) |
|
&& ((SecureKey)o).securityCtx.equals(securityCtx); |
|
} |
|
} |