123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /* AbstractSessionContext -- stores SSL sessions, possibly persistently.
- 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;
- import gnu.java.security.Requires;
- import gnu.javax.net.ssl.provider.SimpleSessionContext;
- import java.util.Enumeration;
- import javax.net.ssl.SSLException;
- import javax.net.ssl.SSLPermission;
- import javax.net.ssl.SSLSession;
- import javax.net.ssl.SSLSessionContext;
- /**
- * A skeletal implementation of {@link SSLSessionContext}. This class may
- * be subclassed to add extended functionality to session contexts, such
- * as by storing sessions in files on disk, or by sharing contexts
- * across different JVM instances.
- *
- * <p>In order to securely store sessions, along with private key data,
- * the abstract methods {@lnk {@link #load(char[])} and {@link #store(char[])}
- * come into play. When storing sessions, a session context implementation
- * must pass this password to the {@link Session#prepare(char[])} method,
- * before either writing the {@link java.io.Serializable} session to the
- * underlying store, or getting the opaque {@link Session#privateData()}
- * class from the session, and storing that.
- *
- * <p>As a simple example, that writes sessions to some object output
- * stream:
- *
- * <pre>
- char[] password = ...;
- ObjectOutputStream out = ...;
- ...
- for (Session s : this)
- {
- s.prepare(password);
- out.writeObject(s);
- }</pre>
- *
- * <p>The reverse must be done when deserializing sessions, by using the
- * {@link Session#repair(char[])} method, possibly by first calling
- * {@link Session#setPrivateData(java.io.Serializable)} with the read,
- * opaque private data type. Thus an example of reading may be:
- *
- * <pre>
- char[] password = ...;
- ObjectInputStream in = ...;
- ...
- while (hasMoreSessions(in))
- {
- Session s = (Session) in.readObject();
- s.repair(password);
- addToThisStore(s);
- }</pre>
- *
- * @author Casey Marshall (csm@gnu.org)
- */
- public abstract class AbstractSessionContext implements SSLSessionContext
- {
- protected long timeout;
- private static Class<? extends AbstractSessionContext>
- implClass = SimpleSessionContext.class;
- /**
- * Create a new instance of a session context, according to the configured
- * implementation class.
- *
- * @return The new session context.
- * @throws SSLException If an error occurs in creating the instance.
- */
- public static AbstractSessionContext newInstance () throws SSLException
- {
- try
- {
- return implClass.newInstance();
- }
- catch (IllegalAccessException iae)
- {
- throw new SSLException(iae);
- }
- catch (InstantiationException ie)
- {
- throw new SSLException(ie);
- }
- }
- /**
- * Reconfigure this instance to use a different session context
- * implementation.
- *
- * <p><strong>Note:</strong> this method requires that the caller have
- * {@link SSLPermission} with target
- * <code>gnu.javax.net.ssl.AbstractSessionContext</code> and action
- * <code>setImplClass</code>.
- *
- * @param clazz The new implementation class.
- * @throws SecurityException If the caller does not have permission to
- * change the session context.
- */
- @Requires(permissionClass = SSLPermission.class,
- target = "gnu.javax.net.ssl.AbstractSessionContext",
- action = "setImplClass")
- public static synchronized void setImplClass
- (Class<? extends AbstractSessionContext> clazz)
- throws SecurityException
- {
- SecurityManager sm = System.getSecurityManager ();
- if (sm != null)
- sm.checkPermission(new SSLPermission("gnu.javax.net.ssl.AbstractSessionContext",
- "setImplClass"));
- implClass = clazz;
- }
- /**
- * @param timeout The initial session timeout.
- */
- protected AbstractSessionContext (final int timeout)
- {
- setSessionTimeout(timeout);
- }
- /**
- * Fetch a saved session by its ID. This method will (possibly)
- * deserialize and return the SSL session with that ID, or null if
- * the requested session does not exist, or has expired.
- *
- * <p>Subclasses implementing this class <strong>must not</strong>
- * perform any blocking operations in this method. If any blocking
- * behavior is required, it must be done in the {@link load(char[])}
- * method.
- *
- * @param sessionId The ID of the session to get.
- * @return The found session, or null if no such session was found,
- * or if that session has expired.
- */
- public final SSLSession getSession (byte[] sessionId)
- {
- Session s = implGet (sessionId);
- if (s != null
- && System.currentTimeMillis () - s.getLastAccessedTime () > timeout)
- {
- remove (sessionId);
- return null;
- }
- return s;
- }
- public final SSLSession getSession(String host, int port)
- {
- for (Enumeration e = getIds(); e.hasMoreElements(); )
- {
- byte[] id = (byte[]) e.nextElement();
- SSLSession s = getSession(id);
- if (s == null) // session expired.
- continue;
- String host2 = s.getPeerHost();
- if (host == null)
- {
- if (host2 != null)
- continue;
- }
- else if (!host.equals(host2))
- continue;
- int port2 = s.getPeerPort();
- if (port != port2)
- continue;
- // Else, a match.
- return s;
- }
- return null;
- }
- /**
- * To be implemented by subclasses. Subclasses do not need to check
- * timeouts in this method.
- *
- * @param sessionId The session ID.
- * @return The session, or <code>null</code> if the requested session
- * was not found.
- */
- protected abstract Session implGet (byte[] sessionId);
- public int getSessionTimeout()
- {
- return (int) (timeout / 1000);
- }
- /**
- * Load this session store from the underlying media, if supported
- * by the implementation.
- *
- * @param password The password that protects the sensitive data in
- * this store.
- * @throws SessionStoreException If reading this store fails, such
- * as when an I/O exception occurs, or if the password is incorrect.
- */
- public abstract void load (char[] password) throws SessionStoreException;
- /**
- * Add a new session to the store. The underlying implementation
- * will add the session to its store, possibly overwriting any
- * existing session with the same ID.
- *
- * <p>Subclasses implementing this class <strong>must not</strong>
- * perform any blocking operations in this method. If any blocking
- * behavior is required, it must be done in the {@link
- * #store(char[])} method.
- *
- * @param session The session to add.
- * @throws NullPointerException If the argument is null.
- */
- public abstract void put (Session session);
- /**
- * Remove a session from this store.
- *
- * <p>Subclasses implementing this class <strong>must not</strong>
- * perform any blocking operations in this method. If any blocking
- * behavior is required, it must be done in the {@link
- * #store(char[])} method.
- *
- * @param sessionId The ID of the session to remove.
- */
- public abstract void remove (byte[] sessionId);
- /**
- *
- */
- public final void setSessionTimeout(int seconds)
- {
- if (timeout < 0)
- throw new IllegalArgumentException("timeout may not be negative");
- this.timeout = (long) seconds * 1000;
- }
- /**
- * Commit this session store to the underlying media. For session
- * store implementations that support saving sessions across
- * invocations of the JVM, this method will save any sessions that
- * have not expired to some persistent media, so they may be loaded
- * and used again later.
- *
- * @param password The password that will protect the sensitive data
- * in this store.
- */
- public abstract void store (char[] password) throws SessionStoreException;
- }
|