jdk/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java
changeset 31270 e6470b24700d
parent 25859 3317bb8137f4
child 33241 27eb2d6abda9
equal deleted inserted replaced
31269:14968253ce7e 31270:e6470b24700d
     1 /*
     1 /*
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    31 import java.util.Iterator;
    31 import java.util.Iterator;
    32 import java.util.Map;
    32 import java.util.Map;
    33 import java.util.Set;
    33 import java.util.Set;
    34 import java.util.HashSet;
    34 import java.util.HashSet;
    35 import java.util.Collections;
    35 import java.util.Collections;
       
    36 import java.security.InvalidParameterException;
       
    37 import java.security.NoSuchAlgorithmException;
    36 import java.security.Provider;
    38 import java.security.Provider;
       
    39 import java.security.Provider.Service;
    37 import java.security.Security;
    40 import java.security.Security;
    38 
    41 
    39 /**
    42 /**
    40  * A static class for creating SASL clients and servers.
    43  * A static class for creating SASL clients and servers.
    41  *<p>
    44  *<p>
   358         Map<String,?> props,
   361         Map<String,?> props,
   359         CallbackHandler cbh) throws SaslException {
   362         CallbackHandler cbh) throws SaslException {
   360 
   363 
   361         SaslClient mech = null;
   364         SaslClient mech = null;
   362         SaslClientFactory fac;
   365         SaslClientFactory fac;
   363         String className;
   366         Service service;
   364         String mechName;
   367         String mechName;
   365 
   368 
   366         for (int i = 0; i < mechanisms.length; i++) {
   369         for (int i = 0; i < mechanisms.length; i++) {
   367             if ((mechName=mechanisms[i]) == null) {
   370             if ((mechName=mechanisms[i]) == null) {
   368                 throw new NullPointerException(
   371                 throw new NullPointerException(
   369                     "Mechanism name cannot be null");
   372                     "Mechanism name cannot be null");
   370             } else if (mechName.length() == 0) {
   373             } else if (mechName.length() == 0) {
   371                 continue;
   374                 continue;
   372             }
   375             }
   373             String mechFilter = "SaslClientFactory." + mechName;
   376             String type = "SaslClientFactory";
   374             Provider[] provs = Security.getProviders(mechFilter);
   377             Provider[] provs = Security.getProviders(type + "." + mechName);
   375             for (int j = 0; provs != null && j < provs.length; j++) {
   378             if (provs != null) {
   376                 className = provs[j].getProperty(mechFilter);
   379                 for (Provider p : provs) {
   377                 if (className == null) {
   380                     service = p.getService(type, mechName);
   378                     // Case is ignored
   381                     if (service == null) {
   379                     continue;
   382                         // no such service exists
   380                 }
   383                         continue;
   381 
   384                     }
   382                 fac = (SaslClientFactory) loadFactory(provs[j], className);
   385 
   383                 if (fac != null) {
   386                     fac = (SaslClientFactory) loadFactory(service);
   384                     mech = fac.createSaslClient(
   387                     if (fac != null) {
   385                         new String[]{mechanisms[i]}, authorizationId,
   388                         mech = fac.createSaslClient(
   386                         protocol, serverName, props, cbh);
   389                             new String[]{mechanisms[i]}, authorizationId,
   387                     if (mech != null) {
   390                             protocol, serverName, props, cbh);
   388                         return mech;
   391                         if (mech != null) {
       
   392                             return mech;
       
   393                         }
   389                     }
   394                     }
   390                 }
   395                 }
   391             }
   396             }
   392         }
   397         }
   393 
       
   394         return null;
   398         return null;
   395     }
   399     }
   396 
   400 
   397     private static Object loadFactory(Provider p, String className)
   401     private static Object loadFactory(Service service)
   398         throws SaslException {
   402         throws SaslException {
   399         try {
   403         try {
   400             /*
   404             /*
   401              * Load the implementation class with the same class loader
   405              * Load the implementation class with the same class loader
   402              * that was used to load the provider.
   406              * that was used to load the provider.
   404              * caller's class loader must be the same as or an ancestor of
   408              * caller's class loader must be the same as or an ancestor of
   405              * the class loader being returned. Otherwise, the caller must
   409              * the class loader being returned. Otherwise, the caller must
   406              * have "getClassLoader" permission, or a SecurityException
   410              * have "getClassLoader" permission, or a SecurityException
   407              * will be thrown.
   411              * will be thrown.
   408              */
   412              */
   409             ClassLoader cl = p.getClass().getClassLoader();
   413             return service.newInstance(null);
   410             Class<?> implClass;
   414         } catch (InvalidParameterException | NoSuchAlgorithmException e) {
   411             implClass = Class.forName(className, true, cl);
   415             throw new SaslException("Cannot instantiate service " + service, e);
   412             return implClass.newInstance();
       
   413         } catch (ClassNotFoundException e) {
       
   414             throw new SaslException("Cannot load class " + className, e);
       
   415         } catch (InstantiationException e) {
       
   416             throw new SaslException("Cannot instantiate class " + className, e);
       
   417         } catch (IllegalAccessException e) {
       
   418             throw new SaslException("Cannot access class " + className, e);
       
   419         } catch (SecurityException e) {
       
   420             throw new SaslException("Cannot access class " + className, e);
       
   421         }
   416         }
   422     }
   417     }
   423 
   418 
   424 
   419 
   425     /**
   420     /**
   501                     javax.security.auth.callback.CallbackHandler cbh)
   496                     javax.security.auth.callback.CallbackHandler cbh)
   502         throws SaslException {
   497         throws SaslException {
   503 
   498 
   504         SaslServer mech = null;
   499         SaslServer mech = null;
   505         SaslServerFactory fac;
   500         SaslServerFactory fac;
   506         String className;
   501         Service service;
   507 
   502 
   508         if (mechanism == null) {
   503         if (mechanism == null) {
   509             throw new NullPointerException("Mechanism name cannot be null");
   504             throw new NullPointerException("Mechanism name cannot be null");
   510         } else if (mechanism.length() == 0) {
   505         } else if (mechanism.length() == 0) {
   511             return null;
   506             return null;
   512         }
   507         }
   513 
   508 
   514         String mechFilter = "SaslServerFactory." + mechanism;
   509         String type = "SaslServerFactory";
   515         Provider[] provs = Security.getProviders(mechFilter);
   510         Provider[] provs = Security.getProviders(type + "." + mechanism);
   516         for (int j = 0; provs != null && j < provs.length; j++) {
   511         if (provs != null) {
   517             className = provs[j].getProperty(mechFilter);
   512             for (Provider p : provs) {
   518             if (className == null) {
   513                 service = p.getService(type, mechanism);
   519                 throw new SaslException("Provider does not support " +
   514                 if (service == null) {
   520                     mechFilter);
   515                     throw new SaslException("Provider does not support " +
   521             }
   516                         mechanism + " " + type);
   522             fac = (SaslServerFactory) loadFactory(provs[j], className);
       
   523             if (fac != null) {
       
   524                 mech = fac.createSaslServer(
       
   525                     mechanism, protocol, serverName, props, cbh);
       
   526                 if (mech != null) {
       
   527                     return mech;
       
   528                 }
   517                 }
       
   518                 fac = (SaslServerFactory) loadFactory(service);
       
   519                 if (fac != null) {
       
   520                     mech = fac.createSaslServer(
       
   521                         mechanism, protocol, serverName, props, cbh);
       
   522                     if (mech != null) {
       
   523                         return mech;
       
   524                     }
       
   525                 }
   529             }
   526             }
   530         }
   527         }
   531 
       
   532         return null;
   528         return null;
   533     }
   529     }
   534 
   530 
   535     /**
   531     /**
   536      * Gets an enumeration of known factories for producing {@code SaslClient}.
   532      * Gets an enumeration of known factories for producing {@code SaslClient}.
   580         if ((serviceName == null) || (serviceName.length() == 0) ||
   576         if ((serviceName == null) || (serviceName.length() == 0) ||
   581             (serviceName.endsWith("."))) {
   577             (serviceName.endsWith("."))) {
   582             return result;
   578             return result;
   583         }
   579         }
   584 
   580 
   585 
   581         Provider[] provs = Security.getProviders();
   586         Provider[] providers = Security.getProviders();
       
   587         HashSet<String> classes = new HashSet<String>();
       
   588         Object fac;
   582         Object fac;
   589 
   583 
   590         for (int i = 0; i < providers.length; i++) {
   584         for (Provider p : provs) {
   591             classes.clear();
   585 
   592 
   586             Iterator<Service> iter = p.getServices().iterator();
   593             // Check the keys for each provider.
   587             while (iter.hasNext()) {
   594             for (Enumeration<Object> e = providers[i].keys(); e.hasMoreElements(); ) {
   588                 Service s = iter.next();
   595                 String currentKey = (String)e.nextElement();
   589                 if (s.getType().equals(serviceName)) {
   596                 if (currentKey.startsWith(serviceName)) {
   590                     try {
   597                     // We should skip the currentKey if it contains a
   591                         fac = loadFactory(s);
   598                     // whitespace. The reason is: such an entry in the
   592                         if (fac != null) {
   599                     // provider property contains attributes for the
   593                             result.add(fac);
   600                     // implementation of an algorithm. We are only interested
       
   601                     // in entries which lead to the implementation
       
   602                     // classes.
       
   603                     if (currentKey.indexOf(' ') < 0) {
       
   604                         String className = providers[i].getProperty(currentKey);
       
   605                         if (!classes.contains(className)) {
       
   606                             classes.add(className);
       
   607                             try {
       
   608                                 fac = loadFactory(providers[i], className);
       
   609                                 if (fac != null) {
       
   610                                     result.add(fac);
       
   611                                 }
       
   612                             }catch (Exception ignore) {
       
   613                             }
       
   614                         }
   594                         }
       
   595                     } catch (Exception ignore) {
   615                     }
   596                     }
   616                 }
   597                 }
   617             }
   598             }
   618         }
   599         }
   619         return Collections.unmodifiableSet(result);
   600         return Collections.unmodifiableSet(result);