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