--- a/jdk/make/common/shared/Defs-java.gmk Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/make/common/shared/Defs-java.gmk Wed Oct 14 14:21:25 2009 -0700
@@ -165,6 +165,11 @@
JAVADOC_CMD = $(JAVA_TOOLS_DIR)/javadoc $(JAVA_TOOLS_FLAGS:%=-J%)
endif
+#always use the bootstrap javah until bug-ID 6889255 is fixed. These
+#five lines should be removed as part of that fix:
+JAVAH_CMD = $(JAVA_TOOLS_DIR)/javah \
+ $(JAVAHFLAGS)
+
# Override of what javac to use (see deploy workspace)
ifdef JAVAC
JAVAC_CMD = $(JAVAC)
--- a/jdk/make/java/java/FILES_java.gmk Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/make/java/java/FILES_java.gmk Wed Oct 14 14:21:25 2009 -0700
@@ -258,6 +258,7 @@
java/util/ServiceConfigurationError.java \
java/util/Timer.java \
java/util/TimerTask.java \
+ java/util/Objects.java \
java/util/UUID.java \
java/util/concurrent/AbstractExecutorService.java \
java/util/concurrent/ArrayBlockingQueue.java \
--- a/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java Wed Oct 14 14:21:25 2009 -0700
@@ -25,11 +25,12 @@
package com.sun.naming.internal;
-import java.applet.Applet;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
@@ -112,6 +113,52 @@
private static final WeakHashMap urlFactoryCache = new WeakHashMap(11);
private static final WeakReference NO_FACTORY = new WeakReference(null);
+ /**
+ * A class to allow JNDI properties be specified as applet parameters
+ * without creating a static dependency on java.applet.
+ */
+ private static class AppletParameter {
+ private static final Class<?> clazz = getClass("java.applet.Applet");
+ private static final Method getMethod =
+ getMethod(clazz, "getParameter", String.class);
+ private static Class<?> getClass(String name) {
+ try {
+ return Class.forName(name, true, null);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+ private static Method getMethod(Class<?> clazz,
+ String name,
+ Class<?>... paramTypes)
+ {
+ if (clazz != null) {
+ try {
+ return clazz.getMethod(name, paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError(e);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value of the applet's named parameter.
+ */
+ static Object get(Object applet, String name) {
+ // if clazz is null then applet cannot be an Applet.
+ if (clazz == null || !clazz.isInstance(applet))
+ throw new ClassCastException(applet.getClass().getName());
+ try {
+ return getMethod.invoke(applet, name);
+ } catch (InvocationTargetException e) {
+ throw new AssertionError(e);
+ } catch (IllegalAccessException iae) {
+ throw new AssertionError(iae);
+ }
+ }
+ }
// There should be no instances of this class.
private ResourceManager() {
@@ -143,7 +190,7 @@
if (env == null) {
env = new Hashtable(11);
}
- Applet applet = (Applet)env.get(Context.APPLET);
+ Object applet = env.get(Context.APPLET);
// Merge property values from env param, applet params, and system
// properties. The first value wins: there's no concatenation of
@@ -157,7 +204,7 @@
Object val = env.get(props[i]);
if (val == null) {
if (applet != null) {
- val = applet.getParameter(props[i]);
+ val = AppletParameter.get(applet, props[i]);
}
if (val == null) {
// Read system property.
--- a/jdk/src/share/classes/java/lang/Byte.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Byte.java Wed Oct 14 14:21:25 2009 -0700
@@ -201,7 +201,7 @@
*/
public static Byte valueOf(String s, int radix)
throws NumberFormatException {
- return new Byte(parseByte(s, radix));
+ return valueOf(parseByte(s, radix));
}
/**
@@ -277,7 +277,7 @@
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value " + i + " out of range from input " + nm);
- return (byte)i;
+ return valueOf((byte)i);
}
/**
@@ -374,7 +374,7 @@
* base 10.
*/
public String toString() {
- return String.valueOf((int)value);
+ return Integer.toString((int)value);
}
/**
--- a/jdk/src/share/classes/java/lang/Double.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Double.java Wed Oct 14 14:21:25 2009 -0700
@@ -629,7 +629,7 @@
* @see java.lang.Double#toString(double)
*/
public String toString() {
- return String.valueOf(value);
+ return toString(value);
}
/**
--- a/jdk/src/share/classes/java/lang/Enum.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Enum.java Wed Oct 14 14:21:25 2009 -0700
@@ -40,10 +40,17 @@
* Edition</i>, <a
* href="http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.9">§8.9</a>.
*
+ * <p> Note that when using an enumeration type as the type of a set
+ * or as the type of the keys in a map, specialized and efficient
+ * {@linkplain java.util.EnumSet set} and {@linkplain
+ * java.util.EnumMap map} implementations are available.
+ *
* @param <E> The enum type subclass
* @author Josh Bloch
* @author Neal Gafter
* @see Class#getEnumConstants()
+ * @see java.util.EnumSet
+ * @see java.util.EnumMap
* @since 1.5
*/
public abstract class Enum<E extends Enum<E>>
--- a/jdk/src/share/classes/java/lang/Float.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Float.java Wed Oct 14 14:21:25 2009 -0700
@@ -551,7 +551,7 @@
* @see java.lang.Float#toString(float)
*/
public String toString() {
- return String.valueOf(value);
+ return Float.toString(value);
}
/**
--- a/jdk/src/share/classes/java/lang/Integer.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Integer.java Wed Oct 14 14:21:25 2009 -0700
@@ -746,7 +746,7 @@
* base 10.
*/
public String toString() {
- return String.valueOf(value);
+ return toString(value);
}
/**
--- a/jdk/src/share/classes/java/lang/Long.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Long.java Wed Oct 14 14:21:25 2009 -0700
@@ -761,7 +761,7 @@
* base 10.
*/
public String toString() {
- return String.valueOf(value);
+ return toString(value);
}
/**
--- a/jdk/src/share/classes/java/lang/Short.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Short.java Wed Oct 14 14:21:25 2009 -0700
@@ -170,7 +170,7 @@
*/
public static Short valueOf(String s, int radix)
throws NumberFormatException {
- return new Short(parseShort(s, radix));
+ return valueOf(parseShort(s, radix));
}
/**
@@ -282,7 +282,7 @@
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value " + i + " out of range from input " + nm);
- return (short)i;
+ return valueOf((short)i);
}
/**
@@ -379,7 +379,7 @@
* base 10.
*/
public String toString() {
- return String.valueOf((int)value);
+ return Integer.toString((int)value);
}
/**
--- a/jdk/src/share/classes/java/lang/String.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/String.java Wed Oct 14 14:21:25 2009 -0700
@@ -2995,7 +2995,7 @@
* @see java.lang.Integer#toString(int, int)
*/
public static String valueOf(int i) {
- return Integer.toString(i, 10);
+ return Integer.toString(i);
}
/**
@@ -3009,7 +3009,7 @@
* @see java.lang.Long#toString(long)
*/
public static String valueOf(long l) {
- return Long.toString(l, 10);
+ return Long.toString(l);
}
/**
--- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Oct 14 14:21:25 2009 -0700
@@ -44,6 +44,8 @@
* as Java Object Serialization or other persistence mechanisms, to
* manipulate objects in a manner that would normally be prohibited.
*
+ * <p>By default, a reflected object is <em>not</em> accessible.
+ *
* @see Field
* @see Method
* @see Constructor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/Objects.java Wed Oct 14 14:21:25 2009 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009 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 java.util;
+
+/**
+ * This class consists of {@code static} utility methods for operating
+ * on objects. These utilities include {@code null}-safe or {@code
+ * null}-tolerant methods for computing the hash code of an object,
+ * returning a string for an object, and comparing two objects.
+ *
+ * @since 1.7
+ */
+public class Objects {
+ private Objects() {
+ throw new AssertionError("No java.util.Objects instances for you!");
+ }
+
+ /**
+ * Returns {@code true} if the arguments are equal to each other
+ * and {@code false} otherwise.
+ * Consequently, if both arguments are {@code null}, {@code true}
+ * is returned and if exactly one argument is {@code null}, {@code
+ * false} is returned. Otherwise, equality is determined by using
+ * the {@link Object#equals equals} method of the first
+ * argument.
+ *
+ * @param a an object
+ * @param b an object to be compared with {@code a} for equality
+ * @return {@code true} if the arguments are equal to each other
+ * and {@code false} otherwise
+ * @see Object#equals(Object)
+ */
+ public static boolean equals(Object a, Object b) {
+ return (a == b) || (a != null && a.equals(b));
+ }
+
+ /**
+ * Returns the hash code of a non-{@code null} argument and 0 for
+ * a {@code null} argument.
+ *
+ * @param o an object
+ * @return the hash code of a non-{@code null} argument and 0 for
+ * a {@code null} argument
+ * @see Object#hashCode
+ */
+ public static int hashCode(Object o) {
+ return o != null ? o.hashCode() : 0;
+ }
+
+ /**
+ * Returns the result of calling {@code toString} for a non-{@code
+ * null} argument and {@code "null"} for a {@code null} argument.
+ *
+ * @param o an object
+ * @return the result of calling {@code toString} for a non-{@code
+ * null} argument and {@code "null"} for a {@code null} argument
+ * @see Object#toString
+ * @see String#valueOf(Object)
+ */
+ public static String toString(Object o) {
+ return String.valueOf(o);
+ }
+
+ /**
+ * Returns 0 if the arguments are identical and {@code
+ * c.compare(a, b)} otherwise.
+ * Consequently, if both arguments are {@code null} 0
+ * is returned.
+ *
+ * <p>Note that if one of the arguments is {@code null}, a {@code
+ * NullPointerException} may or may not be thrown depending on
+ * what ordering policy, if any, the {@link Comparator Comparator}
+ * chooses to have for {@code null} values.
+ *
+ * @param <T> the type of the objects being compared
+ * @param a an object
+ * @param b an object to be compared with {@code a}
+ * @param c the {@code Comparator} to compare the first two arguments
+ * @return 0 if the arguments are identical and {@code
+ * c.compare(a, b)} otherwise.
+ * @see Comparable
+ * @see Comparator
+ */
+ public static <T> int compare(T a, T b, Comparator<? super T> c) {
+ return (a == b) ? 0 : c.compare(a, b);
+ }
+}
--- a/jdk/src/share/classes/sun/security/provider/SunEntries.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SunEntries.java Wed Oct 14 14:21:25 2009 -0700
@@ -210,7 +210,7 @@
* CertStores
*/
map.put("CertStore.LDAP",
- "sun.security.provider.certpath.LDAPCertStore");
+ "sun.security.provider.certpath.ldap.LDAPCertStore");
map.put("CertStore.LDAP LDAPSchema", "RFC2587");
map.put("CertStore.Collection",
"sun.security.provider.certpath.CollectionCertStore");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Wed Oct 14 14:21:25 2009 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009 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.certpath;
+
+import java.net.URI;
+import java.util.Collection;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.cert.CertStore;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509CRLSelector;
+import javax.security.auth.x500.X500Principal;
+import java.io.IOException;
+
+/**
+ * Helper used by URICertStore when delegating to another CertStore to
+ * fetch certs and CRLs.
+ */
+
+public interface CertStoreHelper {
+
+ /**
+ * Returns a CertStore using the given URI as parameters.
+ */
+ CertStore getCertStore(URI uri)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException;
+
+ /**
+ * Wraps an existing X509CertSelector when needing to avoid DN matching
+ * issues.
+ */
+ X509CertSelector wrap(X509CertSelector selector,
+ X500Principal certSubject,
+ String dn)
+ throws IOException;
+
+ /**
+ * Wraps an existing X509CRLSelector when needing to avoid DN matching
+ * issues.
+ */
+ X509CRLSelector wrap(X509CRLSelector selector,
+ Collection<X500Principal> certIssuers,
+ String dn)
+ throws IOException;
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/LDAPCertStore.java Wed Oct 07 08:38:43 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1065 +0,0 @@
-/*
- * Copyright 2000-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.certpath;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URI;
-import java.util.*;
-import javax.naming.Context;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.NameNotFoundException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-import java.security.*;
-import java.security.cert.Certificate;
-import java.security.cert.*;
-import javax.security.auth.x500.X500Principal;
-
-import sun.misc.HexDumpEncoder;
-import sun.security.util.Cache;
-import sun.security.util.Debug;
-import sun.security.x509.X500Name;
-import sun.security.action.GetPropertyAction;
-
-/**
- * A <code>CertStore</code> that retrieves <code>Certificates</code> and
- * <code>CRL</code>s from an LDAP directory, using the PKIX LDAP V2 Schema
- * (RFC 2587):
- * <a href="http://www.ietf.org/rfc/rfc2587.txt">
- * http://www.ietf.org/rfc/rfc2587.txt</a>.
- * <p>
- * Before calling the {@link #engineGetCertificates engineGetCertificates} or
- * {@link #engineGetCRLs engineGetCRLs} methods, the
- * {@link #LDAPCertStore(CertStoreParameters)
- * LDAPCertStore(CertStoreParameters)} constructor is called to create the
- * <code>CertStore</code> and establish the DNS name and port of the LDAP
- * server from which <code>Certificate</code>s and <code>CRL</code>s will be
- * retrieved.
- * <p>
- * <b>Concurrent Access</b>
- * <p>
- * As described in the javadoc for <code>CertStoreSpi</code>, the
- * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods
- * must be thread-safe. That is, multiple threads may concurrently
- * invoke these methods on a single <code>LDAPCertStore</code> object
- * (or more than one) with no ill effects. This allows a
- * <code>CertPathBuilder</code> to search for a CRL while simultaneously
- * searching for further certificates, for instance.
- * <p>
- * This is achieved by adding the <code>synchronized</code> keyword to the
- * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods.
- * <p>
- * This classes uses caching and requests multiple attributes at once to
- * minimize LDAP round trips. The cache is associated with the CertStore
- * instance. It uses soft references to hold the values to minimize impact
- * on footprint and currently has a maximum size of 750 attributes and a
- * 30 second default lifetime.
- * <p>
- * We always request CA certificates, cross certificate pairs, and ARLs in
- * a single LDAP request when any one of them is needed. The reason is that
- * we typically need all of them anyway and requesting them in one go can
- * reduce the number of requests to a third. Even if we don't need them,
- * these attributes are typically small enough not to cause a noticeable
- * overhead. In addition, when the prefetchCRLs flag is true, we also request
- * the full CRLs. It is currently false initially but set to true once any
- * request for an ARL to the server returns an null value. The reason is
- * that CRLs could be rather large but are rarely used. This implementation
- * should improve performance in most cases.
- *
- * @see java.security.cert.CertStore
- *
- * @since 1.4
- * @author Steve Hanna
- * @author Andreas Sterbenz
- */
-public class LDAPCertStore extends CertStoreSpi {
-
- private static final Debug debug = Debug.getInstance("certpath");
-
- private final static boolean DEBUG = false;
-
- /**
- * LDAP attribute identifiers.
- */
- private static final String USER_CERT = "userCertificate;binary";
- private static final String CA_CERT = "cACertificate;binary";
- private static final String CROSS_CERT = "crossCertificatePair;binary";
- private static final String CRL = "certificateRevocationList;binary";
- private static final String ARL = "authorityRevocationList;binary";
- private static final String DELTA_CRL = "deltaRevocationList;binary";
-
- // Constants for various empty values
- private final static String[] STRING0 = new String[0];
-
- private final static byte[][] BB0 = new byte[0][];
-
- private final static Attributes EMPTY_ATTRIBUTES = new BasicAttributes();
-
- // cache related constants
- private final static int DEFAULT_CACHE_SIZE = 750;
- private final static int DEFAULT_CACHE_LIFETIME = 30;
-
- private final static int LIFETIME;
-
- private final static String PROP_LIFETIME =
- "sun.security.certpath.ldap.cache.lifetime";
-
- static {
- String s = AccessController.doPrivileged(
- new GetPropertyAction(PROP_LIFETIME));
- if (s != null) {
- LIFETIME = Integer.parseInt(s); // throws NumberFormatException
- } else {
- LIFETIME = DEFAULT_CACHE_LIFETIME;
- }
- }
-
- /**
- * The CertificateFactory used to decode certificates from
- * their binary stored form.
- */
- private CertificateFactory cf;
- /**
- * The JNDI directory context.
- */
- private DirContext ctx;
-
- /**
- * Flag indicating whether we should prefetch CRLs.
- */
- private boolean prefetchCRLs = false;
-
- private final Cache valueCache;
-
- private int cacheHits = 0;
- private int cacheMisses = 0;
- private int requests = 0;
-
- /**
- * Creates a <code>CertStore</code> with the specified parameters.
- * For this class, the parameters object must be an instance of
- * <code>LDAPCertStoreParameters</code>.
- *
- * @param params the algorithm parameters
- * @exception InvalidAlgorithmParameterException if params is not an
- * instance of <code>LDAPCertStoreParameters</code>
- */
- public LDAPCertStore(CertStoreParameters params)
- throws InvalidAlgorithmParameterException {
- super(params);
- if (!(params instanceof LDAPCertStoreParameters))
- throw new InvalidAlgorithmParameterException(
- "parameters must be LDAPCertStoreParameters");
-
- LDAPCertStoreParameters lparams = (LDAPCertStoreParameters) params;
-
- // Create InitialDirContext needed to communicate with the server
- createInitialDirContext(lparams.getServerName(), lparams.getPort());
-
- // Create CertificateFactory for use later on
- try {
- cf = CertificateFactory.getInstance("X.509");
- } catch (CertificateException e) {
- throw new InvalidAlgorithmParameterException(
- "unable to create CertificateFactory for X.509");
- }
- if (LIFETIME == 0) {
- valueCache = Cache.newNullCache();
- } else if (LIFETIME < 0) {
- valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE);
- } else {
- valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE, LIFETIME);
- }
- }
-
- /**
- * Returns an LDAP CertStore. This method consults a cache of
- * CertStores (shared per JVM) using the LDAP server/port as a key.
- */
- private static final Cache certStoreCache = Cache.newSoftMemoryCache(185);
- static synchronized CertStore getInstance(LDAPCertStoreParameters params)
- throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
- CertStore lcs = (CertStore) certStoreCache.get(params);
- if (lcs == null) {
- lcs = CertStore.getInstance("LDAP", params);
- certStoreCache.put(params, lcs);
- } else {
- if (debug != null) {
- debug.println("LDAPCertStore.getInstance: cache hit");
- }
- }
- return lcs;
- }
-
- /**
- * Create InitialDirContext.
- *
- * @param server Server DNS name hosting LDAP service
- * @param port Port at which server listens for requests
- * @throws InvalidAlgorithmParameterException if creation fails
- */
- private void createInitialDirContext(String server, int port)
- throws InvalidAlgorithmParameterException {
- String url = "ldap://" + server + ":" + port;
- Hashtable<String,Object> env = new Hashtable<String,Object>();
- env.put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.ldap.LdapCtxFactory");
- env.put(Context.PROVIDER_URL, url);
- try {
- ctx = new InitialDirContext(env);
- /*
- * By default, follow referrals unless application has
- * overridden property in an application resource file.
- */
- Hashtable<?,?> currentEnv = ctx.getEnvironment();
- if (currentEnv.get(Context.REFERRAL) == null) {
- ctx.addToEnvironment(Context.REFERRAL, "follow");
- }
- } catch (NamingException e) {
- if (debug != null) {
- debug.println("LDAPCertStore.engineInit about to throw "
- + "InvalidAlgorithmParameterException");
- e.printStackTrace();
- }
- Exception ee = new InvalidAlgorithmParameterException
- ("unable to create InitialDirContext using supplied parameters");
- ee.initCause(e);
- throw (InvalidAlgorithmParameterException)ee;
- }
- }
-
- /**
- * Private class encapsulating the actual LDAP operations and cache
- * handling. Use:
- *
- * LDAPRequest request = new LDAPRequest(dn);
- * request.addRequestedAttribute(CROSS_CERT);
- * request.addRequestedAttribute(CA_CERT);
- * byte[][] crossValues = request.getValues(CROSS_CERT);
- * byte[][] caValues = request.getValues(CA_CERT);
- *
- * At most one LDAP request is sent for each instance created. If all
- * getValues() calls can be satisfied from the cache, no request
- * is sent at all. If a request is sent, all requested attributes
- * are always added to the cache irrespective of whether the getValues()
- * method is called.
- */
- private class LDAPRequest {
-
- private final String name;
- private Map<String, byte[][]> valueMap;
- private final List<String> requestedAttributes;
-
- LDAPRequest(String name) {
- this.name = name;
- requestedAttributes = new ArrayList<String>(5);
- }
-
- String getName() {
- return name;
- }
-
- void addRequestedAttribute(String attrId) {
- if (valueMap != null) {
- throw new IllegalStateException("Request already sent");
- }
- requestedAttributes.add(attrId);
- }
-
- /**
- * Gets one or more binary values from an attribute.
- *
- * @param name the location holding the attribute
- * @param attrId the attribute identifier
- * @return an array of binary values (byte arrays)
- * @throws NamingException if a naming exception occurs
- */
- byte[][] getValues(String attrId) throws NamingException {
- if (DEBUG && ((cacheHits + cacheMisses) % 50 == 0)) {
- System.out.println("Cache hits: " + cacheHits + "; misses: "
- + cacheMisses);
- }
- String cacheKey = name + "|" + attrId;
- byte[][] values = (byte[][])valueCache.get(cacheKey);
- if (values != null) {
- cacheHits++;
- return values;
- }
- cacheMisses++;
- Map<String, byte[][]> attrs = getValueMap();
- values = attrs.get(attrId);
- return values;
- }
-
- /**
- * Get a map containing the values for this request. The first time
- * this method is called on an object, the LDAP request is sent,
- * the results parsed and added to a private map and also to the
- * cache of this LDAPCertStore. Subsequent calls return the private
- * map immediately.
- *
- * The map contains an entry for each requested attribute. The
- * attribute name is the key, values are byte[][]. If there are no
- * values for that attribute, values are byte[0][].
- *
- * @return the value Map
- * @throws NamingException if a naming exception occurs
- */
- private Map<String, byte[][]> getValueMap() throws NamingException {
- if (valueMap != null) {
- return valueMap;
- }
- if (DEBUG) {
- System.out.println("Request: " + name + ":" + requestedAttributes);
- requests++;
- if (requests % 5 == 0) {
- System.out.println("LDAP requests: " + requests);
- }
- }
- valueMap = new HashMap<String, byte[][]>(8);
- String[] attrIds = requestedAttributes.toArray(STRING0);
- Attributes attrs;
- try {
- attrs = ctx.getAttributes(name, attrIds);
- } catch (NameNotFoundException e) {
- // name does not exist on this LDAP server
- // treat same as not attributes found
- attrs = EMPTY_ATTRIBUTES;
- }
- for (String attrId : requestedAttributes) {
- Attribute attr = attrs.get(attrId);
- byte[][] values = getAttributeValues(attr);
- cacheAttribute(attrId, values);
- valueMap.put(attrId, values);
- }
- return valueMap;
- }
-
- /**
- * Add the values to the cache.
- */
- private void cacheAttribute(String attrId, byte[][] values) {
- String cacheKey = name + "|" + attrId;
- valueCache.put(cacheKey, values);
- }
-
- /**
- * Get the values for the given attribute. If the attribute is null
- * or does not contain any values, a zero length byte array is
- * returned. NOTE that it is assumed that all values are byte arrays.
- */
- private byte[][] getAttributeValues(Attribute attr)
- throws NamingException {
- byte[][] values;
- if (attr == null) {
- values = BB0;
- } else {
- values = new byte[attr.size()][];
- int i = 0;
- NamingEnumeration<?> enum_ = attr.getAll();
- while (enum_.hasMore()) {
- Object obj = enum_.next();
- if (debug != null) {
- if (obj instanceof String) {
- debug.println("LDAPCertStore.getAttrValues() "
- + "enum.next is a string!: " + obj);
- }
- }
- byte[] value = (byte[])obj;
- values[i++] = value;
- }
- }
- return values;
- }
-
- }
-
- /*
- * Gets certificates from an attribute id and location in the LDAP
- * directory. Returns a Collection containing only the Certificates that
- * match the specified CertSelector.
- *
- * @param name the location holding the attribute
- * @param id the attribute identifier
- * @param sel a CertSelector that the Certificates must match
- * @return a Collection of Certificates found
- * @throws CertStoreException if an exception occurs
- */
- private Collection<X509Certificate> getCertificates(LDAPRequest request,
- String id, X509CertSelector sel) throws CertStoreException {
-
- /* fetch encoded certs from storage */
- byte[][] encodedCert;
- try {
- encodedCert = request.getValues(id);
- } catch (NamingException namingEx) {
- throw new CertStoreException(namingEx);
- }
-
- int n = encodedCert.length;
- if (n == 0) {
- return Collections.<X509Certificate>emptySet();
- }
-
- List<X509Certificate> certs = new ArrayList<X509Certificate>(n);
- /* decode certs and check if they satisfy selector */
- for (int i = 0; i < n; i++) {
- ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]);
- try {
- Certificate cert = cf.generateCertificate(bais);
- if (sel.match(cert)) {
- certs.add((X509Certificate)cert);
- }
- } catch (CertificateException e) {
- if (debug != null) {
- debug.println("LDAPCertStore.getCertificates() encountered "
- + "exception while parsing cert, skipping the bad data: ");
- HexDumpEncoder encoder = new HexDumpEncoder();
- debug.println(
- "[ " + encoder.encodeBuffer(encodedCert[i]) + " ]");
- }
- }
- }
-
- return certs;
- }
-
- /*
- * Gets certificate pairs from an attribute id and location in the LDAP
- * directory.
- *
- * @param name the location holding the attribute
- * @param id the attribute identifier
- * @return a Collection of X509CertificatePairs found
- * @throws CertStoreException if an exception occurs
- */
- private Collection<X509CertificatePair> getCertPairs(
- LDAPRequest request, String id) throws CertStoreException {
-
- /* fetch the encoded cert pairs from storage */
- byte[][] encodedCertPair;
- try {
- encodedCertPair = request.getValues(id);
- } catch (NamingException namingEx) {
- throw new CertStoreException(namingEx);
- }
-
- int n = encodedCertPair.length;
- if (n == 0) {
- return Collections.<X509CertificatePair>emptySet();
- }
-
- List<X509CertificatePair> certPairs =
- new ArrayList<X509CertificatePair>(n);
- /* decode each cert pair and add it to the Collection */
- for (int i = 0; i < n; i++) {
- try {
- X509CertificatePair certPair =
- X509CertificatePair.generateCertificatePair(encodedCertPair[i]);
- certPairs.add(certPair);
- } catch (CertificateException e) {
- if (debug != null) {
- debug.println(
- "LDAPCertStore.getCertPairs() encountered exception "
- + "while parsing cert, skipping the bad data: ");
- HexDumpEncoder encoder = new HexDumpEncoder();
- debug.println(
- "[ " + encoder.encodeBuffer(encodedCertPair[i]) + " ]");
- }
- }
- }
-
- return certPairs;
- }
-
- /*
- * Looks at certificate pairs stored in the crossCertificatePair attribute
- * at the specified location in the LDAP directory. Returns a Collection
- * containing all Certificates stored in the forward component that match
- * the forward CertSelector and all Certificates stored in the reverse
- * component that match the reverse CertSelector.
- * <p>
- * If either forward or reverse is null, all certificates from the
- * corresponding component will be rejected.
- *
- * @param name the location to look in
- * @param forward the forward CertSelector (or null)
- * @param reverse the reverse CertSelector (or null)
- * @return a Collection of Certificates found
- * @throws CertStoreException if an exception occurs
- */
- private Collection<X509Certificate> getMatchingCrossCerts(
- LDAPRequest request, X509CertSelector forward,
- X509CertSelector reverse)
- throws CertStoreException {
- // Get the cert pairs
- Collection<X509CertificatePair> certPairs =
- getCertPairs(request, CROSS_CERT);
-
- // Find Certificates that match and put them in a list
- ArrayList<X509Certificate> matchingCerts =
- new ArrayList<X509Certificate>();
- for (X509CertificatePair certPair : certPairs) {
- X509Certificate cert;
- if (forward != null) {
- cert = certPair.getForward();
- if ((cert != null) && forward.match(cert)) {
- matchingCerts.add(cert);
- }
- }
- if (reverse != null) {
- cert = certPair.getReverse();
- if ((cert != null) && reverse.match(cert)) {
- matchingCerts.add(cert);
- }
- }
- }
- return matchingCerts;
- }
-
- /**
- * Returns a <code>Collection</code> of <code>Certificate</code>s that
- * match the specified selector. If no <code>Certificate</code>s
- * match the selector, an empty <code>Collection</code> will be returned.
- * <p>
- * It is not practical to search every entry in the LDAP database for
- * matching <code>Certificate</code>s. Instead, the <code>CertSelector</code>
- * is examined in order to determine where matching <code>Certificate</code>s
- * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
- * If the subject is specified, its directory entry is searched. If the
- * issuer is specified, its directory entry is searched. If neither the
- * subject nor the issuer are specified (or the selector is not an
- * <code>X509CertSelector</code>), a <code>CertStoreException</code> is
- * thrown.
- *
- * @param selector a <code>CertSelector</code> used to select which
- * <code>Certificate</code>s should be returned.
- * @return a <code>Collection</code> of <code>Certificate</code>s that
- * match the specified selector
- * @throws CertStoreException if an exception occurs
- */
- public synchronized Collection<X509Certificate> engineGetCertificates
- (CertSelector selector) throws CertStoreException {
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() selector: "
- + String.valueOf(selector));
- }
-
- if (selector == null) {
- selector = new X509CertSelector();
- }
- if (!(selector instanceof X509CertSelector)) {
- throw new CertStoreException("LDAPCertStore needs an X509CertSelector " +
- "to find certs");
- }
- X509CertSelector xsel = (X509CertSelector) selector;
- int basicConstraints = xsel.getBasicConstraints();
- String subject = xsel.getSubjectAsString();
- String issuer = xsel.getIssuerAsString();
- HashSet<X509Certificate> certs = new HashSet<X509Certificate>();
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: "
- + basicConstraints);
- }
-
- // basicConstraints:
- // -2: only EE certs accepted
- // -1: no check is done
- // 0: any CA certificate accepted
- // >1: certificate's basicConstraints extension pathlen must match
- if (subject != null) {
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() "
- + "subject is not null");
- }
- LDAPRequest request = new LDAPRequest(subject);
- if (basicConstraints > -2) {
- request.addRequestedAttribute(CROSS_CERT);
- request.addRequestedAttribute(CA_CERT);
- request.addRequestedAttribute(ARL);
- if (prefetchCRLs) {
- request.addRequestedAttribute(CRL);
- }
- }
- if (basicConstraints < 0) {
- request.addRequestedAttribute(USER_CERT);
- }
-
- if (basicConstraints > -2) {
- certs.addAll(getMatchingCrossCerts(request, xsel, null));
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() after "
- + "getMatchingCrossCerts(subject,xsel,null),certs.size(): "
- + certs.size());
- }
- certs.addAll(getCertificates(request, CA_CERT, xsel));
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() after "
- + "getCertificates(subject,CA_CERT,xsel),certs.size(): "
- + certs.size());
- }
- }
- if (basicConstraints < 0) {
- certs.addAll(getCertificates(request, USER_CERT, xsel));
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() after "
- + "getCertificates(subject,USER_CERT, xsel),certs.size(): "
- + certs.size());
- }
- }
- } else {
- if (debug != null) {
- debug.println
- ("LDAPCertStore.engineGetCertificates() subject is null");
- }
- if (basicConstraints == -2) {
- throw new CertStoreException("need subject to find EE certs");
- }
- if (issuer == null) {
- throw new CertStoreException("need subject or issuer to find certs");
- }
- }
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() about to "
- + "getMatchingCrossCerts...");
- }
- if ((issuer != null) && (basicConstraints > -2)) {
- LDAPRequest request = new LDAPRequest(issuer);
- request.addRequestedAttribute(CROSS_CERT);
- request.addRequestedAttribute(CA_CERT);
- request.addRequestedAttribute(ARL);
- if (prefetchCRLs) {
- request.addRequestedAttribute(CRL);
- }
-
- certs.addAll(getMatchingCrossCerts(request, null, xsel));
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() after "
- + "getMatchingCrossCerts(issuer,null,xsel),certs.size(): "
- + certs.size());
- }
- certs.addAll(getCertificates(request, CA_CERT, xsel));
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() after "
- + "getCertificates(issuer,CA_CERT,xsel),certs.size(): "
- + certs.size());
- }
- }
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCertificates() returning certs");
- }
- return certs;
- }
-
- /*
- * Gets CRLs from an attribute id and location in the LDAP directory.
- * Returns a Collection containing only the CRLs that match the
- * specified CRLSelector.
- *
- * @param name the location holding the attribute
- * @param id the attribute identifier
- * @param sel a CRLSelector that the CRLs must match
- * @return a Collection of CRLs found
- * @throws CertStoreException if an exception occurs
- */
- private Collection<X509CRL> getCRLs(LDAPRequest request, String id,
- X509CRLSelector sel) throws CertStoreException {
-
- /* fetch the encoded crls from storage */
- byte[][] encodedCRL;
- try {
- encodedCRL = request.getValues(id);
- } catch (NamingException namingEx) {
- throw new CertStoreException(namingEx);
- }
-
- int n = encodedCRL.length;
- if (n == 0) {
- return Collections.<X509CRL>emptySet();
- }
-
- List<X509CRL> crls = new ArrayList<X509CRL>(n);
- /* decode each crl and check if it matches selector */
- for (int i = 0; i < n; i++) {
- try {
- CRL crl = cf.generateCRL(new ByteArrayInputStream(encodedCRL[i]));
- if (sel.match(crl)) {
- crls.add((X509CRL)crl);
- }
- } catch (CRLException e) {
- if (debug != null) {
- debug.println("LDAPCertStore.getCRLs() encountered exception"
- + " while parsing CRL, skipping the bad data: ");
- HexDumpEncoder encoder = new HexDumpEncoder();
- debug.println("[ " + encoder.encodeBuffer(encodedCRL[i]) + " ]");
- }
- }
- }
-
- return crls;
- }
-
- /**
- * Returns a <code>Collection</code> of <code>CRL</code>s that
- * match the specified selector. If no <code>CRL</code>s
- * match the selector, an empty <code>Collection</code> will be returned.
- * <p>
- * It is not practical to search every entry in the LDAP database for
- * matching <code>CRL</code>s. Instead, the <code>CRLSelector</code>
- * is examined in order to determine where matching <code>CRL</code>s
- * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
- * If issuerNames or certChecking are specified, the issuer's directory
- * entry is searched. If neither issuerNames or certChecking are specified
- * (or the selector is not an <code>X509CRLSelector</code>), a
- * <code>CertStoreException</code> is thrown.
- *
- * @param selector A <code>CRLSelector</code> used to select which
- * <code>CRL</code>s should be returned. Specify <code>null</code>
- * to return all <code>CRL</code>s.
- * @return A <code>Collection</code> of <code>CRL</code>s that
- * match the specified selector
- * @throws CertStoreException if an exception occurs
- */
- public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
- throws CertStoreException {
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCRLs() selector: "
- + selector);
- }
- // Set up selector and collection to hold CRLs
- if (selector == null) {
- selector = new X509CRLSelector();
- }
- if (!(selector instanceof X509CRLSelector)) {
- throw new CertStoreException("need X509CRLSelector to find CRLs");
- }
- X509CRLSelector xsel = (X509CRLSelector) selector;
- HashSet<X509CRL> crls = new HashSet<X509CRL>();
-
- // Look in directory entry for issuer of cert we're checking.
- Collection<Object> issuerNames;
- X509Certificate certChecking = xsel.getCertificateChecking();
- if (certChecking != null) {
- issuerNames = new HashSet<Object>();
- X500Principal issuer = certChecking.getIssuerX500Principal();
- issuerNames.add(issuer.getName(X500Principal.RFC2253));
- } else {
- // But if we don't know which cert we're checking, try the directory
- // entries of all acceptable CRL issuers
- issuerNames = xsel.getIssuerNames();
- if (issuerNames == null) {
- throw new CertStoreException("need issuerNames or certChecking to "
- + "find CRLs");
- }
- }
- for (Object nameObject : issuerNames) {
- String issuerName;
- if (nameObject instanceof byte[]) {
- try {
- X500Principal issuer = new X500Principal((byte[])nameObject);
- issuerName = issuer.getName(X500Principal.RFC2253);
- } catch (IllegalArgumentException e) {
- continue;
- }
- } else {
- issuerName = (String)nameObject;
- }
- // If all we want is CA certs, try to get the (probably shorter) ARL
- Collection<X509CRL> entryCRLs = Collections.<X509CRL>emptySet();
- if (certChecking == null || certChecking.getBasicConstraints() != -1) {
- LDAPRequest request = new LDAPRequest(issuerName);
- request.addRequestedAttribute(CROSS_CERT);
- request.addRequestedAttribute(CA_CERT);
- request.addRequestedAttribute(ARL);
- if (prefetchCRLs) {
- request.addRequestedAttribute(CRL);
- }
- try {
- entryCRLs = getCRLs(request, ARL, xsel);
- if (entryCRLs.isEmpty()) {
- // no ARLs found. We assume that means that there are
- // no ARLs on this server at all and prefetch the CRLs.
- prefetchCRLs = true;
- } else {
- crls.addAll(entryCRLs);
- }
- } catch (CertStoreException e) {
- if (debug != null) {
- debug.println("LDAPCertStore.engineGetCRLs non-fatal error "
- + "retrieving ARLs:" + e);
- e.printStackTrace();
- }
- }
- }
- // Otherwise, get the CRL
- // if certChecking is null, we don't know if we should look in ARL or CRL
- // attribute, so check both for matching CRLs.
- if (entryCRLs.isEmpty() || certChecking == null) {
- LDAPRequest request = new LDAPRequest(issuerName);
- request.addRequestedAttribute(CRL);
- entryCRLs = getCRLs(request, CRL, xsel);
- crls.addAll(entryCRLs);
- }
- }
- return crls;
- }
-
- // converts an LDAP URI into LDAPCertStoreParameters
- static LDAPCertStoreParameters getParameters(URI uri) {
- String host = uri.getHost();
- if (host == null) {
- return new SunLDAPCertStoreParameters();
- } else {
- int port = uri.getPort();
- return (port == -1
- ? new SunLDAPCertStoreParameters(host)
- : new SunLDAPCertStoreParameters(host, port));
- }
- }
-
- /*
- * Subclass of LDAPCertStoreParameters with overridden equals/hashCode
- * methods. This is necessary because the parameters are used as
- * keys in the LDAPCertStore cache.
- */
- private static class SunLDAPCertStoreParameters
- extends LDAPCertStoreParameters {
-
- private volatile int hashCode = 0;
-
- SunLDAPCertStoreParameters(String serverName, int port) {
- super(serverName, port);
- }
- SunLDAPCertStoreParameters(String serverName) {
- super(serverName);
- }
- SunLDAPCertStoreParameters() {
- super();
- }
- public boolean equals(Object obj) {
- if (!(obj instanceof LDAPCertStoreParameters)) {
- return false;
- }
- LDAPCertStoreParameters params = (LDAPCertStoreParameters) obj;
- return (getPort() == params.getPort() &&
- getServerName().equalsIgnoreCase(params.getServerName()));
- }
- public int hashCode() {
- if (hashCode == 0) {
- int result = 17;
- result = 37*result + getPort();
- result = 37*result + getServerName().toLowerCase().hashCode();
- hashCode = result;
- }
- return hashCode;
- }
- }
-
- /*
- * This inner class wraps an existing X509CertSelector and adds
- * additional criteria to match on when the certificate's subject is
- * different than the LDAP Distinguished Name entry. The LDAPCertStore
- * implementation uses the subject DN as the directory entry for
- * looking up certificates. This can be problematic if the certificates
- * that you want to fetch have a different subject DN than the entry
- * where they are stored. You could set the selector's subject to the
- * LDAP DN entry, but then the resulting match would fail to find the
- * desired certificates because the subject DNs would not match. This
- * class avoids that problem by introducing a certSubject which should
- * be set to the certificate's subject DN when it is different than
- * the LDAP DN.
- */
- static class LDAPCertSelector extends X509CertSelector {
-
- private X500Principal certSubject;
- private X509CertSelector selector;
- private X500Principal subject;
-
- /**
- * Creates an LDAPCertSelector.
- *
- * @param selector the X509CertSelector to wrap
- * @param certSubject the subject DN of the certificate that you want
- * to retrieve via LDAP
- * @param ldapDN the LDAP DN where the certificate is stored
- */
- LDAPCertSelector(X509CertSelector selector, X500Principal certSubject,
- String ldapDN) throws IOException {
- this.selector = selector == null ? new X509CertSelector() : selector;
- this.certSubject = certSubject;
- this.subject = new X500Name(ldapDN).asX500Principal();
- }
-
- // we only override the get (accessor methods) since the set methods
- // will not be invoked by the code that uses this LDAPCertSelector.
- public X509Certificate getCertificate() {
- return selector.getCertificate();
- }
- public BigInteger getSerialNumber() {
- return selector.getSerialNumber();
- }
- public X500Principal getIssuer() {
- return selector.getIssuer();
- }
- public String getIssuerAsString() {
- return selector.getIssuerAsString();
- }
- public byte[] getIssuerAsBytes() throws IOException {
- return selector.getIssuerAsBytes();
- }
- public X500Principal getSubject() {
- // return the ldap DN
- return subject;
- }
- public String getSubjectAsString() {
- // return the ldap DN
- return subject.getName();
- }
- public byte[] getSubjectAsBytes() throws IOException {
- // return the encoded ldap DN
- return subject.getEncoded();
- }
- public byte[] getSubjectKeyIdentifier() {
- return selector.getSubjectKeyIdentifier();
- }
- public byte[] getAuthorityKeyIdentifier() {
- return selector.getAuthorityKeyIdentifier();
- }
- public Date getCertificateValid() {
- return selector.getCertificateValid();
- }
- public Date getPrivateKeyValid() {
- return selector.getPrivateKeyValid();
- }
- public String getSubjectPublicKeyAlgID() {
- return selector.getSubjectPublicKeyAlgID();
- }
- public PublicKey getSubjectPublicKey() {
- return selector.getSubjectPublicKey();
- }
- public boolean[] getKeyUsage() {
- return selector.getKeyUsage();
- }
- public Set<String> getExtendedKeyUsage() {
- return selector.getExtendedKeyUsage();
- }
- public boolean getMatchAllSubjectAltNames() {
- return selector.getMatchAllSubjectAltNames();
- }
- public Collection<List<?>> getSubjectAlternativeNames() {
- return selector.getSubjectAlternativeNames();
- }
- public byte[] getNameConstraints() {
- return selector.getNameConstraints();
- }
- public int getBasicConstraints() {
- return selector.getBasicConstraints();
- }
- public Set<String> getPolicy() {
- return selector.getPolicy();
- }
- public Collection<List<?>> getPathToNames() {
- return selector.getPathToNames();
- }
-
- public boolean match(Certificate cert) {
- // temporarily set the subject criterion to the certSubject
- // so that match will not reject the desired certificates
- selector.setSubject(certSubject);
- boolean match = selector.match(cert);
- selector.setSubject(subject);
- return match;
- }
- }
-
- /**
- * This class has the same purpose as LDAPCertSelector except it is for
- * X.509 CRLs.
- */
- static class LDAPCRLSelector extends X509CRLSelector {
-
- private X509CRLSelector selector;
- private Collection<X500Principal> certIssuers;
- private Collection<X500Principal> issuers;
- private HashSet<Object> issuerNames;
-
- /**
- * Creates an LDAPCRLSelector.
- *
- * @param selector the X509CRLSelector to wrap
- * @param certIssuers the issuer DNs of the CRLs that you want
- * to retrieve via LDAP
- * @param ldapDN the LDAP DN where the CRL is stored
- */
- LDAPCRLSelector(X509CRLSelector selector,
- Collection<X500Principal> certIssuers, String ldapDN)
- throws IOException {
- this.selector = selector == null ? new X509CRLSelector() : selector;
- this.certIssuers = certIssuers;
- issuerNames = new HashSet<Object>();
- issuerNames.add(ldapDN);
- issuers = new HashSet<X500Principal>();
- issuers.add(new X500Name(ldapDN).asX500Principal());
- }
- // we only override the get (accessor methods) since the set methods
- // will not be invoked by the code that uses this LDAPCRLSelector.
- public Collection<X500Principal> getIssuers() {
- // return the ldap DN
- return Collections.unmodifiableCollection(issuers);
- }
- public Collection<Object> getIssuerNames() {
- // return the ldap DN
- return Collections.unmodifiableCollection(issuerNames);
- }
- public BigInteger getMinCRL() {
- return selector.getMinCRL();
- }
- public BigInteger getMaxCRL() {
- return selector.getMaxCRL();
- }
- public Date getDateAndTime() {
- return selector.getDateAndTime();
- }
- public X509Certificate getCertificateChecking() {
- return selector.getCertificateChecking();
- }
- public boolean match(CRL crl) {
- // temporarily set the issuer criterion to the certIssuers
- // so that match will not reject the desired CRL
- selector.setIssuers(certIssuers);
- boolean match = selector.match(crl);
- selector.setIssuers(issuers);
- return match;
- }
- }
-}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Wed Oct 14 14:21:25 2009 -0700
@@ -64,6 +64,8 @@
private static final Debug debug = Debug.getInstance("certpath");
+ private static final int CONNECT_TIMEOUT = 15000; // 15 seconds
+
private OCSP() {}
/**
@@ -176,6 +178,8 @@
debug.println("connecting to OCSP service at: " + url);
}
HttpURLConnection con = (HttpURLConnection)url.openConnection();
+ con.setConnectTimeout(CONNECT_TIMEOUT);
+ con.setReadTimeout(CONNECT_TIMEOUT);
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestMethod("POST");
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Wed Oct 14 14:21:25 2009 -0700
@@ -25,7 +25,6 @@
package sun.security.provider.certpath;
-import java.io.IOException;
import java.math.BigInteger;
import java.util.*;
import java.security.AccessController;
@@ -335,10 +334,11 @@
(issuerCert, currCertImpl.getSerialNumberObject());
response = OCSP.check(Collections.singletonList(certId), uri,
responderCert, pkixParams.getDate());
- } catch (IOException ioe) {
- // should allow this to pass if network failures are acceptable
+ } catch (Exception e) {
+ // Wrap all exceptions in CertPathValidatorException so that
+ // we can fallback to CRLs, if enabled.
throw new CertPathValidatorException
- ("Unable to send OCSP request", ioe);
+ ("Unable to send OCSP request", e);
}
RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
--- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Wed Oct 14 14:21:25 2009 -0700
@@ -30,6 +30,8 @@
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
@@ -121,6 +123,32 @@
private String ldapPath;
/**
+ * Holder class to lazily load LDAPCertStoreHelper if present.
+ */
+ private static class LDAP {
+ private static final String CERT_STORE_HELPER =
+ "sun.security.provider.certpath.ldap.LDAPCertStoreHelper";
+ private static final CertStoreHelper helper =
+ AccessController.doPrivileged(
+ new PrivilegedAction<CertStoreHelper>() {
+ public CertStoreHelper run() {
+ try {
+ Class<?> c = Class.forName(CERT_STORE_HELPER, true, null);
+ return (CertStoreHelper)c.newInstance();
+ } catch (ClassNotFoundException cnf) {
+ return null;
+ } catch (InstantiationException e) {
+ throw new AssertionError(e);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError(e);
+ }
+ }});
+ static CertStoreHelper helper() {
+ return helper;
+ }
+ }
+
+ /**
* Creates a URICertStore.
*
* @param parameters specifying the URI
@@ -135,9 +163,10 @@
this.uri = ((URICertStoreParameters) params).uri;
// if ldap URI, use an LDAPCertStore to fetch certs and CRLs
if (uri.getScheme().toLowerCase().equals("ldap")) {
+ if (LDAP.helper() == null)
+ throw new NoSuchAlgorithmException("LDAP not present");
ldap = true;
- ldapCertStore =
- LDAPCertStore.getInstance(LDAPCertStore.getParameters(uri));
+ ldapCertStore = LDAP.helper().getCertStore(uri);
ldapPath = uri.getPath();
// strip off leading '/'
if (ldapPath.charAt(0) == '/') {
@@ -219,8 +248,7 @@
if (ldap) {
X509CertSelector xsel = (X509CertSelector) selector;
try {
- xsel = new LDAPCertStore.LDAPCertSelector
- (xsel, xsel.getSubject(), ldapPath);
+ xsel = LDAP.helper().wrap(xsel, xsel.getSubject(), ldapPath);
} catch (IOException ioe) {
throw new CertStoreException(ioe);
}
@@ -340,7 +368,7 @@
if (ldap) {
X509CRLSelector xsel = (X509CRLSelector) selector;
try {
- xsel = new LDAPCertStore.LDAPCRLSelector(xsel, null, ldapPath);
+ xsel = LDAP.helper().wrap(xsel, null, ldapPath);
} catch (IOException ioe) {
throw new CertStoreException(ioe);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java Wed Oct 14 14:21:25 2009 -0700
@@ -0,0 +1,1066 @@
+/*
+ * Copyright 2000-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.certpath.ldap;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.*;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.NameNotFoundException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+
+import java.security.*;
+import java.security.cert.Certificate;
+import java.security.cert.*;
+import javax.security.auth.x500.X500Principal;
+
+import sun.misc.HexDumpEncoder;
+import sun.security.provider.certpath.X509CertificatePair;
+import sun.security.util.Cache;
+import sun.security.util.Debug;
+import sun.security.x509.X500Name;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * A <code>CertStore</code> that retrieves <code>Certificates</code> and
+ * <code>CRL</code>s from an LDAP directory, using the PKIX LDAP V2 Schema
+ * (RFC 2587):
+ * <a href="http://www.ietf.org/rfc/rfc2587.txt">
+ * http://www.ietf.org/rfc/rfc2587.txt</a>.
+ * <p>
+ * Before calling the {@link #engineGetCertificates engineGetCertificates} or
+ * {@link #engineGetCRLs engineGetCRLs} methods, the
+ * {@link #LDAPCertStore(CertStoreParameters)
+ * LDAPCertStore(CertStoreParameters)} constructor is called to create the
+ * <code>CertStore</code> and establish the DNS name and port of the LDAP
+ * server from which <code>Certificate</code>s and <code>CRL</code>s will be
+ * retrieved.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * As described in the javadoc for <code>CertStoreSpi</code>, the
+ * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods
+ * must be thread-safe. That is, multiple threads may concurrently
+ * invoke these methods on a single <code>LDAPCertStore</code> object
+ * (or more than one) with no ill effects. This allows a
+ * <code>CertPathBuilder</code> to search for a CRL while simultaneously
+ * searching for further certificates, for instance.
+ * <p>
+ * This is achieved by adding the <code>synchronized</code> keyword to the
+ * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods.
+ * <p>
+ * This classes uses caching and requests multiple attributes at once to
+ * minimize LDAP round trips. The cache is associated with the CertStore
+ * instance. It uses soft references to hold the values to minimize impact
+ * on footprint and currently has a maximum size of 750 attributes and a
+ * 30 second default lifetime.
+ * <p>
+ * We always request CA certificates, cross certificate pairs, and ARLs in
+ * a single LDAP request when any one of them is needed. The reason is that
+ * we typically need all of them anyway and requesting them in one go can
+ * reduce the number of requests to a third. Even if we don't need them,
+ * these attributes are typically small enough not to cause a noticeable
+ * overhead. In addition, when the prefetchCRLs flag is true, we also request
+ * the full CRLs. It is currently false initially but set to true once any
+ * request for an ARL to the server returns an null value. The reason is
+ * that CRLs could be rather large but are rarely used. This implementation
+ * should improve performance in most cases.
+ *
+ * @see java.security.cert.CertStore
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ * @author Andreas Sterbenz
+ */
+public class LDAPCertStore extends CertStoreSpi {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+
+ private final static boolean DEBUG = false;
+
+ /**
+ * LDAP attribute identifiers.
+ */
+ private static final String USER_CERT = "userCertificate;binary";
+ private static final String CA_CERT = "cACertificate;binary";
+ private static final String CROSS_CERT = "crossCertificatePair;binary";
+ private static final String CRL = "certificateRevocationList;binary";
+ private static final String ARL = "authorityRevocationList;binary";
+ private static final String DELTA_CRL = "deltaRevocationList;binary";
+
+ // Constants for various empty values
+ private final static String[] STRING0 = new String[0];
+
+ private final static byte[][] BB0 = new byte[0][];
+
+ private final static Attributes EMPTY_ATTRIBUTES = new BasicAttributes();
+
+ // cache related constants
+ private final static int DEFAULT_CACHE_SIZE = 750;
+ private final static int DEFAULT_CACHE_LIFETIME = 30;
+
+ private final static int LIFETIME;
+
+ private final static String PROP_LIFETIME =
+ "sun.security.certpath.ldap.cache.lifetime";
+
+ static {
+ String s = AccessController.doPrivileged(
+ new GetPropertyAction(PROP_LIFETIME));
+ if (s != null) {
+ LIFETIME = Integer.parseInt(s); // throws NumberFormatException
+ } else {
+ LIFETIME = DEFAULT_CACHE_LIFETIME;
+ }
+ }
+
+ /**
+ * The CertificateFactory used to decode certificates from
+ * their binary stored form.
+ */
+ private CertificateFactory cf;
+ /**
+ * The JNDI directory context.
+ */
+ private DirContext ctx;
+
+ /**
+ * Flag indicating whether we should prefetch CRLs.
+ */
+ private boolean prefetchCRLs = false;
+
+ private final Cache valueCache;
+
+ private int cacheHits = 0;
+ private int cacheMisses = 0;
+ private int requests = 0;
+
+ /**
+ * Creates a <code>CertStore</code> with the specified parameters.
+ * For this class, the parameters object must be an instance of
+ * <code>LDAPCertStoreParameters</code>.
+ *
+ * @param params the algorithm parameters
+ * @exception InvalidAlgorithmParameterException if params is not an
+ * instance of <code>LDAPCertStoreParameters</code>
+ */
+ public LDAPCertStore(CertStoreParameters params)
+ throws InvalidAlgorithmParameterException {
+ super(params);
+ if (!(params instanceof LDAPCertStoreParameters))
+ throw new InvalidAlgorithmParameterException(
+ "parameters must be LDAPCertStoreParameters");
+
+ LDAPCertStoreParameters lparams = (LDAPCertStoreParameters) params;
+
+ // Create InitialDirContext needed to communicate with the server
+ createInitialDirContext(lparams.getServerName(), lparams.getPort());
+
+ // Create CertificateFactory for use later on
+ try {
+ cf = CertificateFactory.getInstance("X.509");
+ } catch (CertificateException e) {
+ throw new InvalidAlgorithmParameterException(
+ "unable to create CertificateFactory for X.509");
+ }
+ if (LIFETIME == 0) {
+ valueCache = Cache.newNullCache();
+ } else if (LIFETIME < 0) {
+ valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE);
+ } else {
+ valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE, LIFETIME);
+ }
+ }
+
+ /**
+ * Returns an LDAP CertStore. This method consults a cache of
+ * CertStores (shared per JVM) using the LDAP server/port as a key.
+ */
+ private static final Cache certStoreCache = Cache.newSoftMemoryCache(185);
+ static synchronized CertStore getInstance(LDAPCertStoreParameters params)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+ CertStore lcs = (CertStore) certStoreCache.get(params);
+ if (lcs == null) {
+ lcs = CertStore.getInstance("LDAP", params);
+ certStoreCache.put(params, lcs);
+ } else {
+ if (debug != null) {
+ debug.println("LDAPCertStore.getInstance: cache hit");
+ }
+ }
+ return lcs;
+ }
+
+ /**
+ * Create InitialDirContext.
+ *
+ * @param server Server DNS name hosting LDAP service
+ * @param port Port at which server listens for requests
+ * @throws InvalidAlgorithmParameterException if creation fails
+ */
+ private void createInitialDirContext(String server, int port)
+ throws InvalidAlgorithmParameterException {
+ String url = "ldap://" + server + ":" + port;
+ Hashtable<String,Object> env = new Hashtable<String,Object>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY,
+ "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL, url);
+ try {
+ ctx = new InitialDirContext(env);
+ /*
+ * By default, follow referrals unless application has
+ * overridden property in an application resource file.
+ */
+ Hashtable<?,?> currentEnv = ctx.getEnvironment();
+ if (currentEnv.get(Context.REFERRAL) == null) {
+ ctx.addToEnvironment(Context.REFERRAL, "follow");
+ }
+ } catch (NamingException e) {
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineInit about to throw "
+ + "InvalidAlgorithmParameterException");
+ e.printStackTrace();
+ }
+ Exception ee = new InvalidAlgorithmParameterException
+ ("unable to create InitialDirContext using supplied parameters");
+ ee.initCause(e);
+ throw (InvalidAlgorithmParameterException)ee;
+ }
+ }
+
+ /**
+ * Private class encapsulating the actual LDAP operations and cache
+ * handling. Use:
+ *
+ * LDAPRequest request = new LDAPRequest(dn);
+ * request.addRequestedAttribute(CROSS_CERT);
+ * request.addRequestedAttribute(CA_CERT);
+ * byte[][] crossValues = request.getValues(CROSS_CERT);
+ * byte[][] caValues = request.getValues(CA_CERT);
+ *
+ * At most one LDAP request is sent for each instance created. If all
+ * getValues() calls can be satisfied from the cache, no request
+ * is sent at all. If a request is sent, all requested attributes
+ * are always added to the cache irrespective of whether the getValues()
+ * method is called.
+ */
+ private class LDAPRequest {
+
+ private final String name;
+ private Map<String, byte[][]> valueMap;
+ private final List<String> requestedAttributes;
+
+ LDAPRequest(String name) {
+ this.name = name;
+ requestedAttributes = new ArrayList<String>(5);
+ }
+
+ String getName() {
+ return name;
+ }
+
+ void addRequestedAttribute(String attrId) {
+ if (valueMap != null) {
+ throw new IllegalStateException("Request already sent");
+ }
+ requestedAttributes.add(attrId);
+ }
+
+ /**
+ * Gets one or more binary values from an attribute.
+ *
+ * @param name the location holding the attribute
+ * @param attrId the attribute identifier
+ * @return an array of binary values (byte arrays)
+ * @throws NamingException if a naming exception occurs
+ */
+ byte[][] getValues(String attrId) throws NamingException {
+ if (DEBUG && ((cacheHits + cacheMisses) % 50 == 0)) {
+ System.out.println("Cache hits: " + cacheHits + "; misses: "
+ + cacheMisses);
+ }
+ String cacheKey = name + "|" + attrId;
+ byte[][] values = (byte[][])valueCache.get(cacheKey);
+ if (values != null) {
+ cacheHits++;
+ return values;
+ }
+ cacheMisses++;
+ Map<String, byte[][]> attrs = getValueMap();
+ values = attrs.get(attrId);
+ return values;
+ }
+
+ /**
+ * Get a map containing the values for this request. The first time
+ * this method is called on an object, the LDAP request is sent,
+ * the results parsed and added to a private map and also to the
+ * cache of this LDAPCertStore. Subsequent calls return the private
+ * map immediately.
+ *
+ * The map contains an entry for each requested attribute. The
+ * attribute name is the key, values are byte[][]. If there are no
+ * values for that attribute, values are byte[0][].
+ *
+ * @return the value Map
+ * @throws NamingException if a naming exception occurs
+ */
+ private Map<String, byte[][]> getValueMap() throws NamingException {
+ if (valueMap != null) {
+ return valueMap;
+ }
+ if (DEBUG) {
+ System.out.println("Request: " + name + ":" + requestedAttributes);
+ requests++;
+ if (requests % 5 == 0) {
+ System.out.println("LDAP requests: " + requests);
+ }
+ }
+ valueMap = new HashMap<String, byte[][]>(8);
+ String[] attrIds = requestedAttributes.toArray(STRING0);
+ Attributes attrs;
+ try {
+ attrs = ctx.getAttributes(name, attrIds);
+ } catch (NameNotFoundException e) {
+ // name does not exist on this LDAP server
+ // treat same as not attributes found
+ attrs = EMPTY_ATTRIBUTES;
+ }
+ for (String attrId : requestedAttributes) {
+ Attribute attr = attrs.get(attrId);
+ byte[][] values = getAttributeValues(attr);
+ cacheAttribute(attrId, values);
+ valueMap.put(attrId, values);
+ }
+ return valueMap;
+ }
+
+ /**
+ * Add the values to the cache.
+ */
+ private void cacheAttribute(String attrId, byte[][] values) {
+ String cacheKey = name + "|" + attrId;
+ valueCache.put(cacheKey, values);
+ }
+
+ /**
+ * Get the values for the given attribute. If the attribute is null
+ * or does not contain any values, a zero length byte array is
+ * returned. NOTE that it is assumed that all values are byte arrays.
+ */
+ private byte[][] getAttributeValues(Attribute attr)
+ throws NamingException {
+ byte[][] values;
+ if (attr == null) {
+ values = BB0;
+ } else {
+ values = new byte[attr.size()][];
+ int i = 0;
+ NamingEnumeration<?> enum_ = attr.getAll();
+ while (enum_.hasMore()) {
+ Object obj = enum_.next();
+ if (debug != null) {
+ if (obj instanceof String) {
+ debug.println("LDAPCertStore.getAttrValues() "
+ + "enum.next is a string!: " + obj);
+ }
+ }
+ byte[] value = (byte[])obj;
+ values[i++] = value;
+ }
+ }
+ return values;
+ }
+
+ }
+
+ /*
+ * Gets certificates from an attribute id and location in the LDAP
+ * directory. Returns a Collection containing only the Certificates that
+ * match the specified CertSelector.
+ *
+ * @param name the location holding the attribute
+ * @param id the attribute identifier
+ * @param sel a CertSelector that the Certificates must match
+ * @return a Collection of Certificates found
+ * @throws CertStoreException if an exception occurs
+ */
+ private Collection<X509Certificate> getCertificates(LDAPRequest request,
+ String id, X509CertSelector sel) throws CertStoreException {
+
+ /* fetch encoded certs from storage */
+ byte[][] encodedCert;
+ try {
+ encodedCert = request.getValues(id);
+ } catch (NamingException namingEx) {
+ throw new CertStoreException(namingEx);
+ }
+
+ int n = encodedCert.length;
+ if (n == 0) {
+ return Collections.<X509Certificate>emptySet();
+ }
+
+ List<X509Certificate> certs = new ArrayList<X509Certificate>(n);
+ /* decode certs and check if they satisfy selector */
+ for (int i = 0; i < n; i++) {
+ ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]);
+ try {
+ Certificate cert = cf.generateCertificate(bais);
+ if (sel.match(cert)) {
+ certs.add((X509Certificate)cert);
+ }
+ } catch (CertificateException e) {
+ if (debug != null) {
+ debug.println("LDAPCertStore.getCertificates() encountered "
+ + "exception while parsing cert, skipping the bad data: ");
+ HexDumpEncoder encoder = new HexDumpEncoder();
+ debug.println(
+ "[ " + encoder.encodeBuffer(encodedCert[i]) + " ]");
+ }
+ }
+ }
+
+ return certs;
+ }
+
+ /*
+ * Gets certificate pairs from an attribute id and location in the LDAP
+ * directory.
+ *
+ * @param name the location holding the attribute
+ * @param id the attribute identifier
+ * @return a Collection of X509CertificatePairs found
+ * @throws CertStoreException if an exception occurs
+ */
+ private Collection<X509CertificatePair> getCertPairs(
+ LDAPRequest request, String id) throws CertStoreException {
+
+ /* fetch the encoded cert pairs from storage */
+ byte[][] encodedCertPair;
+ try {
+ encodedCertPair = request.getValues(id);
+ } catch (NamingException namingEx) {
+ throw new CertStoreException(namingEx);
+ }
+
+ int n = encodedCertPair.length;
+ if (n == 0) {
+ return Collections.<X509CertificatePair>emptySet();
+ }
+
+ List<X509CertificatePair> certPairs =
+ new ArrayList<X509CertificatePair>(n);
+ /* decode each cert pair and add it to the Collection */
+ for (int i = 0; i < n; i++) {
+ try {
+ X509CertificatePair certPair =
+ X509CertificatePair.generateCertificatePair(encodedCertPair[i]);
+ certPairs.add(certPair);
+ } catch (CertificateException e) {
+ if (debug != null) {
+ debug.println(
+ "LDAPCertStore.getCertPairs() encountered exception "
+ + "while parsing cert, skipping the bad data: ");
+ HexDumpEncoder encoder = new HexDumpEncoder();
+ debug.println(
+ "[ " + encoder.encodeBuffer(encodedCertPair[i]) + " ]");
+ }
+ }
+ }
+
+ return certPairs;
+ }
+
+ /*
+ * Looks at certificate pairs stored in the crossCertificatePair attribute
+ * at the specified location in the LDAP directory. Returns a Collection
+ * containing all Certificates stored in the forward component that match
+ * the forward CertSelector and all Certificates stored in the reverse
+ * component that match the reverse CertSelector.
+ * <p>
+ * If either forward or reverse is null, all certificates from the
+ * corresponding component will be rejected.
+ *
+ * @param name the location to look in
+ * @param forward the forward CertSelector (or null)
+ * @param reverse the reverse CertSelector (or null)
+ * @return a Collection of Certificates found
+ * @throws CertStoreException if an exception occurs
+ */
+ private Collection<X509Certificate> getMatchingCrossCerts(
+ LDAPRequest request, X509CertSelector forward,
+ X509CertSelector reverse)
+ throws CertStoreException {
+ // Get the cert pairs
+ Collection<X509CertificatePair> certPairs =
+ getCertPairs(request, CROSS_CERT);
+
+ // Find Certificates that match and put them in a list
+ ArrayList<X509Certificate> matchingCerts =
+ new ArrayList<X509Certificate>();
+ for (X509CertificatePair certPair : certPairs) {
+ X509Certificate cert;
+ if (forward != null) {
+ cert = certPair.getForward();
+ if ((cert != null) && forward.match(cert)) {
+ matchingCerts.add(cert);
+ }
+ }
+ if (reverse != null) {
+ cert = certPair.getReverse();
+ if ((cert != null) && reverse.match(cert)) {
+ matchingCerts.add(cert);
+ }
+ }
+ }
+ return matchingCerts;
+ }
+
+ /**
+ * Returns a <code>Collection</code> of <code>Certificate</code>s that
+ * match the specified selector. If no <code>Certificate</code>s
+ * match the selector, an empty <code>Collection</code> will be returned.
+ * <p>
+ * It is not practical to search every entry in the LDAP database for
+ * matching <code>Certificate</code>s. Instead, the <code>CertSelector</code>
+ * is examined in order to determine where matching <code>Certificate</code>s
+ * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
+ * If the subject is specified, its directory entry is searched. If the
+ * issuer is specified, its directory entry is searched. If neither the
+ * subject nor the issuer are specified (or the selector is not an
+ * <code>X509CertSelector</code>), a <code>CertStoreException</code> is
+ * thrown.
+ *
+ * @param selector a <code>CertSelector</code> used to select which
+ * <code>Certificate</code>s should be returned.
+ * @return a <code>Collection</code> of <code>Certificate</code>s that
+ * match the specified selector
+ * @throws CertStoreException if an exception occurs
+ */
+ public synchronized Collection<X509Certificate> engineGetCertificates
+ (CertSelector selector) throws CertStoreException {
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() selector: "
+ + String.valueOf(selector));
+ }
+
+ if (selector == null) {
+ selector = new X509CertSelector();
+ }
+ if (!(selector instanceof X509CertSelector)) {
+ throw new CertStoreException("LDAPCertStore needs an X509CertSelector " +
+ "to find certs");
+ }
+ X509CertSelector xsel = (X509CertSelector) selector;
+ int basicConstraints = xsel.getBasicConstraints();
+ String subject = xsel.getSubjectAsString();
+ String issuer = xsel.getIssuerAsString();
+ HashSet<X509Certificate> certs = new HashSet<X509Certificate>();
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: "
+ + basicConstraints);
+ }
+
+ // basicConstraints:
+ // -2: only EE certs accepted
+ // -1: no check is done
+ // 0: any CA certificate accepted
+ // >1: certificate's basicConstraints extension pathlen must match
+ if (subject != null) {
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() "
+ + "subject is not null");
+ }
+ LDAPRequest request = new LDAPRequest(subject);
+ if (basicConstraints > -2) {
+ request.addRequestedAttribute(CROSS_CERT);
+ request.addRequestedAttribute(CA_CERT);
+ request.addRequestedAttribute(ARL);
+ if (prefetchCRLs) {
+ request.addRequestedAttribute(CRL);
+ }
+ }
+ if (basicConstraints < 0) {
+ request.addRequestedAttribute(USER_CERT);
+ }
+
+ if (basicConstraints > -2) {
+ certs.addAll(getMatchingCrossCerts(request, xsel, null));
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() after "
+ + "getMatchingCrossCerts(subject,xsel,null),certs.size(): "
+ + certs.size());
+ }
+ certs.addAll(getCertificates(request, CA_CERT, xsel));
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() after "
+ + "getCertificates(subject,CA_CERT,xsel),certs.size(): "
+ + certs.size());
+ }
+ }
+ if (basicConstraints < 0) {
+ certs.addAll(getCertificates(request, USER_CERT, xsel));
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() after "
+ + "getCertificates(subject,USER_CERT, xsel),certs.size(): "
+ + certs.size());
+ }
+ }
+ } else {
+ if (debug != null) {
+ debug.println
+ ("LDAPCertStore.engineGetCertificates() subject is null");
+ }
+ if (basicConstraints == -2) {
+ throw new CertStoreException("need subject to find EE certs");
+ }
+ if (issuer == null) {
+ throw new CertStoreException("need subject or issuer to find certs");
+ }
+ }
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() about to "
+ + "getMatchingCrossCerts...");
+ }
+ if ((issuer != null) && (basicConstraints > -2)) {
+ LDAPRequest request = new LDAPRequest(issuer);
+ request.addRequestedAttribute(CROSS_CERT);
+ request.addRequestedAttribute(CA_CERT);
+ request.addRequestedAttribute(ARL);
+ if (prefetchCRLs) {
+ request.addRequestedAttribute(CRL);
+ }
+
+ certs.addAll(getMatchingCrossCerts(request, null, xsel));
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() after "
+ + "getMatchingCrossCerts(issuer,null,xsel),certs.size(): "
+ + certs.size());
+ }
+ certs.addAll(getCertificates(request, CA_CERT, xsel));
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() after "
+ + "getCertificates(issuer,CA_CERT,xsel),certs.size(): "
+ + certs.size());
+ }
+ }
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCertificates() returning certs");
+ }
+ return certs;
+ }
+
+ /*
+ * Gets CRLs from an attribute id and location in the LDAP directory.
+ * Returns a Collection containing only the CRLs that match the
+ * specified CRLSelector.
+ *
+ * @param name the location holding the attribute
+ * @param id the attribute identifier
+ * @param sel a CRLSelector that the CRLs must match
+ * @return a Collection of CRLs found
+ * @throws CertStoreException if an exception occurs
+ */
+ private Collection<X509CRL> getCRLs(LDAPRequest request, String id,
+ X509CRLSelector sel) throws CertStoreException {
+
+ /* fetch the encoded crls from storage */
+ byte[][] encodedCRL;
+ try {
+ encodedCRL = request.getValues(id);
+ } catch (NamingException namingEx) {
+ throw new CertStoreException(namingEx);
+ }
+
+ int n = encodedCRL.length;
+ if (n == 0) {
+ return Collections.<X509CRL>emptySet();
+ }
+
+ List<X509CRL> crls = new ArrayList<X509CRL>(n);
+ /* decode each crl and check if it matches selector */
+ for (int i = 0; i < n; i++) {
+ try {
+ CRL crl = cf.generateCRL(new ByteArrayInputStream(encodedCRL[i]));
+ if (sel.match(crl)) {
+ crls.add((X509CRL)crl);
+ }
+ } catch (CRLException e) {
+ if (debug != null) {
+ debug.println("LDAPCertStore.getCRLs() encountered exception"
+ + " while parsing CRL, skipping the bad data: ");
+ HexDumpEncoder encoder = new HexDumpEncoder();
+ debug.println("[ " + encoder.encodeBuffer(encodedCRL[i]) + " ]");
+ }
+ }
+ }
+
+ return crls;
+ }
+
+ /**
+ * Returns a <code>Collection</code> of <code>CRL</code>s that
+ * match the specified selector. If no <code>CRL</code>s
+ * match the selector, an empty <code>Collection</code> will be returned.
+ * <p>
+ * It is not practical to search every entry in the LDAP database for
+ * matching <code>CRL</code>s. Instead, the <code>CRLSelector</code>
+ * is examined in order to determine where matching <code>CRL</code>s
+ * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
+ * If issuerNames or certChecking are specified, the issuer's directory
+ * entry is searched. If neither issuerNames or certChecking are specified
+ * (or the selector is not an <code>X509CRLSelector</code>), a
+ * <code>CertStoreException</code> is thrown.
+ *
+ * @param selector A <code>CRLSelector</code> used to select which
+ * <code>CRL</code>s should be returned. Specify <code>null</code>
+ * to return all <code>CRL</code>s.
+ * @return A <code>Collection</code> of <code>CRL</code>s that
+ * match the specified selector
+ * @throws CertStoreException if an exception occurs
+ */
+ public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
+ throws CertStoreException {
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCRLs() selector: "
+ + selector);
+ }
+ // Set up selector and collection to hold CRLs
+ if (selector == null) {
+ selector = new X509CRLSelector();
+ }
+ if (!(selector instanceof X509CRLSelector)) {
+ throw new CertStoreException("need X509CRLSelector to find CRLs");
+ }
+ X509CRLSelector xsel = (X509CRLSelector) selector;
+ HashSet<X509CRL> crls = new HashSet<X509CRL>();
+
+ // Look in directory entry for issuer of cert we're checking.
+ Collection<Object> issuerNames;
+ X509Certificate certChecking = xsel.getCertificateChecking();
+ if (certChecking != null) {
+ issuerNames = new HashSet<Object>();
+ X500Principal issuer = certChecking.getIssuerX500Principal();
+ issuerNames.add(issuer.getName(X500Principal.RFC2253));
+ } else {
+ // But if we don't know which cert we're checking, try the directory
+ // entries of all acceptable CRL issuers
+ issuerNames = xsel.getIssuerNames();
+ if (issuerNames == null) {
+ throw new CertStoreException("need issuerNames or certChecking to "
+ + "find CRLs");
+ }
+ }
+ for (Object nameObject : issuerNames) {
+ String issuerName;
+ if (nameObject instanceof byte[]) {
+ try {
+ X500Principal issuer = new X500Principal((byte[])nameObject);
+ issuerName = issuer.getName(X500Principal.RFC2253);
+ } catch (IllegalArgumentException e) {
+ continue;
+ }
+ } else {
+ issuerName = (String)nameObject;
+ }
+ // If all we want is CA certs, try to get the (probably shorter) ARL
+ Collection<X509CRL> entryCRLs = Collections.<X509CRL>emptySet();
+ if (certChecking == null || certChecking.getBasicConstraints() != -1) {
+ LDAPRequest request = new LDAPRequest(issuerName);
+ request.addRequestedAttribute(CROSS_CERT);
+ request.addRequestedAttribute(CA_CERT);
+ request.addRequestedAttribute(ARL);
+ if (prefetchCRLs) {
+ request.addRequestedAttribute(CRL);
+ }
+ try {
+ entryCRLs = getCRLs(request, ARL, xsel);
+ if (entryCRLs.isEmpty()) {
+ // no ARLs found. We assume that means that there are
+ // no ARLs on this server at all and prefetch the CRLs.
+ prefetchCRLs = true;
+ } else {
+ crls.addAll(entryCRLs);
+ }
+ } catch (CertStoreException e) {
+ if (debug != null) {
+ debug.println("LDAPCertStore.engineGetCRLs non-fatal error "
+ + "retrieving ARLs:" + e);
+ e.printStackTrace();
+ }
+ }
+ }
+ // Otherwise, get the CRL
+ // if certChecking is null, we don't know if we should look in ARL or CRL
+ // attribute, so check both for matching CRLs.
+ if (entryCRLs.isEmpty() || certChecking == null) {
+ LDAPRequest request = new LDAPRequest(issuerName);
+ request.addRequestedAttribute(CRL);
+ entryCRLs = getCRLs(request, CRL, xsel);
+ crls.addAll(entryCRLs);
+ }
+ }
+ return crls;
+ }
+
+ // converts an LDAP URI into LDAPCertStoreParameters
+ static LDAPCertStoreParameters getParameters(URI uri) {
+ String host = uri.getHost();
+ if (host == null) {
+ return new SunLDAPCertStoreParameters();
+ } else {
+ int port = uri.getPort();
+ return (port == -1
+ ? new SunLDAPCertStoreParameters(host)
+ : new SunLDAPCertStoreParameters(host, port));
+ }
+ }
+
+ /*
+ * Subclass of LDAPCertStoreParameters with overridden equals/hashCode
+ * methods. This is necessary because the parameters are used as
+ * keys in the LDAPCertStore cache.
+ */
+ private static class SunLDAPCertStoreParameters
+ extends LDAPCertStoreParameters {
+
+ private volatile int hashCode = 0;
+
+ SunLDAPCertStoreParameters(String serverName, int port) {
+ super(serverName, port);
+ }
+ SunLDAPCertStoreParameters(String serverName) {
+ super(serverName);
+ }
+ SunLDAPCertStoreParameters() {
+ super();
+ }
+ public boolean equals(Object obj) {
+ if (!(obj instanceof LDAPCertStoreParameters)) {
+ return false;
+ }
+ LDAPCertStoreParameters params = (LDAPCertStoreParameters) obj;
+ return (getPort() == params.getPort() &&
+ getServerName().equalsIgnoreCase(params.getServerName()));
+ }
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = 17;
+ result = 37*result + getPort();
+ result = 37*result + getServerName().toLowerCase().hashCode();
+ hashCode = result;
+ }
+ return hashCode;
+ }
+ }
+
+ /*
+ * This inner class wraps an existing X509CertSelector and adds
+ * additional criteria to match on when the certificate's subject is
+ * different than the LDAP Distinguished Name entry. The LDAPCertStore
+ * implementation uses the subject DN as the directory entry for
+ * looking up certificates. This can be problematic if the certificates
+ * that you want to fetch have a different subject DN than the entry
+ * where they are stored. You could set the selector's subject to the
+ * LDAP DN entry, but then the resulting match would fail to find the
+ * desired certificates because the subject DNs would not match. This
+ * class avoids that problem by introducing a certSubject which should
+ * be set to the certificate's subject DN when it is different than
+ * the LDAP DN.
+ */
+ static class LDAPCertSelector extends X509CertSelector {
+
+ private X500Principal certSubject;
+ private X509CertSelector selector;
+ private X500Principal subject;
+
+ /**
+ * Creates an LDAPCertSelector.
+ *
+ * @param selector the X509CertSelector to wrap
+ * @param certSubject the subject DN of the certificate that you want
+ * to retrieve via LDAP
+ * @param ldapDN the LDAP DN where the certificate is stored
+ */
+ LDAPCertSelector(X509CertSelector selector, X500Principal certSubject,
+ String ldapDN) throws IOException {
+ this.selector = selector == null ? new X509CertSelector() : selector;
+ this.certSubject = certSubject;
+ this.subject = new X500Name(ldapDN).asX500Principal();
+ }
+
+ // we only override the get (accessor methods) since the set methods
+ // will not be invoked by the code that uses this LDAPCertSelector.
+ public X509Certificate getCertificate() {
+ return selector.getCertificate();
+ }
+ public BigInteger getSerialNumber() {
+ return selector.getSerialNumber();
+ }
+ public X500Principal getIssuer() {
+ return selector.getIssuer();
+ }
+ public String getIssuerAsString() {
+ return selector.getIssuerAsString();
+ }
+ public byte[] getIssuerAsBytes() throws IOException {
+ return selector.getIssuerAsBytes();
+ }
+ public X500Principal getSubject() {
+ // return the ldap DN
+ return subject;
+ }
+ public String getSubjectAsString() {
+ // return the ldap DN
+ return subject.getName();
+ }
+ public byte[] getSubjectAsBytes() throws IOException {
+ // return the encoded ldap DN
+ return subject.getEncoded();
+ }
+ public byte[] getSubjectKeyIdentifier() {
+ return selector.getSubjectKeyIdentifier();
+ }
+ public byte[] getAuthorityKeyIdentifier() {
+ return selector.getAuthorityKeyIdentifier();
+ }
+ public Date getCertificateValid() {
+ return selector.getCertificateValid();
+ }
+ public Date getPrivateKeyValid() {
+ return selector.getPrivateKeyValid();
+ }
+ public String getSubjectPublicKeyAlgID() {
+ return selector.getSubjectPublicKeyAlgID();
+ }
+ public PublicKey getSubjectPublicKey() {
+ return selector.getSubjectPublicKey();
+ }
+ public boolean[] getKeyUsage() {
+ return selector.getKeyUsage();
+ }
+ public Set<String> getExtendedKeyUsage() {
+ return selector.getExtendedKeyUsage();
+ }
+ public boolean getMatchAllSubjectAltNames() {
+ return selector.getMatchAllSubjectAltNames();
+ }
+ public Collection<List<?>> getSubjectAlternativeNames() {
+ return selector.getSubjectAlternativeNames();
+ }
+ public byte[] getNameConstraints() {
+ return selector.getNameConstraints();
+ }
+ public int getBasicConstraints() {
+ return selector.getBasicConstraints();
+ }
+ public Set<String> getPolicy() {
+ return selector.getPolicy();
+ }
+ public Collection<List<?>> getPathToNames() {
+ return selector.getPathToNames();
+ }
+
+ public boolean match(Certificate cert) {
+ // temporarily set the subject criterion to the certSubject
+ // so that match will not reject the desired certificates
+ selector.setSubject(certSubject);
+ boolean match = selector.match(cert);
+ selector.setSubject(subject);
+ return match;
+ }
+ }
+
+ /**
+ * This class has the same purpose as LDAPCertSelector except it is for
+ * X.509 CRLs.
+ */
+ static class LDAPCRLSelector extends X509CRLSelector {
+
+ private X509CRLSelector selector;
+ private Collection<X500Principal> certIssuers;
+ private Collection<X500Principal> issuers;
+ private HashSet<Object> issuerNames;
+
+ /**
+ * Creates an LDAPCRLSelector.
+ *
+ * @param selector the X509CRLSelector to wrap
+ * @param certIssuers the issuer DNs of the CRLs that you want
+ * to retrieve via LDAP
+ * @param ldapDN the LDAP DN where the CRL is stored
+ */
+ LDAPCRLSelector(X509CRLSelector selector,
+ Collection<X500Principal> certIssuers, String ldapDN)
+ throws IOException {
+ this.selector = selector == null ? new X509CRLSelector() : selector;
+ this.certIssuers = certIssuers;
+ issuerNames = new HashSet<Object>();
+ issuerNames.add(ldapDN);
+ issuers = new HashSet<X500Principal>();
+ issuers.add(new X500Name(ldapDN).asX500Principal());
+ }
+ // we only override the get (accessor methods) since the set methods
+ // will not be invoked by the code that uses this LDAPCRLSelector.
+ public Collection<X500Principal> getIssuers() {
+ // return the ldap DN
+ return Collections.unmodifiableCollection(issuers);
+ }
+ public Collection<Object> getIssuerNames() {
+ // return the ldap DN
+ return Collections.unmodifiableCollection(issuerNames);
+ }
+ public BigInteger getMinCRL() {
+ return selector.getMinCRL();
+ }
+ public BigInteger getMaxCRL() {
+ return selector.getMaxCRL();
+ }
+ public Date getDateAndTime() {
+ return selector.getDateAndTime();
+ }
+ public X509Certificate getCertificateChecking() {
+ return selector.getCertificateChecking();
+ }
+ public boolean match(CRL crl) {
+ // temporarily set the issuer criterion to the certIssuers
+ // so that match will not reject the desired CRL
+ selector.setIssuers(certIssuers);
+ boolean match = selector.match(crl);
+ selector.setIssuers(issuers);
+ return match;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java Wed Oct 14 14:21:25 2009 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 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.certpath.ldap;
+
+import java.net.URI;
+import java.util.Collection;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.cert.CertStore;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509CRLSelector;
+import javax.security.auth.x500.X500Principal;
+import java.io.IOException;
+
+import sun.security.provider.certpath.CertStoreHelper;
+
+/**
+ * LDAP implementation of CertStoreHelper.
+ */
+
+public class LDAPCertStoreHelper
+ implements CertStoreHelper
+{
+ public LDAPCertStoreHelper() { }
+
+ @Override
+ public CertStore getCertStore(URI uri)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException
+ {
+ return LDAPCertStore.getInstance(LDAPCertStore.getParameters(uri));
+ }
+
+ @Override
+ public X509CertSelector wrap(X509CertSelector selector,
+ X500Principal certSubject,
+ String ldapDN)
+ throws IOException
+ {
+ return new LDAPCertStore.LDAPCertSelector(selector, certSubject, ldapDN);
+ }
+
+ @Override
+ public X509CRLSelector wrap(X509CRLSelector selector,
+ Collection<X500Principal> certIssuers,
+ String ldapDN)
+ throws IOException
+ {
+ return new LDAPCertStore.LDAPCRLSelector(selector, certIssuers, ldapDN);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/DefaultAccessibility.java Wed Oct 14 14:21:25 2009 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6648344
+ * @summary Test that default accessibility is false
+ * @author Joseph D. Darcy
+ */
+
+import java.lang.reflect.*;
+
+public class DefaultAccessibility {
+ private DefaultAccessibility() {
+ super();
+ }
+
+ private static int f = 42;
+
+ public static void main(String... args) throws Exception {
+ Class<?> daClass = (new DefaultAccessibility()).getClass();
+
+ int elementCount = 0;
+ for(Constructor<?> ctor : daClass.getDeclaredConstructors()) {
+ elementCount++;
+ if (ctor.isAccessible())
+ throw new RuntimeException("Unexpected accessibility for constructor " +
+ ctor);
+ }
+
+ for(Method method : daClass.getDeclaredMethods()) {
+ elementCount++;
+ if (method.isAccessible())
+ throw new RuntimeException("Unexpected accessibility for method " +
+ method);
+ }
+
+ for(Field field : daClass.getDeclaredFields()) {
+ elementCount++;
+ if (field.isAccessible())
+ throw new RuntimeException("Unexpected accessibility for field " +
+ field);
+ }
+
+ if (elementCount < 3)
+ throw new RuntimeException("Expected at least three members; only found " +
+ elementCount);
+ }
+}
--- a/jdk/test/java/net/MulticastSocket/SetOutgoingIf.java Wed Oct 07 08:38:43 2009 -0700
+++ b/jdk/test/java/net/MulticastSocket/SetOutgoingIf.java Wed Oct 14 14:21:25 2009 -0700
@@ -27,7 +27,6 @@
* @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code
*/
import java.net.*;
-import java.util.concurrent.*;
import java.util.*;
@@ -68,38 +67,61 @@
// We need 2 or more network interfaces to run the test
//
- List<NetworkInterface> nics = new ArrayList<NetworkInterface>();
+ List<NetIf> netIfs = new ArrayList<NetIf>();
+ int index = 1;
for (NetworkInterface nic : Collections.list(NetworkInterface.getNetworkInterfaces())) {
// we should use only network interfaces with multicast support which are in "up" state
- if (!nic.isLoopback() && nic.supportsMulticast() && nic.isUp())
- nics.add(nic);
+ if (!nic.isLoopback() && nic.supportsMulticast() && nic.isUp()) {
+ NetIf netIf = NetIf.create(nic);
+
+ // now determine what (if any) type of addresses are assigned to this interface
+ for (InetAddress addr : Collections.list(nic.getInetAddresses())) {
+ if (addr instanceof Inet4Address) {
+ netIf.ipv4Address(true);
+ } else if (addr instanceof Inet6Address) {
+ netIf.ipv6Address(true);
+ }
+ }
+ if (netIf.ipv4Address() || netIf.ipv6Address()) {
+ netIf.index(index++);
+ netIfs.add(netIf);
+ debug("Using: " + nic);
+ }
+ }
}
- if (nics.size() <= 1) {
+ if (netIfs.size() <= 1) {
System.out.println("Need 2 or more network interfaces to run. Bye.");
return;
}
- // We will send packets to one ipv4, one ipv4-mapped, and one ipv6
+ // We will send packets to one ipv4, and one ipv6
// multicast group using each network interface :-
// 224.1.1.1 --|
- // ::ffff:224.1.1.2 -----> using network interface #1
- // ff02::1:1 --|
+ // ff02::1:1 --|--> using network interface #1
// 224.1.2.1 --|
- // ::ffff:224.1.2.2 -----> using network interface #2
- // ff02::1:2 --|
+ // ff02::1:2 --|--> using network interface #2
// and so on.
//
- List<InetAddress> groups = new ArrayList<InetAddress>();
- for (int i = 0; i < nics.size(); i++) {
- InetAddress groupv4 = InetAddress.getByName("224.1." + (i+1) + ".1");
- InetAddress groupv4mapped = InetAddress.getByName("::ffff:224.1." + (i+1) + ".2");
- InetAddress groupv6 = InetAddress.getByName("ff02::1:" + (i+1));
- groups.add(groupv4);
- groups.add(groupv4mapped);
- groups.add(groupv6);
+ for (NetIf netIf : netIfs) {
+ int NetIfIndex = netIf.index();
+ List<InetAddress> groups = new ArrayList<InetAddress>();
- // use a separated thread to send to those 3 groups
- Thread sender = new Thread(new Sender(nics.get(i), groupv4, groupv4mapped, groupv6, PORT));
+ if (netIf.ipv4Address()) {
+ InetAddress groupv4 = InetAddress.getByName("224.1." + NetIfIndex + ".1");
+ groups.add(groupv4);
+ }
+ if (netIf.ipv6Address()) {
+ InetAddress groupv6 = InetAddress.getByName("ff02::1:" + NetIfIndex);
+ groups.add(groupv6);
+ }
+
+ debug("Adding " + groups + " groups for " + netIf.nic().getName());
+ netIf.groups(groups);
+
+ // use a separated thread to send to those 2 groups
+ Thread sender = new Thread(new Sender(netIf,
+ groups,
+ PORT));
sender.setDaemon(true); // we want sender to stop when main thread exits
sender.start();
}
@@ -108,75 +130,135 @@
// from the expected network interface
//
byte[] buf = new byte[1024];
- for (InetAddress group : groups) {
- MulticastSocket mcastsock = new MulticastSocket(PORT);
- mcastsock.setSoTimeout(5000); // 5 second
- DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
-
- mcastsock.joinGroup(new InetSocketAddress(group, PORT), nics.get(groups.indexOf(group) / 3));
+ for (NetIf netIf : netIfs) {
+ NetworkInterface nic = netIf.nic();
+ for (InetAddress group : netIf.groups()) {
+ MulticastSocket mcastsock = new MulticastSocket(PORT);
+ mcastsock.setSoTimeout(5000); // 5 second
+ DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
- try {
- mcastsock.receive(packet);
- } catch (Exception e) {
- // test failed if any exception
- throw new RuntimeException(e);
- }
+ // the interface supports the IP multicast group
+ debug("Joining " + group + " on " + nic.getName());
+ mcastsock.joinGroup(new InetSocketAddress(group, PORT), nic);
+
+ try {
+ mcastsock.receive(packet);
+ debug("received packet on " + packet.getAddress());
+ } catch (Exception e) {
+ // test failed if any exception
+ throw new RuntimeException(e);
+ }
- // now check which network interface this packet comes from
- NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress());
- NetworkInterface shouldbe = nics.get(groups.indexOf(group) / 3);
- if (!from.equals(shouldbe)) {
- System.out.println("Packets on group "
- + group + " should come from "
- + shouldbe.getName() + ", but came from "
- + from.getName());
- //throw new RuntimeException("Test failed.");
+ // now check which network interface this packet comes from
+ NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress());
+ NetworkInterface shouldbe = nic;
+ if (!from.equals(shouldbe)) {
+ System.out.println("Packets on group "
+ + group + " should come from "
+ + shouldbe.getName() + ", but came from "
+ + from.getName());
+ //throw new RuntimeException("Test failed.");
+ }
+
+ mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic);
}
+ }
+ }
- mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nics.get(groups.indexOf(group) / 3));
- }
+ private static boolean debug = true;
+
+ static void debug(String message) {
+ if (debug)
+ System.out.println(message);
}
}
class Sender implements Runnable {
- private NetworkInterface nic;
- private InetAddress group1;
- private InetAddress group2;
- private InetAddress group3;
+ private NetIf netIf;
+ private List<InetAddress> groups;
private int port;
- public Sender(NetworkInterface nic,
- InetAddress groupv4, InetAddress groupv4mapped, InetAddress groupv6,
- int port) {
- this.nic = nic;
- group1 = groupv4;
- group2 = groupv4mapped;
- group3 = groupv6;
+ public Sender(NetIf netIf,
+ List<InetAddress> groups,
+ int port) {
+ this.netIf = netIf;
+ this.groups = groups;
this.port = port;
}
public void run() {
try {
MulticastSocket mcastsock = new MulticastSocket();
- mcastsock.setNetworkInterface(nic);
+ mcastsock.setNetworkInterface(netIf.nic());
+ List<DatagramPacket> packets = new LinkedList<DatagramPacket>();
byte[] buf = "hello world".getBytes();
- DatagramPacket packet1 = new DatagramPacket(buf, buf.length,
- new InetSocketAddress(group1, port));
- DatagramPacket packet2 = new DatagramPacket(buf, buf.length,
- new InetSocketAddress(group2, port));
- DatagramPacket packet3 = new DatagramPacket(buf, buf.length,
- new InetSocketAddress(group3, port));
+ for (InetAddress group : groups) {
+ packets.add(new DatagramPacket(buf, buf.length, new InetSocketAddress(group, port)));
+ }
for (;;) {
- mcastsock.send(packet1);
- mcastsock.send(packet2);
- mcastsock.send(packet3);
+ for (DatagramPacket packet : packets)
+ mcastsock.send(packet);
- Thread.currentThread().sleep(1000); // sleep 1 second
+ Thread.sleep(1000); // sleep 1 second
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
+
+@SuppressWarnings("unchecked")
+class NetIf {
+ private boolean ipv4Address; //false
+ private boolean ipv6Address; //false
+ private int index;
+ List<InetAddress> groups = Collections.EMPTY_LIST;
+ private final NetworkInterface nic;
+
+ private NetIf(NetworkInterface nic) {
+ this.nic = nic;
+ }
+
+ static NetIf create(NetworkInterface nic) {
+ return new NetIf(nic);
+ }
+
+ NetworkInterface nic() {
+ return nic;
+ }
+
+ boolean ipv4Address() {
+ return ipv4Address;
+ }
+
+ void ipv4Address(boolean ipv4Address) {
+ this.ipv4Address = ipv4Address;
+ }
+
+ boolean ipv6Address() {
+ return ipv6Address;
+ }
+
+ void ipv6Address(boolean ipv6Address) {
+ this.ipv6Address = ipv6Address;
+ }
+
+ int index() {
+ return index;
+ }
+
+ void index(int index) {
+ this.index = index;
+ }
+
+ List<InetAddress> groups() {
+ return groups;
+ }
+
+ void groups(List<InetAddress> groups) {
+ this.groups = groups;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Objects/BasicObjectsTest.java Wed Oct 14 14:21:25 2009 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6797535
+ * @summary Basic tests for methods in java.util.Objects
+ * @author Joseph D. Darcy
+ */
+
+import java.util.*;
+
+public class BasicObjectsTest {
+ public static void main(String... args) {
+ int errors = 0;
+ errors += testEquals();
+ errors += testHashCode();
+ errors += testToString();
+ errors += testCompare();
+ if (errors > 0 )
+ throw new RuntimeException();
+ }
+
+ private static int testEquals() {
+ int errors = 0;
+ Object[] values = {null, "42", 42};
+ for(int i = 0; i < values.length; i++)
+ for(int j = 0; j < values.length; j++) {
+ boolean expected = (i == j);
+ Object a = values[i];
+ Object b = values[j];
+ boolean result = Objects.equals(a, b);
+ if (result != expected) {
+ errors++;
+ System.err.printf("When equating %s to %s, got %b instead of %b%n.",
+ a, b, result, expected);
+ }
+ }
+ return errors;
+ }
+
+ private static int testHashCode() {
+ int errors = 0;
+ errors += (Objects.hashCode(null) == 0 ) ? 0 : 1;
+ String s = "42";
+ errors += (Objects.hashCode(s) == s.hashCode() ) ? 0 : 1;
+ return errors;
+ }
+
+ private static int testToString() {
+ int errors = 0;
+ errors += ("null".equals(Objects.toString(null)) ) ? 0 : 1;
+ String s = "Some string";
+ errors += (s.equals(Objects.toString(s)) ) ? 0 : 1;
+ return errors;
+ }
+
+ private static int testCompare() {
+ int errors = 0;
+ String[] values = {"e. e. cummings", "zzz"};
+ String[] VALUES = {"E. E. Cummings", "ZZZ"};
+ errors += compareTest(null, null, 0);
+ for(int i = 0; i < values.length; i++) {
+ String a = values[i];
+ errors += compareTest(a, a, 0);
+ for(int j = 0; j < VALUES.length; j++) {
+ int expected = Integer.compare(i, j);
+ String b = VALUES[j];
+ errors += compareTest(a, b, expected);
+ }
+ }
+ return errors;
+ }
+
+ private static int compareTest(String a, String b, int expected) {
+ int errors = 0;
+ int result = Objects.compare(a, b, String.CASE_INSENSITIVE_ORDER);
+ if (Integer.signum(result) != Integer.signum(expected)) {
+ errors++;
+ System.err.printf("When comparing %s to %s, got %d instead of %d%n.",
+ a, b, result, expected);
+ }
+ return errors;
+ }
+}