Source for javax.security.sasl.Sasl

   1: /* Sasl.java -- 
   2:    Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.security.sasl;
  40: 
  41: import java.security.Provider;
  42: import java.security.Security;
  43: import java.util.Enumeration;
  44: import java.util.HashSet;
  45: import java.util.Iterator;
  46: import java.util.Map;
  47: import java.util.Vector;
  48: 
  49: import javax.security.auth.callback.CallbackHandler;
  50: 
  51: /**
  52:  * <p>A static class for creating SASL clients and servers.</p>
  53:  *
  54:  * <p>This class defines the policy of how to locate, load, and instantiate SASL
  55:  * clients and servers.</p>
  56:  *
  57:  * <p>For example, an application or library gets a SASL client instance by
  58:  * doing something like:</p>
  59:  *
  60:  * <pre>
  61:  *SaslClient sc =
  62:  *      Sasl.createSaslClient(mechanisms, authorizationID, protocol,
  63:  *                            serverName, props, callbackHandler);
  64:  * </pre>
  65:  *
  66:  * <p>It can then proceed to use the instance to create an authenticated
  67:  * connection.</p>
  68:  *
  69:  * <p>Similarly, a server gets a SASL server instance by using code that looks
  70:  * as follows:</p>
  71:  *
  72:  * <pre>
  73:  *SaslServer ss =
  74:  *      Sasl.createSaslServer(mechanism, protocol, serverName, props,
  75:  *                            callbackHandler);
  76:  * </pre>
  77:  *
  78:  * @since 1.5
  79:  */
  80: public class Sasl
  81: {
  82: 
  83:   // Constants and variables
  84:   // -------------------------------------------------------------------------
  85: 
  86:   /**
  87:    * <p>The name of a property that specifies the quality-of-protection to use.
  88:    * The property contains a comma-separated, ordered list of quality-of-
  89:    * protection values that the client or server is willing to support. A qop
  90:    * value is one of:</p>
  91:    *
  92:    * <ul>
  93:    *    <li><code>"auth"</code> - authentication only,</li>
  94:    *    <li><code>"auth-int"</code> - authentication plus integrity
  95:    *    protection,</li>
  96:    *    <li><code>"auth-conf"</code> - authentication plus integrity and
  97:    *    confidentiality protection.</li>
  98:    * </ul>
  99:    *
 100:    * <p>The order of the list specifies the preference order of the client or
 101:    * server.</p>
 102:    *
 103:    * <p>If this property is absent, the default qop is <code>"auth"</code>.</p>
 104:    *
 105:    * <p>The value of this constant is <code>"javax.security.sasl.qop"</code>.</p>
 106:    */
 107:   public static final String QOP = "javax.security.sasl.qop";
 108: 
 109:   /**
 110:    * <p>The name of a property that specifies the cipher strength to use. The
 111:    * property contains a comma-separated, ordered list of cipher strength
 112:    * values that the client or server is willing to support. A strength value
 113:    * is one of:</p>
 114:    *
 115:    * <ul>
 116:    *    <li><code>"low"</code>,</li>
 117:    *    <li><code>"medium"</code>,</li>
 118:    *    <li><code>"high"</code>.</li>
 119:    * </ul>
 120:    *
 121:    * <p>The order of the list specifies the preference order of the client or
 122:    * server. An implementation should allow configuration of the meaning of
 123:    * these values. An application may use the Java Cryptography Extension (JCE)
 124:    * with JCE-aware mechanisms to control the selection of cipher suites that
 125:    * match the strength values.</p>
 126:    *
 127:    * <p>If this property is absent, the default strength is
 128:    * <code>"high,medium,low"</code>.</p>
 129:    *
 130:    * <p>The value of this constant is <code>"javax.security.sasl.strength"</code>.
 131:    * </p>
 132:    */
 133:   public static final String STRENGTH = "javax.security.sasl.strength";
 134: 
 135:   /**
 136:    * <p>The name of a property that specifies whether the server must authenticate
 137:    * to the client. The property contains <code>"true"</code> if the server
 138:    * must authenticate the to client; <code>"false"</code> otherwise. The
 139:    * default is <code>"false"</code>.</p>
 140:    *
 141:    * <p>The value of this constant is
 142:    * <code>"javax.security.sasl.server.authentication"</code>.</p>
 143:    */
 144:   public static final String SERVER_AUTH = "javax.security.sasl.server.authentication";
 145: 
 146:   /**
 147:    * <p>The name of a property that specifies the maximum size of the receive
 148:    * buffer in bytes of {@link SaslClient}/{@link SaslServer}. The property
 149:    * contains the string representation of an integer.</p>
 150:    *
 151:    * <p>If this property is absent, the default size is defined by the
 152:    * mechanism.</p>
 153:    *
 154:    * <p>The value of this constant is <code>"javax.security.sasl.maxbuffer"</code>.
 155:    * </p>
 156:    */
 157:   public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer";
 158: 
 159:   /**
 160:    * <p>The name of a property that specifies the maximum size of the raw send
 161:    * buffer in bytes of {@link SaslClient}/{@link SaslServer}. The property
 162:    * contains the string representation of an integer. The value of this
 163:    * property is negotiated between the client and server during the
 164:    * authentication exchange.</p>
 165:    *
 166:    * <p>The value of this constant is <code>"javax.security.sasl.rawsendsize"</code>.
 167:    * </p>
 168:    */
 169:   public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize";
 170: 
 171:   /**
 172:    * <p>The name of a property that specifies whether mechanisms susceptible
 173:    * to simple plain passive attacks (e.g., "PLAIN") are not permitted. The
 174:    * property contains <code>"true"</code> if such mechanisms are not
 175:    * permitted; <code>"false"</code> if such mechanisms are permitted. The
 176:    * default is <code>"false"</code>.</p>
 177:    *
 178:    * <p>The value of this constant is <code>"javax.security.sasl.policy.noplaintext"</code>.
 179:    * </p>
 180:    */
 181:   public static final String POLICY_NOPLAINTEXT = "javax.security.sasl.policy.noplaintext";
 182: 
 183:   /**
 184:    * <p>The name of a property that specifies whether mechanisms susceptible to
 185:    * active (non-dictionary) attacks are not permitted. The property contains
 186:    * <code>"true"</code> if mechanisms susceptible to active attacks are not
 187:    * permitted; <code>"false"</code> if such mechanisms are permitted. The
 188:    * default is <code>"false"</code>.</p>
 189:    *
 190:    * <p>The value of this constant is <code>"javax.security.sasl.policy.noactive"</code>.
 191:    * </p>
 192:    */
 193:   public static final String POLICY_NOACTIVE = "javax.security.sasl.policy.noactive";
 194: 
 195:   /**
 196:    * <p>The name of a property that specifies whether mechanisms susceptible to
 197:    * passive dictionary attacks are not permitted. The property contains
 198:    * <code>"true"</code> if mechanisms susceptible to dictionary attacks are
 199:    * not permitted; <code>"false"</code> if such mechanisms are permitted. The
 200:    * default is <code>"false"</code>.</p>
 201:    *
 202:    * <p>The value of this constant is <code>"javax.security.sasl.policy.nodictionary"</code>.
 203:    * </p>
 204:    */
 205:   public static final String POLICY_NODICTIONARY = "javax.security.sasl.policy.nodictionary";
 206: 
 207:   /**
 208:    * <p>The name of a property that specifies whether mechanisms that accept
 209:    * anonymous login are not permitted. The property contains <code>"true"</code>
 210:    * if mechanisms that accept anonymous login are not permitted; <code>"false"
 211:    * </code> if such mechanisms are permitted. The default is <code>"false"</code>.
 212:    * </p>
 213:    *
 214:    * <p>The value of this constant is <code>"javax.security.sasl.policy.noanonymous"</code>.
 215:    * </p>
 216:    */
 217:   public static final String POLICY_NOANONYMOUS = "javax.security.sasl.policy.noanonymous";
 218: 
 219:   /**
 220:    * The name of a property that specifies whether mechanisms that implement
 221:    * forward secrecy between sessions are required. Forward secrecy means that
 222:    * breaking into one session will not automatically provide information for
 223:    * breaking into future sessions. The property contains <code>"true"</code>
 224:    * if mechanisms that implement forward secrecy between sessions are
 225:    * required; <code>"false"</code> if such mechanisms are not required. The
 226:    * default is <code>"false"</code>.
 227:    *
 228:    * <p>The value of this constant is <code>"javax.security.sasl.policy.forward"</code>.
 229:    * </p>
 230:    */
 231:   public static final String POLICY_FORWARD_SECRECY = "javax.security.sasl.policy.forward";
 232: 
 233:   /**
 234:    * The name of a property that specifies whether mechanisms that pass client
 235:    * credentials are required. The property contains <code>"true"</code> if
 236:    * mechanisms that pass client credentials are required; <code>"false"</code>
 237:    * if such mechanisms are not required. The default is <code>"false"</code>.
 238:    *
 239:    * <p>The value of this constant is <code>"javax.security.sasl.policy.credentials"</code>.
 240:    * </p>
 241:    */
 242:   public static final String POLICY_PASS_CREDENTIALS = "javax.security.sasl.policy.credentials";
 243: 
 244:   /**
 245:    * <p>The name of a property that specifies whether to reuse previously
 246:    * authenticated session information. The property contains <code>"true"</code>
 247:    * if the mechanism implementation may attempt to reuse previously
 248:    * authenticated session information; it contains <code>"false"</code> if the
 249:    * implementation must not reuse previously authenticated session information.
 250:    * A setting of <code>"true"</code> serves only as a hint; it does not
 251:    * necessarily entail actual reuse because reuse might not be possible due to
 252:    * a number of reasons, including, but not limited to, lack of mechanism
 253:    * support for reuse, expiration of reusable information, and the peer's
 254:    * refusal to support reuse. The property's default value is <code>"false"</code>.
 255:    * </p>
 256:    *
 257:    * <p>The value of this constant is <code>"javax.security.sasl.reuse"</code>.
 258:    * Note that all other parameters and properties required to create a SASL
 259:    * client/server instance must be provided regardless of whether this
 260:    * property has been supplied. That is, you cannot supply any less
 261:    * information in anticipation of reuse. Mechanism implementations that
 262:    * support reuse might allow customization of its implementation for factors
 263:    * such as cache size, timeouts, and criteria for reuseability. Such
 264:    * customizations are implementation-dependent.</p>
 265:    */
 266:   public static final String REUSE = "javax.security.sasl.reuse";
 267: 
 268:   private static final String CLIENT_FACTORY_SVC = "SaslClientFactory.";
 269:   private static final String SERVER_FACTORY_SVC = "SaslServerFactory.";
 270:   private static final String ALIAS = "Alg.Alias.";
 271: 
 272:   // Constructor(s)
 273:   // -------------------------------------------------------------------------
 274: 
 275:   private Sasl()
 276:   {
 277:     super();
 278:   }
 279: 
 280:   // Class methods
 281:   // -------------------------------------------------------------------------
 282: 
 283:   /**
 284:    * Creates a {@link SaslClient} for the specified mechanism.
 285:    *
 286:    * <p>This method uses the JCA Security Provider Framework, described in the
 287:    * "Java Cryptography Architecture API Specification &amp; Reference", for
 288:    * locating and selecting a {@link SaslClient} implementation.</p>
 289:    *
 290:    * <p>First, it obtains an ordered list of {@link SaslClientFactory}
 291:    * instances from the registered security providers for the
 292:    * <code>"SaslClientFactory"</code> service and the specified mechanism. It
 293:    * then invokes <code>createSaslClient()</code> on each factory instance on
 294:    * the list until one produces a non-null {@link SaslClient} instance. It
 295:    * returns the non-null {@link SaslClient} instance, or <code>null</code> if
 296:    * the search fails to produce a non-null {@link SaslClient} instance.</p>
 297:    *
 298:    * <p>A security provider for <code>SaslClientFactory</code> registers with
 299:    * the JCA Security Provider Framework keys of the form:</p>
 300:    *
 301:    * <pre>
 302:    *    SaslClientFactory.mechanism_name
 303:    * </pre>
 304:    *
 305:    * <p>and values that are class names of implementations of {@link
 306:    * SaslClientFactory}.</p>
 307:    *
 308:    * <p>For example, a provider that contains a factory class,
 309:    * <code>com.wiz.sasl.digest.ClientFactory</code>, that supports the
 310:    * <code>"DIGEST-MD5"</code> mechanism would register the following entry
 311:    * with the JCA:</p>
 312:    *
 313:    * <pre>
 314:    *    SaslClientFactory.DIGEST-MD5     com.wiz.sasl.digest.ClientFactory
 315:    * </pre>
 316:    *
 317:    * <p>See the "Java Cryptography Architecture API Specification &amp;
 318:    * Reference" for information about how to install and configure security
 319:    * service providers.</p>
 320:    *
 321:    * @param mechanisms the non-null list of mechanism names to try. Each is the
 322:    * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
 323:    * @param authorizationID the possibly <code>null</code> protocol-dependent
 324:    * identification to be used for authorization. If <code>null</code> or
 325:    * empty, the server derives an authorization ID from the client's
 326:    * authentication credentials. When the SASL authentication completes
 327:    * successfully, the specified entity is granted access.
 328:    * @param protocol the non-null string name of the protocol for which the
 329:    * authentication is being performed (e.g. "ldap").
 330:    * @param serverName the non-null fully-qualified host name of the server to
 331:    * authenticate to.
 332:    * @param props the possibly null set of properties used to select the SASL
 333:    * mechanism and to configure the authentication exchange of the selected
 334:    * mechanism. For example, if props contains the {@link Sasl#POLICY_NOPLAINTEXT}
 335:    * property with the value <code>"true"</code>, then the selected SASL
 336:    * mechanism must not be susceptible to simple plain passive attacks. In
 337:    * addition to the standard properties declared in this class, other,
 338:    * possibly mechanism-specific, properties can be included. Properties not
 339:    * relevant to the selected mechanism are ignored.
 340:    * @param cbh the possibly <code>null</code> callback handler to used by the
 341:    * SASL mechanisms to get further information from the application/library to
 342:    * complete the authentication. For example, a SASL mechanism might require
 343:    * the authentication ID, password and realm from the caller. The
 344:    * authentication ID is requested by using a
 345:    * {@link javax.security.auth.callback.NameCallback}. The password is
 346:    * requested by using a {@link javax.security.auth.callback.PasswordCallback}.
 347:    * The realm is requested by using a {@link RealmChoiceCallback} if there is
 348:    * a list of realms to choose from, and by using a {@link RealmCallback} if
 349:    * the realm must be entered.
 350:    * @return a possibly <code>null</code> {@link SaslClient} created using the
 351:    * parameters supplied. If <code>null</code>, the method could not find a
 352:    * {@link SaslClientFactory} that will produce one.
 353:    * @throws SaslException if a {@link SaslClient} cannot be created because
 354:    * of an error.
 355:    */
 356:   public static SaslClient createSaslClient(String[] mechanisms,
 357:                                             String authorizationID,
 358:                                             String protocol,
 359:                                             String serverName, Map props,
 360:                                             CallbackHandler cbh)
 361:     throws SaslException
 362:   {
 363:     if (mechanisms == null)
 364:       {
 365:         return null;
 366:       }
 367:     Provider[] providers = Security.getProviders();
 368:     if (providers == null || providers.length == 0)
 369:       {
 370:         return null;
 371:       }
 372: 
 373:     SaslClient result = null;
 374:     SaslClientFactory factory = null;
 375:     String m, clazz = null, upper, alias;
 376:     int j;
 377:     Provider p;
 378:     for (int i = 0; i < mechanisms.length; i++)
 379:       {
 380:         m = mechanisms[i];
 381:         if (m == null)
 382:           continue;
 383:         for (j = 0; j < providers.length; j++)
 384:           {
 385:             p = providers[j];
 386:             if (p != null)
 387:               {
 388:                 // try the name as is
 389:                 clazz = p.getProperty(CLIENT_FACTORY_SVC + m);
 390:                 if (clazz == null) // try all uppercase
 391:                   {
 392:                     upper = m.toUpperCase();
 393:                     clazz = p.getProperty(CLIENT_FACTORY_SVC + upper);
 394:                     if (clazz == null) // try if it's an alias
 395:                       {
 396:                         alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + m);
 397:                         if (alias == null) // try all-uppercase alias name
 398:                           {
 399:                             alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + upper);
 400:                             if (alias == null) // spit the dummy
 401:                               continue;
 402:                           }
 403:                         clazz = p.getProperty(CLIENT_FACTORY_SVC + alias);
 404:                       }
 405:                   }
 406:                 if (clazz == null)
 407:                   continue;
 408:                 else
 409:                   clazz = clazz.trim();
 410:               }
 411: 
 412:             try
 413:               {
 414:                 result = null;
 415:                 factory = (SaslClientFactory) Class.forName(clazz).newInstance();
 416:                 result = factory.createSaslClient(mechanisms, authorizationID,
 417:                                                   protocol, serverName, props, cbh);
 418:               }
 419:             catch (ClassCastException ignored) // ignore instantiation exceptions
 420:               {
 421:               }
 422:             catch (ClassNotFoundException ignored)
 423:               {
 424:               }
 425:             catch (InstantiationException ignored)
 426:               {
 427:               }
 428:             catch (IllegalAccessException ignored)
 429:               {
 430:               }
 431:             if (result != null)
 432:               return result;
 433:           }
 434:       }
 435:     return null;
 436:   }
 437: 
 438:   /**
 439:    * Gets an enumeration of known factories for producing a {@link SaslClient}
 440:    * instance. This method uses the same sources for locating factories as
 441:    * <code>createSaslClient()</code>.
 442:    *
 443:    * @return a non-null {@link Enumeration} of known factories for producing a
 444:    * {@link SaslClient} instance.
 445:    * @see #createSaslClient(String[],String,String,String,Map,CallbackHandler)
 446:    */
 447:   public static Enumeration getSaslClientFactories()
 448:   {
 449:     Vector result = new Vector();
 450:     HashSet names = new HashSet();
 451:     Provider[] providers = Security.getProviders();
 452:     Iterator it;
 453:     if (providers != null)
 454:       {
 455:         Provider p;
 456:         String key;
 457:         for (int i = 0; i < providers.length; i++)
 458:           {
 459:             p = providers[i];
 460:             for (it = p.keySet().iterator(); it.hasNext(); )
 461:               {
 462:                 key = (String) it.next();
 463:                 // add key's binding (a) it is a class of a client factory,
 464:                 // and (b) the key does not include blanks
 465:                 if (key.startsWith(CLIENT_FACTORY_SVC) && key.indexOf(" ") == -1)
 466:                   {
 467:                     names.add(p.getProperty(key));
 468:                     break;
 469:                   }
 470:               }
 471:           }
 472:       }
 473:     // we have the factory class names in names; instantiate and enumerate
 474:     String c;
 475:     for (it = names.iterator(); it.hasNext(); )
 476:       {
 477:         c = (String) it.next();
 478:         try
 479:           {
 480:             SaslClientFactory f = (SaslClientFactory) Class.forName(c).newInstance();
 481:             if (f != null)
 482:               result.add(f);
 483:           } catch (ClassCastException ignored) { // ignore instantiation exceptions
 484:           } catch (ClassNotFoundException ignored) {
 485:           } catch (InstantiationException ignored) {
 486:           } catch (IllegalAccessException ignored) {
 487:           }
 488:       }
 489: 
 490:     return result.elements();
 491:   }
 492: 
 493:   /**
 494:    * Creates a {@link SaslServer} for the specified mechanism.
 495:    *
 496:    * <p>This method uses the JCA Security Provider Framework, described in the
 497:    * "Java Cryptography Architecture API Specification &amp; Reference", for
 498:    * locating and selecting a SaslServer implementation.</p>
 499:    *
 500:    * <p>First, it obtains an ordered list of {@link SaslServerFactory}
 501:    * instances from the registered security providers for the
 502:    * <code>"SaslServerFactory"</code> service and the specified mechanism. It
 503:    * then invokes <code>createSaslServer()</code> on each factory instance on
 504:    * the list until one produces a non-null {@link SaslServer} instance. It
 505:    * returns the non-null {@link SaslServer} instance, or <code>null</code> if
 506:    * the search fails to produce a non-null {@link SaslServer} instance.</p>
 507:    *
 508:    * <p>A security provider for {@link SaslServerFactory} registers with the
 509:    * JCA Security Provider Framework keys of the form:</p>
 510:    *
 511:    * <pre>
 512:    *    SaslServerFactory.mechanism_name
 513:    * </pre>
 514:    *
 515:    * <p>and values that are class names of implementations of {@link
 516:    * SaslServerFactory}.</p>
 517:    *
 518:    * <p>For example, a provider that contains a factory class,
 519:    * <code>com.wiz.sasl.digest.ServerFactory</code>, that supports the
 520:    * <code>"DIGEST-MD5"</code> mechanism would register the following entry
 521:    * with the JCA:</p>
 522:    *
 523:    * <pre>
 524:    *    SaslServerFactory.DIGEST-MD5     com.wiz.sasl.digest.ServerFactory
 525:    * </pre>
 526:    *
 527:    * <p>See the "Java Cryptography Architecture API Specification &amp;
 528:    * Reference" for information about how to install and configure security
 529:    * service providers.</p>
 530:    *
 531:    * @param mechanism the non-null mechanism name. It must be an
 532:    * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
 533:    * @param protocol the non-null string name of the protocol for which the
 534:    * authentication is being performed (e.g. "ldap").
 535:    * @param serverName the non-null fully qualified host name of the server.
 536:    * @param props the possibly <code>null</code> set of properties used to
 537:    * select the SASL mechanism and to configure the authentication exchange of
 538:    * the selected mechanism. For example, if props contains the {@link
 539:    * Sasl#POLICY_NOPLAINTEXT} property with the value <code>"true"</code>, then
 540:    * the selected SASL mechanism must not be susceptible to simple plain
 541:    * passive attacks. In addition to the standard properties declared in this
 542:    * class, other, possibly mechanism-specific, properties can be included.
 543:    * Properties not relevant to the selected mechanism are ignored.
 544:    * @param cbh the possibly <code>null</code> callback handler to used by the
 545:    * SASL mechanisms to get further information from the application/library to
 546:    * complete the authentication. For example, a SASL mechanism might require
 547:    * the authentication ID, password and realm from the caller. The
 548:    * authentication ID is requested by using a
 549:    * {@link javax.security.auth.callback.NameCallback}. The password is
 550:    * requested by using a {@link javax.security.auth.callback.PasswordCallback}.
 551:    * The realm is requested by using a {@link RealmChoiceCallback} if there is
 552:    * a list of realms to choose from, and by using a {@link RealmCallback} if
 553:    * the realm must be entered.
 554:    * @return a possibly <code>null</code> {@link SaslServer} created using the
 555:    * parameters supplied. If <code>null</code>, the method cannot find a
 556:    * {@link SaslServerFactory} instance that will produce one.
 557:    * @throws SaslException if a {@link SaslServer} instance cannot be created
 558:    * because of an error.
 559:    */
 560:   public static SaslServer createSaslServer(String mechanism, String protocol,
 561:                                             String serverName,
 562:                                             Map props, CallbackHandler cbh)
 563:     throws SaslException
 564:   {
 565:     if (mechanism == null)
 566:       return null;
 567:     Provider[] providers = Security.getProviders();
 568:     if (providers == null || providers.length == 0)
 569:       return null;
 570: 
 571:     SaslServer result = null;
 572:     SaslServerFactory factory = null;
 573:     String clazz = null, upper, alias = null;
 574:     int j;
 575:     Provider p;
 576:     for (j = 0; j < providers.length; j++)
 577:       {
 578:         p = providers[j];
 579:         if (p != null)
 580:           {
 581:             // try the name as is
 582:             clazz = p.getProperty(SERVER_FACTORY_SVC + mechanism);
 583:             if (clazz == null) // try all uppercase
 584:               {
 585:                 upper = mechanism.toUpperCase();
 586:                 clazz = p.getProperty(SERVER_FACTORY_SVC + upper);
 587:                 if (clazz == null) // try if it's an alias
 588:                   {
 589:                     alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + mechanism);
 590:                     if (alias == null) // try all-uppercase alias name
 591:                       {
 592:                         alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + upper);
 593:                         if (alias == null) // spit the dummy
 594:                           continue;
 595:                       }
 596:                   }
 597:                 clazz = p.getProperty(SERVER_FACTORY_SVC + alias);
 598:               }
 599:           }
 600:         if (clazz == null)
 601:           continue;
 602:         else
 603:           clazz = clazz.trim();
 604: 
 605:         try
 606:           {
 607:             result = null;
 608:             factory = (SaslServerFactory) Class.forName(clazz).newInstance();
 609:             result =
 610:               factory.createSaslServer(mechanism, protocol, serverName, props, cbh);
 611:           }
 612:         catch (ClassCastException ignored) // ignore instantiation exceptions
 613:           {
 614:           }
 615:         catch (ClassNotFoundException ignored)
 616:           {
 617:           }
 618:         catch (InstantiationException ignored)
 619:           {
 620:           }
 621:         catch (IllegalAccessException ignored)
 622:           {
 623:           }
 624:         if (result != null)
 625:           return result;
 626:       }
 627:     return null;
 628:   }
 629: 
 630:   /**
 631:    * Gets an enumeration of known factories for producing a {@link SaslServer}
 632:    * instance. This method uses the same sources for locating factories as
 633:    * <code>createSaslServer()</code>.
 634:    *
 635:    * @return a non-null {@link Enumeration} of known factories for producing a
 636:    * {@link SaslServer} instance.
 637:    * @see #createSaslServer(String,String,String,Map,CallbackHandler)
 638:    */
 639:   public static Enumeration getSaslServerFactories()
 640:   {
 641:     Vector result = new Vector();
 642:     HashSet names = new HashSet();
 643:     Provider[] providers = Security.getProviders();
 644:     Iterator it;
 645:     if (providers != null)
 646:       {
 647:         Provider p;
 648:         String key;
 649:         for (int i = 0; i < providers.length; i++)
 650:           {
 651:             p = providers[i];
 652:             for (it = p.keySet().iterator(); it.hasNext(); )
 653:               {
 654:                 key = (String) it.next();
 655:                 // add key's binding (a) it is a class of a server factory,
 656:                 // and (b) the key does not include blanks
 657:                 if (key.startsWith(SERVER_FACTORY_SVC) && key.indexOf(" ") == -1)
 658:                   {
 659:                     names.add(p.getProperty(key));
 660:                     break;
 661:                   }
 662:               }
 663:           }
 664:       }
 665:     // we have the factory class names in names; instantiate and enumerate
 666:     String c;
 667:     for (it = names.iterator(); it.hasNext(); )
 668:       {
 669:         c = (String) it.next();
 670:         try
 671:           {
 672:             SaslServerFactory f = (SaslServerFactory) Class.forName(c).newInstance();
 673:             if (f != null)
 674:               result.add(f);
 675:           }
 676:         catch (ClassCastException ignored) // ignore instantiation exceptions
 677:           {
 678:           }
 679:         catch (ClassNotFoundException ignored)
 680:           {
 681:           }
 682:         catch (InstantiationException ignored)
 683:           {
 684:           }
 685:         catch (IllegalAccessException ignored)
 686:           {
 687:           }
 688:       }
 689: 
 690:     return result.elements();
 691:   }
 692: }