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