J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package javax.security.sasl; |
| 27 | |
| 28 | import javax.security.auth.callback.CallbackHandler; |
| 29 | |
| 30 | import java.util.Enumeration; |
| 31 | import java.util.Iterator; |
| 32 | import java.util.Map; |
| 33 | import java.util.Set; |
| 34 | import java.util.HashSet; |
| 35 | import java.util.Collections; |
| 36 | import java.security.Provider; |
| 37 | import java.security.Security; |
| 38 | |
| 39 | /** |
| 40 | * A static class for creating SASL clients and servers. |
| 41 | *<p> |
| 42 | * This class defines the policy of how to locate, load, and instantiate |
| 43 | * SASL clients and servers. |
| 44 | *<p> |
| 45 | * For example, an application or library gets a SASL client by doing |
| 46 | * something like: |
| 47 | *<blockquote><pre> |
| 48 | * SaslClient sc = Sasl.createSaslClient(mechanisms, |
| 49 | * authorizationId, protocol, serverName, props, callbackHandler); |
| 50 | *</pre></blockquote> |
| 51 | * It can then proceed to use the instance to create an authentication connection. |
| 52 | *<p> |
| 53 | * Similarly, a server gets a SASL server by using code that looks as follows: |
| 54 | *<blockquote><pre> |
| 55 | * SaslServer ss = Sasl.createSaslServer(mechanism, |
| 56 | * protocol, serverName, props, callbackHandler); |
| 57 | *</pre></blockquote> |
| 58 | * |
| 59 | * @since 1.5 |
| 60 | * |
| 61 | * @author Rosanna Lee |
| 62 | * @author Rob Weltman |
| 63 | */ |
| 64 | public class Sasl { |
| 65 | // Cannot create one of these |
| 66 | private Sasl() { |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | * The name of a property that specifies the quality-of-protection to use. |
| 71 | * The property contains a comma-separated, ordered list |
| 72 | * of quality-of-protection values that the |
| 73 | * client or server is willing to support. A qop value is one of |
| 74 | * <ul> |
| 75 | * <li><tt>"auth"</tt> - authentication only</li> |
| 76 | * <li><tt>"auth-int"</tt> - authentication plus integrity protection</li> |
| 77 | * <li><tt>"auth-conf"</tt> - authentication plus integrity and confidentiality |
| 78 | * protection</li> |
| 79 | * </ul> |
| 80 | * |
| 81 | * The order of the list specifies the preference order of the client or |
| 82 | * server. If this property is absent, the default qop is <tt>"auth"</tt>. |
| 83 | * The value of this constant is <tt>"javax.security.sasl.qop"</tt>. |
| 84 | */ |
| 85 | public static final String QOP = "javax.security.sasl.qop"; |
| 86 | |
| 87 | /** |
| 88 | * The name of a property that specifies the cipher strength to use. |
| 89 | * The property contains a comma-separated, ordered list |
| 90 | * of cipher strength values that |
| 91 | * the client or server is willing to support. A strength value is one of |
| 92 | * <ul> |
| 93 | * <li><tt>"low"</tt></li> |
| 94 | * <li><tt>"medium"</tt></li> |
| 95 | * <li><tt>"high"</tt></li> |
| 96 | * </ul> |
| 97 | * The order of the list specifies the preference order of the client or |
| 98 | * server. An implementation should allow configuration of the meaning |
| 99 | * of these values. An application may use the Java Cryptography |
| 100 | * Extension (JCE) with JCE-aware mechanisms to control the selection of |
| 101 | * cipher suites that match the strength values. |
| 102 | * <BR> |
| 103 | * If this property is absent, the default strength is |
| 104 | * <tt>"high,medium,low"</tt>. |
| 105 | * The value of this constant is <tt>"javax.security.sasl.strength"</tt>. |
| 106 | */ |
| 107 | public static final String STRENGTH = "javax.security.sasl.strength"; |
| 108 | |
| 109 | /** |
| 110 | * The name of a property that specifies whether the |
| 111 | * server must authenticate to the client. The property contains |
| 112 | * <tt>"true"</tt> if the server must |
| 113 | * authenticate the to client; <tt>"false"</tt> otherwise. |
| 114 | * The default is <tt>"false"</tt>. |
| 115 | * <br>The value of this constant is |
| 116 | * <tt>"javax.security.sasl.server.authentication"</tt>. |
| 117 | */ |
| 118 | public static final String SERVER_AUTH = |
| 119 | "javax.security.sasl.server.authentication"; |
| 120 | |
| 121 | /** |
| 122 | * The name of a property that specifies the maximum size of the receive |
| 123 | * buffer in bytes of <tt>SaslClient</tt>/<tt>SaslServer</tt>. |
| 124 | * The property contains the string representation of an integer. |
| 125 | * <br>If this property is absent, the default size |
| 126 | * is defined by the mechanism. |
| 127 | * <br>The value of this constant is <tt>"javax.security.sasl.maxbuffer"</tt>. |
| 128 | */ |
| 129 | public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer"; |
| 130 | |
| 131 | /** |
| 132 | * The name of a property that specifies the maximum size of the raw send |
| 133 | * buffer in bytes of <tt>SaslClient</tt>/<tt>SaslServer</tt>. |
| 134 | * The property contains the string representation of an integer. |
| 135 | * The value of this property is negotiated between the client and server |
| 136 | * during the authentication exchange. |
| 137 | * <br>The value of this constant is <tt>"javax.security.sasl.rawsendsize"</tt>. |
| 138 | */ |
| 139 | public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize"; |
| 140 | |
| 141 | /** |
| 142 | * The name of a property that specifies whether to reuse previously |
| 143 | * authenticated session information. The property contains "true" if the |
| 144 | * mechanism implementation may attempt to reuse previously authenticated |
| 145 | * session information; it contains "false" if the implementation must |
| 146 | * not reuse previously authenticated session information. A setting of |
| 147 | * "true" serves only as a hint: it does not necessarily entail actual |
| 148 | * reuse because reuse might not be possible due to a number of reasons, |
| 149 | * including, but not limited to, lack of mechanism support for reuse, |
| 150 | * expiration of reusable information, and the peer's refusal to support |
| 151 | * reuse. |
| 152 | * |
| 153 | * The property's default value is "false". The value of this constant |
| 154 | * is "javax.security.sasl.reuse". |
| 155 | * |
| 156 | * Note that all other parameters and properties required to create a |
| 157 | * SASL client/server instance must be provided regardless of whether |
| 158 | * this property has been supplied. That is, you cannot supply any less |
| 159 | * information in anticipation of reuse. |
| 160 | * |
| 161 | * Mechanism implementations that support reuse might allow customization |
| 162 | * of its implementation, for factors such as cache size, timeouts, and |
| 163 | * criteria for reuseability. Such customizations are |
| 164 | * implementation-dependent. |
| 165 | */ |
| 166 | public static final String REUSE = "javax.security.sasl.reuse"; |
| 167 | |
| 168 | /** |
| 169 | * The name of a property that specifies |
| 170 | * whether mechanisms susceptible to simple plain passive attacks (e.g., |
| 171 | * "PLAIN") are not permitted. The property |
| 172 | * contains <tt>"true"</tt> if such mechanisms are not permitted; |
| 173 | * <tt>"false"</tt> if such mechanisms are permitted. |
| 174 | * The default is <tt>"false"</tt>. |
| 175 | * <br>The value of this constant is |
| 176 | * <tt>"javax.security.sasl.policy.noplaintext"</tt>. |
| 177 | */ |
| 178 | public static final String POLICY_NOPLAINTEXT = |
| 179 | "javax.security.sasl.policy.noplaintext"; |
| 180 | |
| 181 | /** |
| 182 | * The name of a property that specifies whether |
| 183 | * mechanisms susceptible to active (non-dictionary) attacks |
| 184 | * are not permitted. |
| 185 | * The property contains <tt>"true"</tt> |
| 186 | * if mechanisms susceptible to active attacks |
| 187 | * are not permitted; <tt>"false"</tt> if such mechanisms are permitted. |
| 188 | * The default is <tt>"false"</tt>. |
| 189 | * <br>The value of this constant is |
| 190 | * <tt>"javax.security.sasl.policy.noactive"</tt>. |
| 191 | */ |
| 192 | public static final String POLICY_NOACTIVE = |
| 193 | "javax.security.sasl.policy.noactive"; |
| 194 | |
| 195 | /** |
| 196 | * The name of a property that specifies whether |
| 197 | * mechanisms susceptible to passive dictionary attacks are not permitted. |
| 198 | * The property contains <tt>"true"</tt> |
| 199 | * if mechanisms susceptible to dictionary attacks are not permitted; |
| 200 | * <tt>"false"</tt> if such mechanisms are permitted. |
| 201 | * The default is <tt>"false"</tt>. |
| 202 | *<br> |
| 203 | * The value of this constant is |
| 204 | * <tt>"javax.security.sasl.policy.nodictionary"</tt>. |
| 205 | */ |
| 206 | public static final String POLICY_NODICTIONARY = |
| 207 | "javax.security.sasl.policy.nodictionary"; |
| 208 | |
| 209 | /** |
| 210 | * The name of a property that specifies whether mechanisms that accept |
| 211 | * anonymous login are not permitted. The property contains <tt>"true"</tt> |
| 212 | * if mechanisms that accept anonymous login are not permitted; |
| 213 | * <tt>"false"</tt> |
| 214 | * if such mechanisms are permitted. The default is <tt>"false"</tt>. |
| 215 | *<br> |
| 216 | * The value of this constant is |
| 217 | * <tt>"javax.security.sasl.policy.noanonymous"</tt>. |
| 218 | */ |
| 219 | public static final String POLICY_NOANONYMOUS = |
| 220 | "javax.security.sasl.policy.noanonymous"; |
| 221 | |
| 222 | /** |
| 223 | * The name of a property that specifies whether mechanisms that implement |
| 224 | * forward secrecy between sessions are required. Forward secrecy |
| 225 | * means that breaking into one session will not automatically |
| 226 | * provide information for breaking into future sessions. |
| 227 | * The property |
| 228 | * contains <tt>"true"</tt> if mechanisms that implement forward secrecy |
| 229 | * between sessions are required; <tt>"false"</tt> if such mechanisms |
| 230 | * are not required. The default is <tt>"false"</tt>. |
| 231 | *<br> |
| 232 | * The value of this constant is |
| 233 | * <tt>"javax.security.sasl.policy.forward"</tt>. |
| 234 | */ |
| 235 | public static final String POLICY_FORWARD_SECRECY = |
| 236 | "javax.security.sasl.policy.forward"; |
| 237 | |
| 238 | /** |
| 239 | * The name of a property that specifies whether |
| 240 | * mechanisms that pass client credentials are required. The property |
| 241 | * contains <tt>"true"</tt> if mechanisms that pass |
| 242 | * client credentials are required; <tt>"false"</tt> |
| 243 | * if such mechanisms are not required. The default is <tt>"false"</tt>. |
| 244 | *<br> |
| 245 | * The value of this constant is |
| 246 | * <tt>"javax.security.sasl.policy.credentials"</tt>. |
| 247 | */ |
| 248 | public static final String POLICY_PASS_CREDENTIALS = |
| 249 | "javax.security.sasl.policy.credentials"; |
| 250 | |
| 251 | /** |
| 252 | * The name of a property that specifies the credentials to use. |
| 253 | * The property contains a mechanism-specific Java credential object. |
| 254 | * Mechanism implementations may examine the value of this property |
| 255 | * to determine whether it is a class that they support. |
| 256 | * The property may be used to supply credentials to a mechanism that |
| 257 | * supports delegated authentication. |
| 258 | *<br> |
| 259 | * The value of this constant is |
| 260 | * <tt>"javax.security.sasl.credentials"</tt>. |
| 261 | */ |
| 262 | public static final String CREDENTIALS = "javax.security.sasl.credentials"; |
| 263 | |
| 264 | /** |
| 265 | * Creates a <tt>SaslClient</tt> using the parameters supplied. |
| 266 | * |
| 267 | * This method uses the |
| 268 | <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#Provider">JCA Security Provider Framework</a>, described in the |
| 269 | * "Java Cryptography Architecture API Specification & Reference", for |
| 270 | * locating and selecting a <tt>SaslClient</tt> implementation. |
| 271 | * |
| 272 | * First, it |
| 273 | * obtains an ordered list of <tt>SaslClientFactory</tt> instances from |
| 274 | * the registered security providers for the "SaslClientFactory" service |
| 275 | * and the specified SASL mechanism(s). It then invokes |
| 276 | * <tt>createSaslClient()</tt> on each factory instance on the list |
| 277 | * until one produces a non-null <tt>SaslClient</tt> instance. It returns |
| 278 | * the non-null <tt>SaslClient</tt> instance, or null if the search fails |
| 279 | * to produce a non-null <tt>SaslClient</tt> instance. |
| 280 | *<p> |
| 281 | * A security provider for SaslClientFactory registers with the |
| 282 | * JCA Security Provider Framework keys of the form <br> |
| 283 | * <tt>SaslClientFactory.<em>mechanism_name</em></tt> |
| 284 | * <br> |
| 285 | * and values that are class names of implementations of |
| 286 | * <tt>javax.security.sasl.SaslClientFactory</tt>. |
| 287 | * |
| 288 | * For example, a provider that contains a factory class, |
| 289 | * <tt>com.wiz.sasl.digest.ClientFactory</tt>, that supports the |
| 290 | * "DIGEST-MD5" mechanism would register the following entry with the JCA: |
| 291 | * <tt>SaslClientFactory.DIGEST-MD5 com.wiz.sasl.digest.ClientFactory</tt> |
| 292 | *<p> |
| 293 | * See the |
| 294 | * "Java Cryptography Architecture API Specification & Reference" |
| 295 | * for information about how to install and configure security service |
| 296 | * providers. |
| 297 | * |
| 298 | * @param mechanisms The non-null list of mechanism names to try. Each is the |
| 299 | * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). |
| 300 | * @param authorizationId The possibly null protocol-dependent |
| 301 | * identification to be used for authorization. |
| 302 | * If null or empty, the server derives an authorization |
| 303 | * ID from the client's authentication credentials. |
| 304 | * When the SASL authentication completes successfully, |
| 305 | * the specified entity is granted access. |
| 306 | * |
| 307 | * @param protocol The non-null string name of the protocol for which |
| 308 | * the authentication is being performed (e.g., "ldap"). |
| 309 | * |
| 310 | * @param serverName The non-null fully-qualified host name of the server |
| 311 | * to authenticate to. |
| 312 | * |
| 313 | * @param props The possibly null set of properties used to |
| 314 | * select the SASL mechanism and to configure the authentication |
| 315 | * exchange of the selected mechanism. |
| 316 | * For example, if <tt>props</tt> contains the |
| 317 | * <code>Sasl.POLICY_NOPLAINTEXT</code> property with the value |
| 318 | * <tt>"true"</tt>, then the selected |
| 319 | * SASL mechanism must not be susceptible to simple plain passive attacks. |
| 320 | * In addition to the standard properties declared in this class, |
| 321 | * other, possibly mechanism-specific, properties can be included. |
| 322 | * Properties not relevant to the selected mechanism are ignored, |
| 323 | * including any map entries with non-String keys. |
| 324 | * |
| 325 | * @param cbh The possibly null callback handler to used by the SASL |
| 326 | * mechanisms to get further information from the application/library |
| 327 | * to complete the authentication. For example, a SASL mechanism might |
| 328 | * require the authentication ID, password and realm from the caller. |
| 329 | * The authentication ID is requested by using a <tt>NameCallback</tt>. |
| 330 | * The password is requested by using a <tt>PasswordCallback</tt>. |
| 331 | * The realm is requested by using a <tt>RealmChoiceCallback</tt> if there is a list |
| 332 | * of realms to choose from, and by using a <tt>RealmCallback</tt> if |
| 333 | * the realm must be entered. |
| 334 | * |
| 335 | *@return A possibly null <tt>SaslClient</tt> created using the parameters |
| 336 | * supplied. If null, cannot find a <tt>SaslClientFactory</tt> |
| 337 | * that will produce one. |
| 338 | *@exception SaslException If cannot create a <tt>SaslClient</tt> because |
| 339 | * of an error. |
| 340 | */ |
| 341 | public static SaslClient createSaslClient( |
| 342 | String[] mechanisms, |
| 343 | String authorizationId, |
| 344 | String protocol, |
| 345 | String serverName, |
| 346 | Map<String,?> props, |
| 347 | CallbackHandler cbh) throws SaslException { |
| 348 | |
| 349 | SaslClient mech = null; |
| 350 | SaslClientFactory fac; |
| 351 | String className; |
| 352 | String mechName; |
| 353 | |
| 354 | for (int i = 0; i < mechanisms.length; i++) { |
| 355 | if ((mechName=mechanisms[i]) == null) { |
| 356 | throw new NullPointerException( |
| 357 | "Mechanism name cannot be null"); |
| 358 | } else if (mechName.length() == 0) { |
| 359 | continue; |
| 360 | } |
| 361 | String mechFilter = "SaslClientFactory." + mechName; |
| 362 | Provider[] provs = Security.getProviders(mechFilter); |
| 363 | for (int j = 0; provs != null && j < provs.length; j++) { |
| 364 | className = provs[j].getProperty(mechFilter); |
| 365 | if (className == null) { |
| 366 | // Case is ignored |
| 367 | continue; |
| 368 | } |
| 369 | |
| 370 | fac = (SaslClientFactory) loadFactory(provs[j], className); |
| 371 | if (fac != null) { |
| 372 | mech = fac.createSaslClient( |
| 373 | new String[]{mechanisms[i]}, authorizationId, |
| 374 | protocol, serverName, props, cbh); |
| 375 | if (mech != null) { |
| 376 | return mech; |
| 377 | } |
| 378 | } |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | return null; |
| 383 | } |
| 384 | |
| 385 | private static Object loadFactory(Provider p, String className) |
| 386 | throws SaslException { |
| 387 | try { |
| 388 | /* |
| 389 | * Load the implementation class with the same class loader |
| 390 | * that was used to load the provider. |
| 391 | * In order to get the class loader of a class, the |
| 392 | * caller's class loader must be the same as or an ancestor of |
| 393 | * the class loader being returned. Otherwise, the caller must |
| 394 | * have "getClassLoader" permission, or a SecurityException |
| 395 | * will be thrown. |
| 396 | */ |
| 397 | ClassLoader cl = p.getClass().getClassLoader(); |
| 398 | Class implClass; |
| 399 | implClass = Class.forName(className, true, cl); |
| 400 | return implClass.newInstance(); |
| 401 | } catch (ClassNotFoundException e) { |
| 402 | throw new SaslException("Cannot load class " + className, e); |
| 403 | } catch (InstantiationException e) { |
| 404 | throw new SaslException("Cannot instantiate class " + className, e); |
| 405 | } catch (IllegalAccessException e) { |
| 406 | throw new SaslException("Cannot access class " + className, e); |
| 407 | } catch (SecurityException e) { |
| 408 | throw new SaslException("Cannot access class " + className, e); |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | |
| 413 | /** |
| 414 | * Creates a <tt>SaslServer</tt> for the specified mechanism. |
| 415 | * |
| 416 | * This method uses the |
| 417 | <a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#Provider">JCA Security Provider Framework</a>, |
| 418 | * described in the |
| 419 | * "Java Cryptography Architecture API Specification & Reference", for |
| 420 | * locating and selecting a <tt>SaslServer</tt> implementation. |
| 421 | * |
| 422 | * First, it |
| 423 | * obtains an ordered list of <tt>SaslServerFactory</tt> instances from |
| 424 | * the registered security providers for the "SaslServerFactory" service |
| 425 | * and the specified mechanism. It then invokes |
| 426 | * <tt>createSaslServer()</tt> on each factory instance on the list |
| 427 | * until one produces a non-null <tt>SaslServer</tt> instance. It returns |
| 428 | * the non-null <tt>SaslServer</tt> instance, or null if the search fails |
| 429 | * to produce a non-null <tt>SaslServer</tt> instance. |
| 430 | *<p> |
| 431 | * A security provider for SaslServerFactory registers with the |
| 432 | * JCA Security Provider Framework keys of the form <br> |
| 433 | * <tt>SaslServerFactory.<em>mechanism_name</em></tt> |
| 434 | * <br> |
| 435 | * and values that are class names of implementations of |
| 436 | * <tt>javax.security.sasl.SaslServerFactory</tt>. |
| 437 | * |
| 438 | * For example, a provider that contains a factory class, |
| 439 | * <tt>com.wiz.sasl.digest.ServerFactory</tt>, that supports the |
| 440 | * "DIGEST-MD5" mechanism would register the following entry with the JCA: |
| 441 | * <tt>SaslServerFactory.DIGEST-MD5 com.wiz.sasl.digest.ServerFactory</tt> |
| 442 | *<p> |
| 443 | * See the |
| 444 | * "Java Cryptography Architecture API Specification & Reference" |
| 445 | * for information about how to install and configure security |
| 446 | * service providers. |
| 447 | * |
| 448 | * @param mechanism The non-null mechanism name. It must be an |
| 449 | * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). |
| 450 | * @param protocol The non-null string name of the protocol for which |
| 451 | * the authentication is being performed (e.g., "ldap"). |
| 452 | * @param serverName The non-null fully qualified host name of the server. |
| 453 | * @param props The possibly null set of properties used to |
| 454 | * select the SASL mechanism and to configure the authentication |
| 455 | * exchange of the selected mechanism. |
| 456 | * For example, if <tt>props</tt> contains the |
| 457 | * <code>Sasl.POLICY_NOPLAINTEXT</code> property with the value |
| 458 | * <tt>"true"</tt>, then the selected |
| 459 | * SASL mechanism must not be susceptible to simple plain passive attacks. |
| 460 | * In addition to the standard properties declared in this class, |
| 461 | * other, possibly mechanism-specific, properties can be included. |
| 462 | * Properties not relevant to the selected mechanism are ignored, |
| 463 | * including any map entries with non-String keys. |
| 464 | * |
| 465 | * @param cbh The possibly null callback handler to used by the SASL |
| 466 | * mechanisms to get further information from the application/library |
| 467 | * to complete the authentication. For example, a SASL mechanism might |
| 468 | * require the authentication ID, password and realm from the caller. |
| 469 | * The authentication ID is requested by using a <tt>NameCallback</tt>. |
| 470 | * The password is requested by using a <tt>PasswordCallback</tt>. |
| 471 | * The realm is requested by using a <tt>RealmChoiceCallback</tt> if there is a list |
| 472 | * of realms to choose from, and by using a <tt>RealmCallback</tt> if |
| 473 | * the realm must be entered. |
| 474 | * |
| 475 | *@return A possibly null <tt>SaslServer</tt> created using the parameters |
| 476 | * supplied. If null, cannot find a <tt>SaslServerFactory</tt> |
| 477 | * that will produce one. |
| 478 | *@exception SaslException If cannot create a <tt>SaslServer</tt> because |
| 479 | * of an error. |
| 480 | **/ |
| 481 | public static SaslServer |
| 482 | createSaslServer(String mechanism, |
| 483 | String protocol, |
| 484 | String serverName, |
| 485 | Map<String,?> props, |
| 486 | javax.security.auth.callback.CallbackHandler cbh) |
| 487 | throws SaslException { |
| 488 | |
| 489 | SaslServer mech = null; |
| 490 | SaslServerFactory fac; |
| 491 | String className; |
| 492 | |
| 493 | if (mechanism == null) { |
| 494 | throw new NullPointerException("Mechanism name cannot be null"); |
| 495 | } else if (mechanism.length() == 0) { |
| 496 | return null; |
| 497 | } |
| 498 | |
| 499 | String mechFilter = "SaslServerFactory." + mechanism; |
| 500 | Provider[] provs = Security.getProviders(mechFilter); |
| 501 | for (int j = 0; provs != null && j < provs.length; j++) { |
| 502 | className = provs[j].getProperty(mechFilter); |
| 503 | if (className == null) { |
| 504 | throw new SaslException("Provider does not support " + |
| 505 | mechFilter); |
| 506 | } |
| 507 | fac = (SaslServerFactory) loadFactory(provs[j], className); |
| 508 | if (fac != null) { |
| 509 | mech = fac.createSaslServer( |
| 510 | mechanism, protocol, serverName, props, cbh); |
| 511 | if (mech != null) { |
| 512 | return mech; |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | |
| 517 | return null; |
| 518 | } |
| 519 | |
| 520 | /** |
| 521 | * Gets an enumeration of known factories for producing <tt>SaslClient</tt>. |
| 522 | * This method uses the same algorithm for locating factories as |
| 523 | * <tt>createSaslClient()</tt>. |
| 524 | * @return A non-null enumeration of known factories for producing |
| 525 | * <tt>SaslClient</tt>. |
| 526 | * @see #createSaslClient |
| 527 | */ |
| 528 | public static Enumeration<SaslClientFactory> getSaslClientFactories() { |
| 529 | Set<Object> facs = getFactories("SaslClientFactory"); |
| 530 | final Iterator<Object> iter = facs.iterator(); |
| 531 | return new Enumeration<SaslClientFactory>() { |
| 532 | public boolean hasMoreElements() { |
| 533 | return iter.hasNext(); |
| 534 | } |
| 535 | public SaslClientFactory nextElement() { |
| 536 | return (SaslClientFactory)iter.next(); |
| 537 | } |
| 538 | }; |
| 539 | } |
| 540 | |
| 541 | /** |
| 542 | * Gets an enumeration of known factories for producing <tt>SaslServer</tt>. |
| 543 | * This method uses the same algorithm for locating factories as |
| 544 | * <tt>createSaslServer()</tt>. |
| 545 | * @return A non-null enumeration of known factories for producing |
| 546 | * <tt>SaslServer</tt>. |
| 547 | * @see #createSaslServer |
| 548 | */ |
| 549 | public static Enumeration<SaslServerFactory> getSaslServerFactories() { |
| 550 | Set<Object> facs = getFactories("SaslServerFactory"); |
| 551 | final Iterator<Object> iter = facs.iterator(); |
| 552 | return new Enumeration<SaslServerFactory>() { |
| 553 | public boolean hasMoreElements() { |
| 554 | return iter.hasNext(); |
| 555 | } |
| 556 | public SaslServerFactory nextElement() { |
| 557 | return (SaslServerFactory)iter.next(); |
| 558 | } |
| 559 | }; |
| 560 | } |
| 561 | |
| 562 | private static Set<Object> getFactories(String serviceName) { |
| 563 | HashSet<Object> result = new HashSet<Object>(); |
| 564 | |
| 565 | if ((serviceName == null) || (serviceName.length() == 0) || |
| 566 | (serviceName.endsWith("."))) { |
| 567 | return result; |
| 568 | } |
| 569 | |
| 570 | |
| 571 | Provider[] providers = Security.getProviders(); |
| 572 | HashSet<String> classes = new HashSet<String>(); |
| 573 | Object fac; |
| 574 | |
| 575 | for (int i = 0; i < providers.length; i++) { |
| 576 | classes.clear(); |
| 577 | |
| 578 | // Check the keys for each provider. |
| 579 | for (Enumeration e = providers[i].keys(); e.hasMoreElements(); ) { |
| 580 | String currentKey = (String)e.nextElement(); |
| 581 | if (currentKey.startsWith(serviceName)) { |
| 582 | // We should skip the currentKey if it contains a |
| 583 | // whitespace. The reason is: such an entry in the |
| 584 | // provider property contains attributes for the |
| 585 | // implementation of an algorithm. We are only interested |
| 586 | // in entries which lead to the implementation |
| 587 | // classes. |
| 588 | if (currentKey.indexOf(" ") < 0) { |
| 589 | String className = providers[i].getProperty(currentKey); |
| 590 | if (!classes.contains(className)) { |
| 591 | classes.add(className); |
| 592 | try { |
| 593 | fac = loadFactory(providers[i], className); |
| 594 | if (fac != null) { |
| 595 | result.add(fac); |
| 596 | } |
| 597 | }catch (Exception ignore) { |
| 598 | } |
| 599 | } |
| 600 | } |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | return Collections.unmodifiableSet(result); |
| 605 | } |
| 606 | } |