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,
 360:                                             Map<String, ?> props,
 361:                                             CallbackHandler cbh)
 362:     throws SaslException
 363:   {
 364:     if (mechanisms == null)
 365:       {
 366:         return null;
 367:       }
 368:     Provider[] providers = Security.getProviders();
 369:     if (providers == null || providers.length == 0)
 370:       {
 371:         return null;
 372:       }
 373: 
 374:     SaslClient result = null;
 375:     SaslClientFactory factory = null;
 376:     String m, clazz = null, upper, alias;
 377:     int j;
 378:     Provider p;
 379:     for (int i = 0; i < mechanisms.length; i++)
 380:       {
 381:         m = mechanisms[i];
 382:         if (m == null)
 383:           continue;
 384:         for (j = 0; j < providers.length; j++)
 385:           {
 386:             p = providers[j];
 387:             if (p != null)
 388:               {
 389:                 // try the name as is
 390:                 clazz = p.getProperty(CLIENT_FACTORY_SVC + m);
 391:                 if (clazz == null) // try all uppercase
 392:                   {
 393:                     upper = m.toUpperCase();
 394:                     clazz = p.getProperty(CLIENT_FACTORY_SVC + upper);
 395:                     if (clazz == null) // try if it's an alias
 396:                       {
 397:                         alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + m);
 398:                         if (alias == null) // try all-uppercase alias name
 399:                           {
 400:                             alias = p.getProperty(ALIAS + CLIENT_FACTORY_SVC + upper);
 401:                             if (alias == null) // spit the dummy
 402:                               continue;
 403:                           }
 404:                         clazz = p.getProperty(CLIENT_FACTORY_SVC + alias);
 405:                       }
 406:                   }
 407:                 if (clazz == null)
 408:                   continue;
 409:                 else
 410:                   clazz = clazz.trim();
 411:               }
 412: 
 413:             try
 414:               {
 415:                 result = null;
 416:                 factory = (SaslClientFactory) Class.forName(clazz).newInstance();
 417:                 result = factory.createSaslClient(mechanisms, authorizationID,
 418:                                                   protocol, serverName, props, cbh);
 419:               }
 420:             catch (ClassCastException ignored) // ignore instantiation exceptions
 421:               {
 422:               }
 423:             catch (ClassNotFoundException ignored)
 424:               {
 425:               }
 426:             catch (InstantiationException ignored)
 427:               {
 428:               }
 429:             catch (IllegalAccessException ignored)
 430:               {
 431:               }
 432:             if (result != null)
 433:               return result;
 434:           }
 435:       }
 436:     return null;
 437:   }
 438: 
 439:   /**
 440:    * Gets an enumeration of known factories for producing a {@link SaslClient}
 441:    * instance. This method uses the same sources for locating factories as
 442:    * <code>createSaslClient()</code>.
 443:    *
 444:    * @return a non-null {@link Enumeration} of known factories for producing a
 445:    * {@link SaslClient} instance.
 446:    * @see #createSaslClient(String[],String,String,String,Map,CallbackHandler)
 447:    */
 448:   public static Enumeration<SaslClientFactory> getSaslClientFactories()
 449:   {
 450:     Vector result = new Vector();
 451:     HashSet names = new HashSet();
 452:     Provider[] providers = Security.getProviders();
 453:     Iterator it;
 454:     if (providers != null)
 455:       {
 456:         Provider p;
 457:         String key;
 458:         for (int i = 0; i < providers.length; i++)
 459:           {
 460:             p = providers[i];
 461:             for (it = p.keySet().iterator(); it.hasNext(); )
 462:               {
 463:                 key = (String) it.next();
 464:                 // add key's binding (a) it is a class of a client factory,
 465:                 // and (b) the key does not include blanks
 466:                 if (key.startsWith(CLIENT_FACTORY_SVC) && key.indexOf(" ") == -1)
 467:                   {
 468:                     names.add(p.getProperty(key));
 469:                     break;
 470:                   }
 471:               }
 472:           }
 473:       }
 474:     // we have the factory class names in names; instantiate and enumerate
 475:     String c;
 476:     for (it = names.iterator(); it.hasNext(); )
 477:       {
 478:         c = (String) it.next();
 479:         try
 480:           {
 481:             SaslClientFactory f = (SaslClientFactory) Class.forName(c).newInstance();
 482:             if (f != null)
 483:               result.add(f);
 484:           } catch (ClassCastException ignored) { // ignore instantiation exceptions
 485:           } catch (ClassNotFoundException ignored) {
 486:           } catch (InstantiationException ignored) {
 487:           } catch (IllegalAccessException ignored) {
 488:           }
 489:       }
 490: 
 491:     return result.elements();
 492:   }
 493: 
 494:   /**
 495:    * Creates a {@link SaslServer} for the specified mechanism.
 496:    *
 497:    * <p>This method uses the JCA Security Provider Framework, described in the
 498:    * "Java Cryptography Architecture API Specification &amp; Reference", for
 499:    * locating and selecting a SaslServer implementation.</p>
 500:    *
 501:    * <p>First, it obtains an ordered list of {@link SaslServerFactory}
 502:    * instances from the registered security providers for the
 503:    * <code>"SaslServerFactory"</code> service and the specified mechanism. It
 504:    * then invokes <code>createSaslServer()</code> on each factory instance on
 505:    * the list until one produces a non-null {@link SaslServer} instance. It
 506:    * returns the non-null {@link SaslServer} instance, or <code>null</code> if
 507:    * the search fails to produce a non-null {@link SaslServer} instance.</p>
 508:    *
 509:    * <p>A security provider for {@link SaslServerFactory} registers with the
 510:    * JCA Security Provider Framework keys of the form:</p>
 511:    *
 512:    * <pre>
 513:    *    SaslServerFactory.mechanism_name
 514:    * </pre>
 515:    *
 516:    * <p>and values that are class names of implementations of {@link
 517:    * SaslServerFactory}.</p>
 518:    *
 519:    * <p>For example, a provider that contains a factory class,
 520:    * <code>com.wiz.sasl.digest.ServerFactory</code>, that supports the
 521:    * <code>"DIGEST-MD5"</code> mechanism would register the following entry
 522:    * with the JCA:</p>
 523:    *
 524:    * <pre>
 525:    *    SaslServerFactory.DIGEST-MD5     com.wiz.sasl.digest.ServerFactory
 526:    * </pre>
 527:    *
 528:    * <p>See the "Java Cryptography Architecture API Specification &amp;
 529:    * Reference" for information about how to install and configure security
 530:    * service providers.</p>
 531:    *
 532:    * @param mechanism the non-null mechanism name. It must be an
 533:    * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
 534:    * @param protocol the non-null string name of the protocol for which the
 535:    * authentication is being performed (e.g. "ldap").
 536:    * @param serverName the non-null fully qualified host name of the server.
 537:    * @param props the possibly <code>null</code> set of properties used to
 538:    * select the SASL mechanism and to configure the authentication exchange of
 539:    * the selected mechanism. For example, if props contains the {@link
 540:    * Sasl#POLICY_NOPLAINTEXT} property with the value <code>"true"</code>, then
 541:    * the selected SASL mechanism must not be susceptible to simple plain
 542:    * passive attacks. In addition to the standard properties declared in this
 543:    * class, other, possibly mechanism-specific, properties can be included.
 544:    * Properties not relevant to the selected mechanism are ignored.
 545:    * @param cbh the possibly <code>null</code> callback handler to used by the
 546:    * SASL mechanisms to get further information from the application/library to
 547:    * complete the authentication. For example, a SASL mechanism might require
 548:    * the authentication ID, password and realm from the caller. The
 549:    * authentication ID is requested by using a
 550:    * {@link javax.security.auth.callback.NameCallback}. The password is
 551:    * requested by using a {@link javax.security.auth.callback.PasswordCallback}.
 552:    * The realm is requested by using a {@link RealmChoiceCallback} if there is
 553:    * a list of realms to choose from, and by using a {@link RealmCallback} if
 554:    * the realm must be entered.
 555:    * @return a possibly <code>null</code> {@link SaslServer} created using the
 556:    * parameters supplied. If <code>null</code>, the method cannot find a
 557:    * {@link SaslServerFactory} instance that will produce one.
 558:    * @throws SaslException if a {@link SaslServer} instance cannot be created
 559:    * because of an error.
 560:    */
 561:   public static SaslServer createSaslServer(String mechanism, String protocol,
 562:                                             String serverName,
 563:                                             Map<String, ?> props,
 564:                                             CallbackHandler cbh)
 565:     throws SaslException
 566:   {
 567:     if (mechanism == null)
 568:       return null;
 569:     Provider[] providers = Security.getProviders();
 570:     if (providers == null || providers.length == 0)
 571:       return null;
 572: 
 573:     SaslServer result = null;
 574:     SaslServerFactory factory = null;
 575:     String clazz = null, upper, alias = null;
 576:     int j;
 577:     Provider p;
 578:     for (j = 0; j < providers.length; j++)
 579:       {
 580:         p = providers[j];
 581:         if (p != null)
 582:           {
 583:             // try the name as is
 584:             clazz = p.getProperty(SERVER_FACTORY_SVC + mechanism);
 585:             if (clazz == null) // try all uppercase
 586:               {
 587:                 upper = mechanism.toUpperCase();
 588:                 clazz = p.getProperty(SERVER_FACTORY_SVC + upper);
 589:                 if (clazz == null) // try if it's an alias
 590:                   {
 591:                     alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + mechanism);
 592:                     if (alias == null) // try all-uppercase alias name
 593:                       {
 594:                         alias = p.getProperty(ALIAS + SERVER_FACTORY_SVC + upper);
 595:                         if (alias == null) // spit the dummy
 596:                           continue;
 597:                       }
 598:                   }
 599:                 clazz = p.getProperty(SERVER_FACTORY_SVC + alias);
 600:               }
 601:           }
 602:         if (clazz == null)
 603:           continue;
 604:         else
 605:           clazz = clazz.trim();
 606: 
 607:         try
 608:           {
 609:             result = null;
 610:             factory = (SaslServerFactory) Class.forName(clazz).newInstance();
 611:             result =
 612:               factory.createSaslServer(mechanism, protocol, serverName, props, cbh);
 613:           }
 614:         catch (ClassCastException ignored) // ignore instantiation exceptions
 615:           {
 616:           }
 617:         catch (ClassNotFoundException ignored)
 618:           {
 619:           }
 620:         catch (InstantiationException ignored)
 621:           {
 622:           }
 623:         catch (IllegalAccessException ignored)
 624:           {
 625:           }
 626:         if (result != null)
 627:           return result;
 628:       }
 629:     return null;
 630:   }
 631: 
 632:   /**
 633:    * Gets an enumeration of known factories for producing a {@link SaslServer}
 634:    * instance. This method uses the same sources for locating factories as
 635:    * <code>createSaslServer()</code>.
 636:    *
 637:    * @return a non-null {@link Enumeration} of known factories for producing a
 638:    * {@link SaslServer} instance.
 639:    * @see #createSaslServer(String,String,String,Map,CallbackHandler)
 640:    */
 641:   public static Enumeration<SaslServerFactory> getSaslServerFactories()
 642:   {
 643:     Vector result = new Vector();
 644:     HashSet names = new HashSet();
 645:     Provider[] providers = Security.getProviders();
 646:     Iterator it;
 647:     if (providers != null)
 648:       {
 649:         Provider p;
 650:         String key;
 651:         for (int i = 0; i < providers.length; i++)
 652:           {
 653:             p = providers[i];
 654:             for (it = p.keySet().iterator(); it.hasNext(); )
 655:               {
 656:                 key = (String) it.next();
 657:                 // add key's binding (a) it is a class of a server factory,
 658:                 // and (b) the key does not include blanks
 659:                 if (key.startsWith(SERVER_FACTORY_SVC) && key.indexOf(" ") == -1)
 660:                   {
 661:                     names.add(p.getProperty(key));
 662:                     break;
 663:                   }
 664:               }
 665:           }
 666:       }
 667:     // we have the factory class names in names; instantiate and enumerate
 668:     String c;
 669:     for (it = names.iterator(); it.hasNext(); )
 670:       {
 671:         c = (String) it.next();
 672:         try
 673:           {
 674:             SaslServerFactory f = (SaslServerFactory) Class.forName(c).newInstance();
 675:             if (f != null)
 676:               result.add(f);
 677:           }
 678:         catch (ClassCastException ignored) // ignore instantiation exceptions
 679:           {
 680:           }
 681:         catch (ClassNotFoundException ignored)
 682:           {
 683:           }
 684:         catch (InstantiationException ignored)
 685:           {
 686:           }
 687:         catch (IllegalAccessException ignored)
 688:           {
 689:           }
 690:       }
 691: 
 692:     return result.elements();
 693:   }
 694: }