| /* Session.java -- SSL and TLS session data. |
| Copyright (C) 2006 Free Software Foundation, Inc. |
| |
| This file is a part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or (at |
| your option) any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 |
| USA |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package gnu.javax.net.ssl.provider; |
| |
| import java.security.SecureRandom; |
| import java.security.cert.Certificate; |
| import java.security.cert.CertificateException; |
| |
| import java.util.Arrays; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.SortedSet; |
| import java.util.TreeSet; |
| |
| import javax.net.ssl.SSLPeerUnverifiedException; |
| import javax.net.ssl.SSLPermission; |
| import javax.net.ssl.SSLSession; |
| import javax.net.ssl.SSLSessionBindingEvent; |
| import javax.net.ssl.SSLSessionBindingListener; |
| import javax.net.ssl.SSLSessionContext; |
| import javax.net.ssl.X509KeyManager; |
| import javax.net.ssl.X509TrustManager; |
| import javax.security.cert.X509Certificate; |
| |
| import gnu.javax.net.ssl.SRPTrustManager; |
| |
| /** |
| * A generic SSL session implementation for SSL and TLS. |
| */ |
| final class Session implements SSLSession |
| { |
| |
| // Constants and fields. |
| // ------------------------------------------------------------------------- |
| |
| private static final SSLPermission GET_SESSION_CONTEXT_PERMISSION = |
| new SSLPermission("getSSLSessionContext"); |
| |
| private final long creationTime; |
| private Date lastAccessedTime; |
| ID sessionId; |
| Certificate[] localCerts; |
| Certificate[] peerCerts; |
| X509Certificate[] peerCertChain; |
| String peerHost; |
| boolean peerVerified; |
| SessionContext context; |
| HashMap values; |
| boolean valid; |
| List enabledSuites; |
| CipherSuite cipherSuite; |
| SortedSet enabledProtocols; |
| ProtocolVersion protocol; |
| byte[] masterSecret; |
| SRPTrustManager srpTrustManager; |
| X509TrustManager trustManager; |
| X509KeyManager keyManager; |
| SecureRandom random; |
| SecurityParameters params; |
| Alert currentAlert; |
| |
| // Constructor. |
| // ------------------------------------------------------------------------- |
| |
| Session() |
| { |
| this(System.currentTimeMillis()); |
| } |
| |
| Session(long creationTime) |
| { |
| peerVerified = false; |
| valid = true; |
| this.creationTime = creationTime; |
| lastAccessedTime = new Date(0L); |
| values = new HashMap(); |
| if (("true").equalsIgnoreCase (Util.getSecurityProperty ("jessie.with.jce"))) |
| params = new JCESecurityParameters(); |
| else |
| params = new GNUSecurityParameters (this); |
| } |
| |
| // Public instance methods. |
| // ------------------------------------------------------------------------- |
| |
| protected Object clone() |
| { |
| Session result = new Session(creationTime); |
| result.lastAccessedTime = lastAccessedTime; |
| result.sessionId = sessionId; |
| result.localCerts = (localCerts != null ? (Certificate[]) localCerts.clone() : null); |
| result.peerCerts = (peerCerts != null ? (Certificate[]) peerCerts.clone() : null); |
| result.peerHost = peerHost; |
| result.peerVerified = peerVerified; |
| result.context = context; |
| result.values = values; |
| result.enabledSuites = new ArrayList(enabledSuites); |
| result.cipherSuite = cipherSuite; |
| result.enabledProtocols = new TreeSet(enabledProtocols); |
| result.protocol = protocol; |
| result.masterSecret = masterSecret; |
| result.keyManager = keyManager; |
| result.srpTrustManager = srpTrustManager; |
| result.trustManager = trustManager; |
| result.random = random; |
| return result; |
| } |
| |
| public String getCipherSuite() |
| { |
| return cipherSuite.toString(); |
| } |
| |
| public long getCreationTime() |
| { |
| return creationTime; |
| } |
| |
| public byte[] getId() |
| { |
| return (sessionId != null ? sessionId.getId() : null); |
| } |
| |
| public long getLastAccessedTime() |
| { |
| return lastAccessedTime.getTime(); |
| } |
| |
| public Certificate[] getLocalCertificates() |
| { |
| return (Certificate[]) (localCerts != null ? localCerts.clone() : null); |
| } |
| |
| public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException |
| { |
| if (!peerVerified) |
| { |
| throw new SSLPeerUnverifiedException("peer not verified"); |
| } |
| return (Certificate[]) (peerCerts != null ? peerCerts.clone() : null); |
| } |
| |
| public X509Certificate[] getPeerCertificateChain() |
| throws SSLPeerUnverifiedException |
| { |
| if (!peerVerified) |
| { |
| throw new SSLPeerUnverifiedException("peer not verified"); |
| } |
| if (peerCerts == null) |
| { |
| return null; |
| } |
| if (peerCertChain != null) |
| { |
| return (X509Certificate[]) peerCertChain.clone(); |
| } |
| try |
| { |
| peerCertChain = new X509Certificate[peerCerts.length]; |
| for (int i = 0; i < peerCerts.length; i++) |
| { |
| peerCertChain[i] = X509Certificate.getInstance(peerCerts[i].getEncoded()); |
| } |
| return (X509Certificate[]) peerCertChain.clone(); |
| } |
| catch (javax.security.cert.CertificateException ce) |
| { |
| return null; |
| } |
| catch (CertificateException ce2) |
| { |
| return null; |
| } |
| } |
| |
| public String getPeerHost() |
| { |
| return peerHost; |
| } |
| |
| public String getProtocol() |
| { |
| return protocol.toString(); |
| } |
| |
| public SSLSessionContext getSessionContext() |
| { |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) |
| { |
| sm.checkPermission(GET_SESSION_CONTEXT_PERMISSION); |
| } |
| return context; |
| } |
| |
| public String[] getValueNames() |
| { |
| Set names = values.keySet(); |
| return (String[]) names.toArray(new String[names.size()]); |
| } |
| |
| public Object getValue(String name) |
| { |
| return values.get(name); |
| } |
| |
| public void putValue(String name, Object value) |
| { |
| values.put(name, value); |
| if (value instanceof SSLSessionBindingListener) |
| { |
| ((SSLSessionBindingListener) value).valueBound( |
| new SSLSessionBindingEvent(this, name)); |
| } |
| } |
| |
| public void removeValue(String name) |
| { |
| Object value = values.remove(name); |
| if (value != null && (value instanceof SSLSessionBindingListener)) |
| { |
| ((SSLSessionBindingListener) value).valueUnbound( |
| new SSLSessionBindingEvent(this, name)); |
| } |
| } |
| |
| public void invalidate() |
| { |
| if (masterSecret != null) |
| { |
| for (int i = 0; i < masterSecret.length; i++) |
| { |
| masterSecret[i] = 0; |
| } |
| masterSecret = null; |
| } |
| valid = false; |
| } |
| |
| synchronized void access() |
| { |
| lastAccessedTime.setTime(System.currentTimeMillis()); |
| context.notifyAccess(this); |
| } |
| |
| void setLastAccessedTime(long lastAccessedTime) |
| { |
| this.lastAccessedTime.setTime(lastAccessedTime); |
| } |
| |
| // Inner classes. |
| // ------------------------------------------------------------------------- |
| |
| /** |
| * A byte array with appropriate <code>equals()</code>, |
| * <code>hashCode()</code>, and <code>compareTo()</code> semantics. |
| */ |
| static final class ID implements Comparable |
| { |
| |
| // Fields. |
| // ----------------------------------------------------------------------- |
| |
| /** The ID itself. */ |
| private final byte[] id; |
| |
| // Constructor. |
| // ----------------------------------------------------------------------- |
| |
| /** |
| * Creates a new ID. |
| * |
| * @param id The ID. The array is not cloned. |
| */ |
| ID(byte[] id) |
| { |
| if (id == null) |
| { |
| throw new IllegalArgumentException(); |
| } |
| this.id = id; |
| } |
| |
| // Instance methods. |
| // ----------------------------------------------------------------------- |
| |
| public byte[] getId() |
| { |
| return (byte[]) id.clone(); |
| } |
| |
| public boolean equals(Object other) |
| { |
| if (other == null || !(other instanceof ID)) |
| { |
| return false; |
| } |
| return Arrays.equals(id, ((ID) other).id); |
| } |
| |
| public int hashCode() |
| { |
| int code = 0; |
| for (int i = 0; i < id.length; i++) |
| { |
| code |= (id[i] & 0xFF) << ((i & 3) << 3); |
| } |
| return code; |
| } |
| |
| public int compareTo(Object other) |
| { |
| if (other == null || !(other instanceof ID)) |
| { |
| return 1; |
| } |
| byte[] id2 = ((ID) other).id; |
| if (id.length != id2.length) |
| { |
| return (id.length < id2.length) ? -1 : 1; |
| } |
| for (int i = 0; i < id.length; i++) |
| { |
| if (id[i] < id2[i]) |
| { |
| return -1; |
| } |
| else if (id[i] > id2[i]) |
| { |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| public String toString() |
| { |
| return Util.toHexString(id, ':'); |
| } |
| } |
| } |