aboutsummaryrefslogtreecommitdiff
path: root/libjava/javax/security/sasl/Sasl.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/javax/security/sasl/Sasl.java')
-rw-r--r--libjava/javax/security/sasl/Sasl.java691
1 files changed, 691 insertions, 0 deletions
diff --git a/libjava/javax/security/sasl/Sasl.java b/libjava/javax/security/sasl/Sasl.java
new file mode 100644
index 00000000000..2174692f4b4
--- /dev/null
+++ b/libjava/javax/security/sasl/Sasl.java
@@ -0,0 +1,691 @@
+/* Sasl.java
+ Copyright (C) 2003, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307 USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.security.sasl;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Vector;
+import java.security.Security;
+import java.security.Provider;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * <p>A static class for creating SASL clients and servers.</p>
+ *
+ * <p>This class defines the policy of how to locate, load, and instantiate SASL
+ * clients and servers.</p>
+ *
+ * <p>For example, an application or library gets a SASL client instance by
+ * doing something like:</p>
+ *
+ * <pre>
+ *SaslClient sc =
+ * Sasl.createSaslClient(mechanisms, authorizationID, protocol,
+ * serverName, props, callbackHandler);
+ * </pre>
+ *
+ * <p>It can then proceed to use the instance to create an authenticated
+ * connection.</p>
+ *
+ * <p>Similarly, a server gets a SASL server instance by using code that looks
+ * as follows:</p>
+ *
+ * <pre>
+ *SaslServer ss =
+ * Sasl.createSaslServer(mechanism, protocol, serverName, props,
+ * callbackHandler);
+ * </pre>
+ */
+public class Sasl
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>The name of a property that specifies the quality-of-protection to use.
+ * The property contains a comma-separated, ordered list of quality-of-
+ * protection values that the client or server is willing to support. A qop
+ * value is one of:</p>
+ *
+ * <ul>
+ * <li><code>"auth"</code> - authentication only,</li>
+ * <li><code>"auth-int"</code> - authentication plus integrity
+ * protection,</li>
+ * <li><code>"auth-conf"</code> - authentication plus integrity and
+ * confidentiality protection.</li>
+ * </ul>
+ *
+ * <p>The order of the list specifies the preference order of the client or
+ * server.</p>
+ *
+ * <p>If this property is absent, the default qop is <code>"auth"</code>.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.qop"</code>.</p>
+ */
+ public static final String QOP = "javax.security.sasl.qop";
+
+ /**
+ * <p>The name of a property that specifies the cipher strength to use. The
+ * property contains a comma-separated, ordered list of cipher strength
+ * values that the client or server is willing to support. A strength value
+ * is one of:</p>
+ *
+ * <ul>
+ * <li><code>"low"</code>,</li>
+ * <li><code>"medium"</code>,</li>
+ * <li><code>"high"</code>.</li>
+ * </ul>
+ *
+ * <p>The order of the list specifies the preference order of the client or
+ * server. An implementation should allow configuration of the meaning of
+ * these values. An application may use the Java Cryptography Extension (JCE)
+ * with JCE-aware mechanisms to control the selection of cipher suites that
+ * match the strength values.</p>
+ *
+ * <p>If this property is absent, the default strength is
+ * <code>"high,medium,low"</code>.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.strength"</code>.
+ * </p>
+ */
+ public static final String STRENGTH = "javax.security.sasl.strength";
+
+ /**
+ * <p>The name of a property that specifies whether the server must authenticate
+ * to the client. The property contains <code>"true"</code> if the server
+ * must authenticate the to client; <code>"false"</code> otherwise. The
+ * default is <code>"false"</code>.</p>
+ *
+ * <p>The value of this constant is
+ * <code>"javax.security.sasl.server.authentication"</code>.</p>
+ */
+ public static final String SERVER_AUTH = "javax.security.sasl.server.authentication";
+
+ /**
+ * <p>The name of a property that specifies the maximum size of the receive
+ * buffer in bytes of {@link SaslClient}/{@link SaslServer}. The property
+ * contains the string representation of an integer.</p>
+ *
+ * <p>If this property is absent, the default size is defined by the
+ * mechanism.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.maxbuffer"</code>.
+ * </p>
+ */
+ public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer";
+
+ /**
+ * <p>The name of a property that specifies the maximum size of the raw send
+ * buffer in bytes of {@link SaslClient}/{@link SaslServer}. The property
+ * contains the string representation of an integer. The value of this
+ * property is negotiated between the client and server during the
+ * authentication exchange.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.rawsendsize"</code>.
+ * </p>
+ */
+ public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize";
+
+ /**
+ * <p>The name of a property that specifies whether mechanisms susceptible
+ * to simple plain passive attacks (e.g., "PLAIN") are not permitted. The
+ * property contains <code>"true"</code> if such mechanisms are not
+ * permitted; <code>"false"</code> if such mechanisms are permitted. The
+ * default is <code>"false"</code>.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.policy.noplaintext"</code>.
+ * </p>
+ */
+ public static final String POLICY_NOPLAINTEXT = "javax.security.sasl.policy.noplaintext";
+
+ /**
+ * <p>The name of a property that specifies whether mechanisms susceptible to
+ * active (non-dictionary) attacks are not permitted. The property contains
+ * <code>"true"</code> if mechanisms susceptible to active attacks are not
+ * permitted; <code>"false"</code> if such mechanisms are permitted. The
+ * default is <code>"false"</code>.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.policy.noactive"</code>.
+ * </p>
+ */
+ public static final String POLICY_NOACTIVE = "javax.security.sasl.policy.noactive";
+
+ /**
+ * <p>The name of a property that specifies whether mechanisms susceptible to
+ * passive dictionary attacks are not permitted. The property contains
+ * <code>"true"</code> if mechanisms susceptible to dictionary attacks are
+ * not permitted; <code>"false"</code> if such mechanisms are permitted. The
+ * default is <code>"false"</code>.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.policy.nodictionary"</code>.
+ * </p>
+ */
+ public static final String POLICY_NODICTIONARY = "javax.security.sasl.policy.nodictionary";
+
+ /**
+ * <p>The name of a property that specifies whether mechanisms that accept
+ * anonymous login are not permitted. The property contains <code>"true"</code>
+ * if mechanisms that accept anonymous login are not permitted; <code>"false"
+ * </code> if such mechanisms are permitted. The default is <code>"false"</code>.
+ * </p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.policy.noanonymous"</code>.
+ * </p>
+ */
+ public static final String POLICY_NOANONYMOUS = "javax.security.sasl.policy.noanonymous";
+
+ /**
+ * The name of a property that specifies whether mechanisms that implement
+ * forward secrecy between sessions are required. Forward secrecy means that
+ * breaking into one session will not automatically provide information for
+ * breaking into future sessions. The property contains <code>"true"</code>
+ * if mechanisms that implement forward secrecy between sessions are
+ * required; <code>"false"</code> if such mechanisms are not required. The
+ * default is <code>"false"</code>.</p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.policy.forward"</code>.
+ * </p>
+ */
+ public static final String POLICY_FORWARD_SECRECY = "javax.security.sasl.policy.forward";
+
+ /**
+ * The name of a property that specifies whether mechanisms that pass client
+ * credentials are required. The property contains <code>"true"</code> if
+ * mechanisms that pass client credentials are required; <code>"false"</code>
+ * if such mechanisms are not required. The default is <code>"false"</code>.
+ * </p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.policy.credentials"</code>.
+ * </p>
+ */
+ public static final String POLICY_PASS_CREDENTIALS = "javax.security.sasl.policy.credentials";
+
+ /**
+ * <p>The name of a property that specifies whether to reuse previously
+ * authenticated session information. The property contains <code>"true"</code>
+ * if the mechanism implementation may attempt to reuse previously
+ * authenticated session information; it contains <code>"false"</code> if the
+ * implementation must not reuse previously authenticated session information.
+ * A setting of <code>"true"</code> serves only as a hint; it does not
+ * necessarily entail actual reuse because reuse might not be possible due to
+ * a number of reasons, including, but not limited to, lack of mechanism
+ * support for reuse, expiration of reusable information, and the peer's
+ * refusal to support reuse. The property's default value is <code>"false"</code>.
+ * </p>
+ *
+ * <p>The value of this constant is <code>"javax.security.sasl.reuse"</code>.
+ * Note that all other parameters and properties required to create a SASL
+ * client/server instance must be provided regardless of whether this
+ * property has been supplied. That is, you cannot supply any less
+ * information in anticipation of reuse. Mechanism implementations that
+ * support reuse might allow customization of its implementation for factors
+ * such as cache size, timeouts, and criteria for reuseability. Such
+ * customizations are implementation-dependent.</p>
+ */
+ public static final String REUSE = "javax.security.sasl.reuse";
+
+ private static final String CLIENT_FACTORY_SVC = "SaslClientFactory.";
+ private static final String SERVER_FACTORY_SVC = "SaslServerFactory.";
+ private static final String ALIAS = "Alg.Alias.";
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private Sasl()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Creates a {@link SaslClient} for the specified mechanism.</p>
+ *
+ * <p>This method uses the JCA Security Provider Framework, described in the
+ * "Java Cryptography Architecture API Specification &amp; Reference", for
+ * locating and selecting a {@link SaslClient} implementation.</p>
+ *
+ * <p>First, it obtains an ordered list of {@link SaslClientFactory}
+ * instances from the registered security providers for the
+ * <code>"SaslClientFactory"</code> service and the specified mechanism. It
+ * then invokes <code>createSaslClient()</code> on each factory instance on
+ * the list until one produces a non-null {@link SaslClient} instance. It
+ * returns the non-null {@link SaslClient} instance, or <code>null</code> if
+ * the search fails to produce a non-null {@link SaslClient} instance.</p>
+ *
+ * <p>A security provider for <code>SaslClientFactory</code> registers with
+ * the JCA Security Provider Framework keys of the form:</p>
+ *
+ * <pre>
+ * SaslClientFactory.mechanism_name
+ * </pre>
+ *
+ * <p>and values that are class names of implementations of {@link
+ * SaslClientFactory}.</p>
+ *
+ * <p>For example, a provider that contains a factory class,
+ * <code>com.wiz.sasl.digest.ClientFactory</code>, that supports the
+ * <code>"DIGEST-MD5"</code> mechanism would register the following entry
+ * with the JCA:</p>
+ *
+ * <pre>
+ * SaslClientFactory.DIGEST-MD5 com.wiz.sasl.digest.ClientFactory
+ * </pre>
+ *
+ * <p>See the "Java Cryptography Architecture API Specification &amp;
+ * Reference" for information about how to install and configure security
+ * service providers.</p>
+ *
+ * @param mechanisms the non-null list of mechanism names to try. Each is the
+ * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
+ * @param authorizationID the possibly <code>null</code> protocol-dependent
+ * identification to be used for authorization. If <code>null</code> or
+ * empty, the server derives an authorization ID from the client's
+ * authentication credentials. When the SASL authentication completes
+ * successfully, the specified entity is granted access.
+ * @param protocol the non-null string name of the protocol for which the
+ * authentication is being performed (e.g. "ldap").
+ * @param serverName the non-null fully-qualified host name of the server to
+ * authenticate to.
+ * @param props the possibly null set of properties used to select the SASL
+ * mechanism and to configure the authentication exchange of the selected
+ * mechanism. For example, if props contains the {@link Sasl#POLICY_NOPLAINTEXT}
+ * property with the value <code>"true"</code>, then the selected SASL
+ * mechanism must not be susceptible to simple plain passive attacks. In
+ * addition to the standard properties declared in this class, other,
+ * possibly mechanism-specific, properties can be included. Properties not
+ * relevant to the selected mechanism are ignored.
+ * @param cbh the possibly <code>null</code> callback handler to used by the
+ * SASL mechanisms to get further information from the application/library to
+ * complete the authentication. For example, a SASL mechanism might require
+ * the authentication ID, password and realm from the caller. The
+ * authentication ID is requested by using a
+ * {@link javax.security.auth.callback.NameCallback}. The password is
+ * requested by using a {@link javax.security.auth.callback.PasswordCallback}.
+ * The realm is requested by using a {@link RealmChoiceCallback} if there is
+ * a list of realms to choose from, and by using a {@link RealmCallback} if
+ * the realm must be entered.
+ * @return a possibly <code>null</code> {@link SaslClient} created using the
+ * parameters supplied. If <code>null</code>, the method could not find a
+ * {@link SaslClientFactory} that will produce one.
+ * @throws SaslException if a {@link SaslClient} cannot be created because
+ * of an error.
+ */
+ public static SaslClient createSaslClient(String[] mechanisms,
+ String authorizationID,
+ String protocol,
+ String serverName, Map props,
+ CallbackHandler cbh)
+ throws SaslException
+ {
+ if (mechanisms == null)
+ {
+ return null;
+ }
+ Provider[] providers = Security.getProviders();
+ if (providers == null || providers.length == 0)
+ {
+ return null;
+ }
+
+ SaslClient result = null;
+ SaslClientFactory factory = null;
+ String m, clazz = null, upper, alias;
+ int j;
+ Provider p;
+ for (int i = 0; i < mechanisms.length; i++)
+ {
+ m = mechanisms[i];
+ if (m == null)
+ continue;
+ for (j = 0; j < providers.length; j++)
+ {
+ p = providers[j];
+ if (p != null)
+ {
+ // try the name as is
+ clazz = p.getProperty(CLIENT_FACTORY_SVC + m);
+ if (clazz == null) // try all uppercase
+ {
+ upper = m.toUpperCase();
+ clazz = p.getProperty(CLIENT_FACTORY_SVC + upper);
+ if (clazz == null) // try if it's an alias
+ {
+ alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + m);
+ if (alias == null) // try all-uppercase alias name
+ {
+ alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + upper);
+ if (alias == null) // spit the dummy
+ continue;
+ }
+ clazz = p.getProperty(CLIENT_FACTORY_SVC + alias);
+ }
+ }
+ if (clazz == null)
+ continue;
+ else
+ clazz = clazz.trim();
+ }
+
+ try
+ {
+ result = null;
+ factory = (SaslClientFactory) Class.forName(clazz).newInstance();
+ result = factory.createSaslClient(mechanisms, authorizationID,
+ protocol, serverName, props, cbh);
+ }
+ catch (ClassCastException ignored) // ignore instantiation exceptions
+ {
+ }
+ catch (ClassNotFoundException ignored)
+ {
+ }
+ catch (InstantiationException ignored)
+ {
+ }
+ catch (IllegalAccessException ignored)
+ {
+ }
+ if (result != null)
+ return result;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets an enumeration of known factories for producing a {@link SaslClient}
+ * instance. This method uses the same sources for locating factories as
+ * <code>createSaslClient()</code>.
+ *
+ * @return a non-null {@link Enumeration} of known factories for producing a
+ * {@link SaslClient} instance.
+ * @see #createSaslClient(String[],String,String,String,Map,CallbackHandler)
+ */
+ public static Enumeration getSaslClientFactories()
+ {
+ Vector result = new Vector();
+ HashSet names = new HashSet();
+ Provider[] providers = Security.getProviders();
+ Iterator it;
+ if (providers == null)
+ {
+ Provider p;
+ String key;
+ for (int i = 0; i < providers.length; i++)
+ {
+ p = providers[i];
+ for (it = p.keySet().iterator(); it.hasNext(); )
+ {
+ key = (String) it.next();
+ // add key's binding (a) it is a class of a client factory,
+ // and (b) the key does not include blanks
+ if (key.startsWith(CLIENT_FACTORY_SVC) && key.indexOf(" ") == -1)
+ {
+ names.add(p.getProperty(key));
+ break;
+ }
+ }
+ }
+ }
+ // we have the factory class names in names; instantiate and enumerate
+ String c;
+ for (it = names.iterator(); it.hasNext(); )
+ {
+ c = (String) it.next();
+ try
+ {
+ SaslClientFactory f = (SaslClientFactory) Class.forName(c).newInstance();
+ if (f != null)
+ result.add(f);
+ } catch (ClassCastException ignored) { // ignore instantiation exceptions
+ } catch (ClassNotFoundException ignored) {
+ } catch (InstantiationException ignored) {
+ } catch (IllegalAccessException ignored) {
+ }
+ }
+
+ return result.elements();
+ }
+
+ /**
+ * <p>Creates a {@link SaslServer} for the specified mechanism.</p>
+ *
+ * <p>This method uses the JCA Security Provider Framework, described in the
+ * "Java Cryptography Architecture API Specification &amp; Reference", for
+ * locating and selecting a SaslServer implementation.</p>
+ *
+ * <p>First, it obtains an ordered list of {@link SaslServerFactory}
+ * instances from the registered security providers for the
+ * <code>"SaslServerFactory"</code> service and the specified mechanism. It
+ * then invokes <code>createSaslServer()</code> on each factory instance on
+ * the list until one produces a non-null {@link SaslServer} instance. It
+ * returns the non-null {@link SaslServer} instance, or <code>null</code> if
+ * the search fails to produce a non-null {@link SaslServer} instance.</p>
+ *
+ * <p>A security provider for {@link SaslServerFactory} registers with the
+ * JCA Security Provider Framework keys of the form:</p>
+ *
+ * <pre>
+ * SaslServerFactory.mechanism_name
+ * </pre>
+ *
+ * <p>and values that are class names of implementations of {@link
+ * SaslServerFactory}.</p>
+ *
+ * <p>For example, a provider that contains a factory class,
+ * <code>com.wiz.sasl.digest.ServerFactory</code>, that supports the
+ * <code>"DIGEST-MD5"</code> mechanism would register the following entry
+ * with the JCA:</p>
+ *
+ * <pre>
+ * SaslServerFactory.DIGEST-MD5 com.wiz.sasl.digest.ServerFactory
+ * </pre></p>
+ *
+ * <p>See the "Java Cryptography Architecture API Specification &amp;
+ * Reference" for information about how to install and configure security
+ * service providers.</p>
+ *
+ * @param mechanism the non-null mechanism name. It must be an
+ * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
+ * @param protocol the non-null string name of the protocol for which the
+ * authentication is being performed (e.g. "ldap").
+ * @param serverName the non-null fully qualified host name of the server.
+ * @param props the possibly <code>null</code> set of properties used to
+ * select the SASL mechanism and to configure the authentication exchange of
+ * the selected mechanism. For example, if props contains the {@link
+ * Sasl#POLICY_NOPLAINTEXT} property with the value <code>"true"</code>, then
+ * the selected SASL mechanism must not be susceptible to simple plain
+ * passive attacks. In addition to the standard properties declared in this
+ * class, other, possibly mechanism-specific, properties can be included.
+ * Properties not relevant to the selected mechanism are ignored.
+ * @param cbh the possibly <code>null</code> callback handler to used by the
+ * SASL mechanisms to get further information from the application/library to
+ * complete the authentication. For example, a SASL mechanism might require
+ * the authentication ID, password and realm from the caller. The
+ * authentication ID is requested by using a
+ * {@link javax.security.auth.callback.NameCallback}. The password is
+ * requested by using a {@link javax.security.auth.callback.PasswordCallback}.
+ * The realm is requested by using a {@link RealmChoiceCallback} if there is
+ * a list of realms to choose from, and by using a {@link RealmCallback} if
+ * the realm must be entered.
+ * @return a possibly <code>null</code> {@link SaslServer} created using the
+ * parameters supplied. If <code>null</code>, the method cannot find a
+ * {@link SaslServerFactory} instance that will produce one.
+ * @throws SaslException if a {@link SaslServer} instance cannot be created
+ * because of an error.
+ */
+ public static SaslServer createSaslServer(String mechanism, String protocol,
+ String serverName,
+ Map props, CallbackHandler cbh)
+ throws SaslException
+ {
+ if (mechanism == null)
+ return null;
+ Provider[] providers = Security.getProviders();
+ if (providers == null || providers.length == 0)
+ return null;
+
+ SaslServer result = null;
+ SaslServerFactory factory = null;
+ String clazz = null, upper, alias = null;
+ int j;
+ Provider p;
+ for (j = 0; j < providers.length; j++)
+ {
+ p = providers[j];
+ if (p != null)
+ {
+ // try the name as is
+ clazz = p.getProperty(SERVER_FACTORY_SVC + mechanism);
+ if (clazz == null) // try all uppercase
+ {
+ upper = mechanism.toUpperCase();
+ clazz = p.getProperty(SERVER_FACTORY_SVC + upper);
+ if (clazz == null) // try if it's an alias
+ {
+ alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + mechanism);
+ if (alias == null) // try all-uppercase alias name
+ {
+ alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + upper);
+ if (alias == null) // spit the dummy
+ continue;
+ }
+ }
+ clazz = p.getProperty(SERVER_FACTORY_SVC + alias);
+ }
+ }
+ if (clazz == null)
+ continue;
+ else
+ clazz = clazz.trim();
+
+ try
+ {
+ result = null;
+ factory = (SaslServerFactory) Class.forName(clazz).newInstance();
+ result =
+ factory.createSaslServer(mechanism, protocol, serverName, props, cbh);
+ }
+ catch (ClassCastException ignored) // ignore instantiation exceptions
+ {
+ }
+ catch (ClassNotFoundException ignored)
+ {
+ }
+ catch (InstantiationException ignored)
+ {
+ }
+ catch (IllegalAccessException ignored)
+ {
+ }
+ if (result != null)
+ return result;
+ }
+ return null;
+ }
+
+ /**
+ * Gets an enumeration of known factories for producing a {@link SaslServer}
+ * instance. This method uses the same sources for locating factories as
+ * <code>createSaslServer()</code>.
+ *
+ * @return a non-null {@link Enumeration} of known factories for producing a
+ * {@link SaslServer} instance.
+ * @see #createSaslServer(String,String,String,Map,CallbackHandler)
+ */
+ public static Enumeration getSaslServerFactories()
+ {
+ Vector result = new Vector();
+ HashSet names = new HashSet();
+ Provider[] providers = Security.getProviders();
+ Iterator it;
+ if (providers == null)
+ {
+ Provider p;
+ String key;
+ for (int i = 0; i < providers.length; i++)
+ {
+ p = providers[i];
+ for (it = p.keySet().iterator(); it.hasNext(); )
+ {
+ key = (String) it.next();
+ // add key's binding (a) it is a class of a server factory,
+ // and (b) the key does not include blanks
+ if (key.startsWith(SERVER_FACTORY_SVC) && key.indexOf(" ") == -1)
+ {
+ names.add(p.getProperty(key));
+ break;
+ }
+ }
+ }
+ }
+ // we have the factory class names in names; instantiate and enumerate
+ String c;
+ for (it = names.iterator(); it.hasNext(); )
+ {
+ c = (String) it.next();
+ try
+ {
+ SaslServerFactory f = (SaslServerFactory) Class.forName(c).newInstance();
+ if (f != null)
+ result.add(f);
+ }
+ catch (ClassCastException ignored) // ignore instantiation exceptions
+ {
+ }
+ catch (ClassNotFoundException ignored)
+ {
+ }
+ catch (InstantiationException ignored)
+ {
+ }
+ catch (IllegalAccessException ignored)
+ {
+ }
+ }
+
+ return result.elements();
+ }
+}