--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/IdentityDatabase.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,427 @@
+/*
+ * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.provider;
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+
+/**
+ * An implementation of IdentityScope as a persistent identity
+ * database.
+ *
+ * @see Identity
+ * @see Key
+ *
+ * @author Benjamin Renaud
+ */
+public
+class IdentityDatabase extends IdentityScope implements Serializable {
+
+ /** use serialVersionUID from JDK 1.1. for interoperability */
+ private static final long serialVersionUID = 4923799573357658384L;
+
+ /* Are we debugging? */
+ private static final boolean debug = false;
+
+ /* Are we printing out error messages? */
+ private static final boolean error = true;
+
+ /* The source file, if any, for this database.*/
+ File sourceFile;
+
+ /* The private representation of the database.*/
+ Hashtable<String, Identity> identities;
+
+ IdentityDatabase() throws InvalidParameterException {
+ this("restoring...");
+ }
+
+ /**
+ * Construct a new, empty database with a specified source file.
+ *
+ * @param file the source file.
+ */
+ public IdentityDatabase(File file) throws InvalidParameterException {
+ this(file.getName());
+ sourceFile = file;
+ }
+
+ /**
+ * Construct a new, empty database.
+ */
+ public IdentityDatabase(String name) throws InvalidParameterException {
+ super(name);
+ identities = new Hashtable<String, Identity>();
+ }
+
+ /**
+ * Initialize an identity database from a stream. The stream should
+ * contain data to initialized a serialized IdentityDatabase
+ * object.
+ *
+ * @param is the input stream from which to restore the database.
+ *
+ * @exception IOException if a stream IO exception occurs
+ */
+ public static IdentityDatabase fromStream(InputStream is)
+ throws IOException {
+ IdentityDatabase db = null;
+ try {
+ ObjectInputStream ois = new ObjectInputStream(is);
+ db = (IdentityDatabase)ois.readObject();
+ } catch (ClassNotFoundException e) {
+ // this can't happen.
+ debug("This should not be happening.", e);
+ error(
+ "The version of the database is obsolete. Cannot initialize.");
+
+ } catch (InvalidClassException e) {
+ // this may happen in developers workspaces happen.
+ debug("This should not be happening.", e);
+ error("Unable to initialize system identity scope: " +
+ " InvalidClassException. \nThis is most likely due to " +
+ "a serialization versioning problem: a class used in " +
+ "key management was obsoleted");
+
+ } catch (StreamCorruptedException e) {
+ debug("The serialization stream is corrupted. Unable to load.", e);
+ error("Unable to initialize system identity scope." +
+ " StreamCorruptedException.");
+ }
+
+ if (db == null) {
+ db = new IdentityDatabase("uninitialized");
+ }
+
+ return db;
+ }
+
+ /**
+ * Initialize an IdentityDatabase from file.
+ *
+ * @param f the filename where the identity database is stored.
+ *
+ * @exception IOException a file-related exception occurs (e.g.
+ * the directory of the file passed does not exists, etc.
+ *
+ * @IOException if a file IO exception occurs.
+ */
+ public static IdentityDatabase fromFile(File f) throws IOException {
+ FileInputStream fis = new FileInputStream(f);
+ IdentityDatabase edb = fromStream(fis);
+ edb.sourceFile = f;
+ return edb;
+ }
+
+
+
+ /**
+ * @return the number of identities in the database.
+ */
+ public int size() {
+ return identities.size();
+ }
+
+
+ /**
+ * @param name the name of the identity to be retrieved.
+ *
+ * @return the identity named name, or null if there are
+ * no identities named name in the database.
+ */
+ public Identity getIdentity(String name) {
+ Identity id = identities.get(name);
+ if (id instanceof Signer) {
+ localCheck("get.signer");
+ }
+ return id;
+ }
+
+ /**
+ * Get an identity by key.
+ *
+ * @param name the key of the identity to be retrieved.
+ *
+ * @return the identity with a given key, or null if there are no
+ * identities with that key in the database.
+ */
+ public Identity getIdentity(PublicKey key) {
+ if (key == null) {
+ return null;
+ }
+ Enumeration<Identity> e = identities();
+ while (e.hasMoreElements()) {
+ Identity i = e.nextElement();
+ PublicKey k = i.getPublicKey();
+ if (k != null && keyEqual(k, key)) {
+ if (i instanceof Signer) {
+ localCheck("get.signer");
+ }
+ return i;
+ }
+ }
+ return null;
+ }
+
+ private boolean keyEqual(Key key1, Key key2) {
+ if (key1 == key2) {
+ return true;
+ } else {
+ return MessageDigest.isEqual(key1.getEncoded(), key2.getEncoded());
+ }
+ }
+
+ /**
+ * Adds an identity to the database.
+ *
+ * @param identity the identity to be added.
+ *
+ * @exception KeyManagementException if a name or key clash
+ * occurs, or if another exception occurs.
+ */
+ public void addIdentity(Identity identity)
+ throws KeyManagementException {
+ localCheck("add.identity");
+ Identity byName = getIdentity(identity.getName());
+ Identity byKey = getIdentity(identity.getPublicKey());
+ String msg = null;
+
+ if (byName != null) {
+ msg = "name conflict";
+ }
+ if (byKey != null) {
+ msg = "key conflict";
+ }
+ if (msg != null) {
+ throw new KeyManagementException(msg);
+ }
+ identities.put(identity.getName(), identity);
+ }
+
+ /**
+ * Removes an identity to the database.
+ */
+ public void removeIdentity(Identity identity)
+ throws KeyManagementException {
+ localCheck("remove.identity");
+ String name = identity.getName();
+ if (identities.get(name) == null) {
+ throw new KeyManagementException("there is no identity named " +
+ name + " in " + this);
+ }
+ identities.remove(name);
+ }
+
+ /**
+ * @return an enumeration of all identities in the database.
+ */
+ public Enumeration<Identity> identities() {
+ return identities.elements();
+ }
+
+ /**
+ * Set the source file for this database.
+ */
+ void setSourceFile(File f) {
+ sourceFile = f;
+ }
+
+ /**
+ * @return the source file for this database.
+ */
+ File getSourceFile() {
+ return sourceFile;
+ }
+
+ /**
+ * Save the database in its current state to an output stream.
+ *
+ * @param os the output stream to which the database should be serialized.
+ *
+ * @exception IOException if an IO exception is raised by stream
+ * operations.
+ */
+ public void save(OutputStream os) throws IOException {
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(os);
+ oos.writeObject(this);
+ oos.flush();
+ } catch (InvalidClassException e) {
+ debug("This should not be happening.", e);
+ return;
+ }
+ }
+
+ /**
+ * Save the database to a file.
+ *
+ * @exception IOException if an IO exception is raised by stream
+ * operations.
+ */
+ void save(File f) throws IOException {
+ setSourceFile(f);
+ FileOutputStream fos = new FileOutputStream(f);
+ save(fos);
+ }
+
+ /**
+ * Saves the database to the default source file.
+ *
+ * @exception KeyManagementException when there is no default source
+ * file specified for this database.
+ */
+ public void save() throws IOException {
+ if (sourceFile == null) {
+ throw new IOException("this database has no source file");
+ }
+ save(sourceFile);
+ }
+
+ /**
+ * This method returns the file from which to initialize the
+ * system database.
+ */
+ private static File systemDatabaseFile() {
+
+ // First figure out where the identity database is hiding, if anywhere.
+ String dbPath = Security.getProperty("identity.database");
+ // if nowhere, it's the canonical place.
+ if (dbPath == null) {
+ dbPath = System.getProperty("user.home") + File.separatorChar +
+ "identitydb.obj";
+ }
+ return new File(dbPath);
+ }
+
+
+ /* This block initializes the system database, if there is one. */
+ static {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ initializeSystem();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * This method initializes the system's identity database. The
+ * canonical location is
+ * <user.home>/identitydatabase.obj. This is settable through
+ * the identity.database property. */
+ private static void initializeSystem() {
+
+ IdentityDatabase systemDatabase;
+ File dbFile = systemDatabaseFile();
+
+ // Second figure out if it's there, and if it isn't, create one.
+ try {
+ if (dbFile.exists()) {
+ debug("loading system database from file: " + dbFile);
+ systemDatabase = fromFile(dbFile);
+ } else {
+ systemDatabase = new IdentityDatabase(dbFile);
+ }
+ IdentityScope.setSystemScope(systemDatabase);
+ debug("System database initialized: " + systemDatabase);
+ } catch (IOException e) {
+ debug("Error initializing identity database: " + dbFile, e);
+ return;
+ } catch (InvalidParameterException e) {
+ debug("Error trying to instantiate a system identities db in " +
+ dbFile, e);
+ return;
+ }
+ }
+
+ /*
+ private static File securityPropFile(String filename) {
+ // maybe check for a system property which will specify where to
+ // look.
+ String sep = File.separator;
+ return new File(System.getProperty("java.home") +
+ sep + "lib" + sep + "security" +
+ sep + filename);
+ }
+ */
+
+ public String toString() {
+ return "sun.security.provider.IdentityDatabase, source file: " +
+ sourceFile;
+ }
+
+
+ private static void debug(String s) {
+ if (debug) {
+ System.err.println(s);
+ }
+ }
+
+ private static void debug(String s, Throwable t) {
+ if (debug) {
+ t.printStackTrace();
+ System.err.println(s);
+ }
+ }
+
+ private static void error(String s) {
+ if (error) {
+ System.err.println(s);
+ }
+ }
+
+ void localCheck(String directive) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ directive = this.getClass().getName() + "." +
+ directive + "." + localFullName();
+ security.checkSecurityAccess(directive);
+ }
+ }
+
+ /**
+ * Returns a parsable name for identity: identityName.scopeName
+ */
+ String localFullName() {
+ String parsable = getName();
+ if (getScope() != null) {
+ parsable += "." +getScope().getName();
+ }
+ return parsable;
+ }
+
+ /**
+ * Serialization write.
+ */
+ private synchronized void writeObject (java.io.ObjectOutputStream stream)
+ throws IOException {
+ localCheck("serialize.identity.database");
+ stream.writeObject(identities);
+ stream.writeObject(sourceFile);
+ }
+}