* @throws SSLPeerUnverifiedException if the peer's identity has not * been verified */ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { if ((cipherSuite.keyExchange == K_KRB5) || (cipherSuite.keyExchange == K_KRB5_EXPORT)) { if (peerPrincipal == null) { throw new SSLPeerUnverifiedException("peer not authenticated"); } else { // Eliminate dependency on KerberosPrincipal return peerPrincipal; } } if (peerCerts == null) { throw new SSLPeerUnverifiedException("peer not authenticated"); } return peerCerts[0].getSubjectX500Principal(); } /** * 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. If no principal was * sent, then null is returned. */ public Principal getLocalPrincipal() { if ((cipherSuite.keyExchange == K_KRB5) || (cipherSuite.keyExchange == K_KRB5_EXPORT)) { // Eliminate dependency on KerberosPrincipal return (localPrincipal == null ? null : localPrincipal); } return (localCerts == null ? null : localCerts[0].getSubjectX500Principal()); } /** * Returns the time this session was created. */ public long getCreationTime() { return creationTime; } /** * Returns the last time this session was used to initialize * a connection. */ public long getLastAccessedTime() { return (lastUsedTime != 0) ? lastUsedTime : creationTime; } void setLastAccessedTime(long time) { lastUsedTime = time; } /** * Returns the network address of the session's peer. This * implementation does not insist that connections between * different ports on the same host must necessarily belong * to different sessions, though that is of course allowed. */ public InetAddress getPeerAddress() { try { return InetAddress.getByName(host); } catch (java.net.UnknownHostException e) { return null; } } public String getPeerHost() { return host; } /** * Need to provide the port info for caching sessions based on * host and port. Accessed by SSLSessionContextImpl */ public int getPeerPort() { return port; } void setContext(SSLSessionContextImpl ctx) { if (context == null) { context = ctx; } } /** * Invalidate a session. Active connections may still exist, but * no connections will be able to rejoin this session. */ synchronized public void invalidate() { // // Can't invalidate the NULL session -- this would be // attempted when we get a handshaking error on a brand // new connection, with no "real" session yet. // 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; } } /* * Table of application-specific session data indexed by an application * 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<>(); /** * Assigns a session value. Session change events are given if * appropriate, to any original value as well as the new value. */ 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 = table.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); } } /** * Returns the specified session value. */ public Object getValue(String key) { if (key == null) { throw new IllegalArgumentException("argument can not be null"); } SecureKey secureKey = new SecureKey(key); return table.get(secureKey); } /** * Removes the specified session value, delivering a session changed * event as appropriate. */ public void removeValue(String key) { if (key == null) { throw new IllegalArgumentException("argument can not be null"); } SecureKey secureKey = new SecureKey(key); Object value = table.remove(secureKey); if (value instanceof SSLSessionBindingListener) { SSLSessionBindingEvent e; e = new SSLSessionBindingEvent(this, key); ((SSLSessionBindingListener)value).valueUnbound(e); } } /** * Lists the names of the session values. */ public String[] getValueNames() { Enumeration<SecureKey> e; Vector<Object> v = new Vector<>(); SecureKey key; Object securityCtx = SecureKey.getCurrentSecurityContext(); for (e = table.keys(); e.hasMoreElements(); ) { key = e.nextElement(); if (securityCtx.equals(key.getSecurityContext())) { v.addElement(key.getAppKey()); } } String[] names = new String[v.size()]; v.copyInto(names); return names; } /** * Use large packet sizes now or follow RFC 2246 packet sizes (2^14) * until changed. * * In the TLS specification (section 6.2.1, RFC2246), it is not * recommended that the plaintext has more than 2^14 bytes. * However, some TLS implementations violate the specification. * This is a workaround for interoperability with these stacks. * * Application could accept large fragments up to 2^15 bytes by * setting the system property jsse.SSLEngine.acceptLargeFragments * to "true". */ private boolean acceptLargeFragments = Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false); /** * Expand the buffer size of both SSL/TLS network packet and * application data. */ protected synchronized void expandBufferSizes() { acceptLargeFragments = true; } /** * Gets the current size of the largest SSL/TLS packet that is expected * when using this session. */ public synchronized int getPacketBufferSize() { return acceptLargeFragments ? Record.maxLargeRecordSize : Record.maxRecordSize; } /** * Gets the current size of the largest application data that is * expected when using this session. */ public synchronized int getApplicationBufferSize() { return getPacketBufferSize() - Record.headerSize; } /** * Gets an array of supported signature algorithms that the local side is * willing to verify. */ public String[] getLocalSupportedSignatureAlgorithms() { if (localSupportedSignAlgs != null) { return localSupportedSignAlgs.clone(); } return new String[0]; } /** * Gets an array of supported signature algorithms that the peer is * able to verify. */ public String[] getPeerSupportedSignatureAlgorithms() { if (peerSupportedSignAlgs != null) { return peerSupportedSignAlgs.clone(); } return new String[0]; } /** Returns a string representation of this SSL session */ public String toString() { return "[Session-" + sessionCount + ", " + getCipherSuite() + "]"; } /** * When SSL sessions are finalized, all values bound to * them are removed. */ public void finalize() { String[] names = getValueNames(); for (int i = 0; i < names.length; i++) { removeValue(names[i]); } }} /** * 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; 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; } public int hashCode() { return appKey.hashCode() ^ securityCtx.hashCode(); } public boolean equals(Object o) { return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey) && ((SecureKey)o).securityCtx.equals(securityCtx); }}Lines 501–832 of 832. Previous lines
* @throws SSLPeerUnverifiedException if the peer's identity has not * been verified */ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { if ((cipherSuite.keyExchange == K_KRB5) || (cipherSuite.keyExchange == K_KRB5_EXPORT)) { if (peerPrincipal == null) { throw new SSLPeerUnverifiedException("peer not authenticated"); } else { // Eliminate dependency on KerberosPrincipal return peerPrincipal; } } if (peerCerts == null) { throw new SSLPeerUnverifiedException("peer not authenticated"); } return peerCerts[0].getSubjectX500Principal(); } /** * 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. If no principal was * sent, then null is returned. */ public Principal getLocalPrincipal() { if ((cipherSuite.keyExchange == K_KRB5) || (cipherSuite.keyExchange == K_KRB5_EXPORT)) { // Eliminate dependency on KerberosPrincipal return (localPrincipal == null ? null : localPrincipal); } return (localCerts == null ? null : localCerts[0].getSubjectX500Principal()); } /** * Returns the time this session was created. */ public long getCreationTime() { return creationTime; } /** * Returns the last time this session was used to initialize * a connection. */ public long getLastAccessedTime() { return (lastUsedTime != 0) ? lastUsedTime : creationTime; } void setLastAccessedTime(long time) { lastUsedTime = time; } /** * Returns the network address of the session's peer. This * implementation does not insist that connections between * different ports on the same host must necessarily belong * to different sessions, though that is of course allowed. */ public InetAddress getPeerAddress() { try { return InetAddress.getByName(host); } catch (java.net.UnknownHostException e) { return null; } } public String getPeerHost() { return host; } /** * Need to provide the port info for caching sessions based on * host and port. Accessed by SSLSessionContextImpl */ public int getPeerPort() { return port; } void setContext(SSLSessionContextImpl ctx) { if (context == null) { context = ctx; } } /** * Invalidate a session. Active connections may still exist, but * no connections will be able to rejoin this session. */ synchronized public void invalidate() { // // Can't invalidate the NULL session -- this would be // attempted when we get a handshaking error on a brand // new connection, with no "real" session yet. // 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; } } /* * Table of application-specific session data indexed by an application * 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<>(); /** * Assigns a session value. Session change events are given if * appropriate, to any original value as well as the new value. */ 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 = table.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); } } /** * Returns the specified session value. */ public Object getValue(String key) { if (key == null) { throw new IllegalArgumentException("argument can not be null"); } SecureKey secureKey = new SecureKey(key); return table.get(secureKey); } /** * Removes the specified session value, delivering a session changed * event as appropriate. */ public void removeValue(String key) { if (key == null) { throw new IllegalArgumentException("argument can not be null"); } SecureKey secureKey = new SecureKey(key); Object value = table.remove(secureKey); if (value instanceof SSLSessionBindingListener) { SSLSessionBindingEvent e; e = new SSLSessionBindingEvent(this, key); ((SSLSessionBindingListener)value).valueUnbound(e); } } /** * Lists the names of the session values. */ public String[] getValueNames() { Enumeration<SecureKey> e; Vector<Object> v = new Vector<>(); SecureKey key; Object securityCtx = SecureKey.getCurrentSecurityContext(); for (e = table.keys(); e.hasMoreElements(); ) { key = e.nextElement(); if (securityCtx.equals(key.getSecurityContext())) { v.addElement(key.getAppKey()); } } String[] names = new String[v.size()]; v.copyInto(names); return names; } /** * Use large packet sizes now or follow RFC 2246 packet sizes (2^14) * until changed. * * In the TLS specification (section 6.2.1, RFC2246), it is not * recommended that the plaintext has more than 2^14 bytes. * However, some TLS implementations violate the specification. * This is a workaround for interoperability with these stacks. * * Application could accept large fragments up to 2^15 bytes by * setting the system property jsse.SSLEngine.acceptLargeFragments * to "true". */ private boolean acceptLargeFragments = Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false); /** * Expand the buffer size of both SSL/TLS network packet and * application data. */ protected synchronized void expandBufferSizes() { acceptLargeFragments = true; } /** * Gets the current size of the largest SSL/TLS packet that is expected * when using this session. */ public synchronized int getPacketBufferSize() { return acceptLargeFragments ? Record.maxLargeRecordSize : Record.maxRecordSize; } /** * Gets the current size of the largest application data that is * expected when using this session. */ public synchronized int getApplicationBufferSize() { return getPacketBufferSize() - Record.headerSize; } /** * Gets an array of supported signature algorithms that the local side is * willing to verify. */ public String[] getLocalSupportedSignatureAlgorithms() { if (localSupportedSignAlgs != null) { return localSupportedSignAlgs.clone(); } return new String[0]; } /** * Gets an array of supported signature algorithms that the peer is * able to verify. */ public String[] getPeerSupportedSignatureAlgorithms() { if (peerSupportedSignAlgs != null) { return peerSupportedSignAlgs.clone(); } return new String[0]; } /** Returns a string representation of this SSL session */ public String toString() { return "[Session-" + sessionCount + ", " + getCipherSuite() + "]"; } /** * When SSL sessions are finalized, all values bound to * them are removed. */ public void finalize() { String[] names = getValueNames(); for (int i = 0; i < names.length; i++) { removeValue(names[i]); } } } /** * 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; 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; } public int hashCode() { return appKey.hashCode() ^ securityCtx.hashCode(); } public boolean equals(Object o) { return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey) && ((SecureKey)o).securityCtx.equals(securityCtx); } }