View Javadoc
1   /*
2    * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
3    * Copyright (C) 2009  Mickael Guessant
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18   */
19  package davmail.http;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.InputStream;
23  import java.lang.reflect.Constructor;
24  import java.lang.reflect.Method;
25  import java.nio.charset.StandardCharsets;
26  import java.security.AuthProvider;
27  import java.security.Provider;
28  import java.security.Security;
29  
30  /**
31   * Add the SunPKCS11 Provider.
32   */
33  public final class SunPKCS11ProviderHandler {
34  
35      private SunPKCS11ProviderHandler() {
36      }
37  
38      /**
39       * Register PKCS11 provider.
40       *
41       * @param pkcs11Config PKCS11 config string
42       */
43      public static void registerProvider(String pkcs11Config) {
44          Provider p;
45  
46          try {
47              @SuppressWarnings("unchecked") Class<AuthProvider> sunPkcs11Class = (Class<AuthProvider>) Class.forName("sun.security.pkcs11.SunPKCS11");
48              Constructor<AuthProvider> sunPkcs11Constructor = sunPkcs11Class.getDeclaredConstructor(InputStream.class);
49              p = sunPkcs11Constructor.newInstance(new ByteArrayInputStream(pkcs11Config.getBytes(StandardCharsets.UTF_8)));
50          } catch (NoSuchMethodException e) {
51              // try java 9 configuration
52              p = configurePkcs11Provider(pkcs11Config);
53          } catch (Exception e) {
54              throw new PKCS11ProviderException(buildErrorMessage(e));
55          }
56  
57          Security.addProvider(p);
58      }
59  
60      private static Provider configurePkcs11Provider(String pkcs11Config) {
61          Provider p;
62          try {
63              p = Security.getProvider("SunPKCS11");
64              // new Java 9 configure method
65              Method configureMethod = Provider.class.getDeclaredMethod("configure", String.class);
66              configureMethod.invoke(p, "--"+pkcs11Config);
67          } catch (Exception e) {
68              throw new PKCS11ProviderException(buildErrorMessage(e));
69          }
70          return p;
71      }
72  
73      private static String buildErrorMessage(Exception e) {
74          StringBuilder errorMessage = new StringBuilder("Unable to configure SunPKCS11 provider");
75          Throwable cause = e.getCause();
76          while (cause != null) {
77              errorMessage.append(" ").append(cause.getMessage());
78              cause = cause.getCause();
79          }
80          return errorMessage.toString();
81      }
82  
83      static final class PKCS11ProviderException extends RuntimeException {
84          public PKCS11ProviderException(String message) {
85              super(message);
86          }
87      }
88  
89  }