Index: java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java =================================================================== --- java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java (revision 1798630) +++ java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java (working copy) @@ -1039,10 +1039,12 @@ // Last accessed time private long lastAccessedTime = -1; + // Cache to protect from async access + private byte[] id = SSL.getSessionId(ssl); + private long creationTime = SSL.getTime(ssl); + @Override public byte[] getId() { - // We don't cache that to keep memory usage to a minimum. - byte[] id = SSL.getSessionId(ssl); if (id == null) { // The id should never be null, if it was null then the SESSION itself was not valid. throw new IllegalStateException(sm.getString("engine.noSession")); @@ -1058,7 +1060,7 @@ @Override public long getCreationTime() { // We need to multiply by 1000 as OpenSSL uses seconds and we need milliseconds. - return SSL.getTime(ssl) * 1000L; + return creationTime * 1000L; } @Override @@ -1140,19 +1142,22 @@ // these are lazy created to reduce memory overhead Certificate[] c = peerCerts; if (c == null) { - if (SSL.isInInit(ssl) != 0) { - throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); - } - byte[][] chain = SSL.getPeerCertChain(ssl); byte[] clientCert; - if (!clientMode) { - // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. - // We use SSL_get_peer_certificate to get it in this case and add it to our array later. - // - // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html - clientCert = SSL.getPeerCertificate(ssl); - } else { - clientCert = null; + byte[][] chain; + synchronized (OpenSSLEngine.this) { + if (destroyed || SSL.isInInit(ssl) != 0) { + throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); + } + chain = SSL.getPeerCertChain(ssl); + if (!clientMode) { + // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. + // We use SSL_get_peer_certificate to get it in this case and add it to our array later. + // + // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html + clientCert = SSL.getPeerCertificate(ssl); + } else { + clientCert = null; + } } if (chain == null && clientCert == null) { return null; @@ -1193,10 +1198,13 @@ // these are lazy created to reduce memory overhead X509Certificate[] c = x509PeerCerts; if (c == null) { - if (SSL.isInInit(ssl) != 0) { - throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); + byte[][] chain; + synchronized (OpenSSLEngine.this) { + if (destroyed || SSL.isInInit(ssl) != 0) { + throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); + } + chain = SSL.getPeerCertChain(ssl); } - byte[][] chain = SSL.getPeerCertChain(ssl); if (chain == null) { throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); } @@ -1241,7 +1249,14 @@ return INVALID_CIPHER; } if (cipher == null) { - String c = OpenSSLCipherConfigurationParser.openSSLToJsse(SSL.getCipherForSSL(ssl)); + String ciphers; + synchronized (OpenSSLEngine.this) { + if (destroyed) { + return INVALID_CIPHER; + } + ciphers = SSL.getCipherForSSL(ssl); + } + String c = OpenSSLCipherConfigurationParser.openSSLToJsse(ciphers); if (c != null) { cipher = c; } @@ -1251,6 +1266,7 @@ @Override public String getProtocol() { + // No sync as ALPN is called when opening the connection String applicationProtocol = OpenSSLEngine.this.applicationProtocol; if (applicationProtocol == null) { applicationProtocol = SSL.getNextProtoNegotiated(ssl);