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); |