View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.integration.spring.ssl;
    21
    22  import java.security.KeyStore;
    23  import java.security.SecureRandom;
    24
    25  import javax.net.ssl.KeyManager;
    26  import javax.net.ssl.KeyManagerFactory;
    27  import javax.net.ssl.SSLContext;
    28  import javax.net.ssl.TrustManager;
    29  import javax.net.ssl.TrustManagerFactory;
    30  import javax.net.ssl.ManagerFactoryParameters;
    31
    32  import org.springframework.beans.factory.config.AbstractFactoryBean;
    33  import org.springframework.util.Assert;
    34
    35  /**
    36   * Spring {@link org.springframework.beans.factory.FactoryBean} implementation
    37   * which makes it possible to configure {@link javax.net.ssl.SSLContext}
    38   * instances using Spring.
    39   * <p>
    40   * If no properties are set the returned {@link javax.net.ssl.SSLContext} will
    41   * be equivalent to what the following creates:
    42   * <pre>
    43   *      SSLContext c = SSLContext.getInstance( "TLS" );
    44   *      c.init( null, null, null );
    45   * </pre>
    46   * </p>
    47   * <p>
    48   * Use the properties prefixed with <code>keyManagerFactory</code> to control
    49   * the creation of the {@link javax.net.ssl.KeyManager} to be used.
    50   * </p>
    51   * <p>
    52   * Use the properties prefixed with <code>trustManagerFactory</code> to control
    53   * the creation of the {@link javax.net.ssl.TrustManagerFactory} to be used.
    54   * </p>
    55   *
    56   * @author The Apache Directory Project (mina-dev@directory.apache.org)
    57   * @version $Rev: 555855 $, $Date: 2007-07-13 05:19:00 +0200 (Fri, 13 Jul 2007) $
    58   */
    59  public class SSLContextFactoryBean extends AbstractFactoryBean {
    60      private String protocol = "TLS";
    61
    62      private String provider = null;
    63
    64      private SecureRandom secureRandom = null;
    65
    66      private KeyStore keyManagerFactoryKeyStore = null;
    67
    68      private char[] keyManagerFactoryKeyStorePassword = null;
    69
    70      private KeyManagerFactory keyManagerFactory = null;
    71
    72      private String keyManagerFactoryAlgorithm = null;
    73
    74      private String keyManagerFactoryProvider = null;
    75
    76      private boolean keyManagerFactoryAlgorithmUseDefault = false;
    77
    78      private KeyStore trustManagerFactoryKeyStore = null;
    79
    80      private TrustManagerFactory trustManagerFactory = null;
    81
    82      private String trustManagerFactoryAlgorithm = null;
    83
    84      private String trustManagerFactoryProvider = null;
    85
    86      private boolean trustManagerFactoryAlgorithmUseDefault = false;
    87
    88      private ManagerFactoryParameters trustManagerFactoryParameters = null;
    89
    90      protected Object createInstance() throws Exception {
    91          KeyManagerFactory kmf = this.keyManagerFactory;
    92          TrustManagerFactory tmf = this.trustManagerFactory;
    93
    94          if (kmf == null) {
    95              String algorithm = keyManagerFactoryAlgorithm;
    96              if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) {
    97                  algorithm = KeyManagerFactory.getDefaultAlgorithm();
    98              }
    99              if (algorithm != null) {
    100                 if (keyManagerFactoryProvider == null) {
    101                     kmf = KeyManagerFactory.getInstance(algorithm);
    102                 } else {
    103                     kmf = KeyManagerFactory.getInstance(algorithm,
    104                             keyManagerFactoryProvider);
    105                 }
    106             }
    107         }
    108
    109         if (tmf == null) {
    110             String algorithm = trustManagerFactoryAlgorithm;
    111             if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) {
    112                 algorithm = TrustManagerFactory.getDefaultAlgorithm();
    113             }
    114             if (algorithm != null) {
    115                 if (trustManagerFactoryProvider == null) {
    116                     tmf = TrustManagerFactory.getInstance(algorithm);
    117                 } else {
    118                     tmf = TrustManagerFactory.getInstance(algorithm,
    119                             trustManagerFactoryProvider);
    120                 }
    121             }
    122         }
    123
    124         KeyManager[] keyManagers = null;
    125         if (kmf != null) {
    126             kmf.init(keyManagerFactoryKeyStore,
    127                     keyManagerFactoryKeyStorePassword);
    128             keyManagers = kmf.getKeyManagers();
    129         }
    130         TrustManager[] trustManagers = null;
    131         if (tmf != null) {
    132             if (trustManagerFactoryParameters != null) {
    133                 tmf.init(trustManagerFactoryParameters);
    134             } else {
    135                 tmf.init(trustManagerFactoryKeyStore);
    136             }
    137             trustManagers = tmf.getTrustManagers();
    138         }
    139
    140         SSLContext context = null;
    141         if (provider == null) {
    142             context = SSLContext.getInstance(protocol);
    143         } else {
    144             context = SSLContext.getInstance(protocol, provider);
    145         }
    146
    147         context.init(keyManagers, trustManagers, secureRandom);
    148
    149         return context;
    150     }
    151
    152     public Class getObjectType() {
    153         return SSLContext.class;
    154     }
    155
    156     /**
    157      * Sets the protocol to use when creating the {@link SSLContext}. The
    158      * default is <code>TLS</code>.
    159      *
    160      * @param protocol the name of the protocol.
    161      * @throws IllegalArgumentException if the specified value is
    162      *         <code>null</code>.
    163      */
    164     public void setProtocol(String protocol) {
    165         Assert.notNull(protocol, "Property 'protocol' may not be null");
    166         this.protocol = protocol;
    167     }
    168
    169     /**
    170      * If this is set to <code>true</code> while no {@link KeyManagerFactory}
    171      * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
    172      * no algorithm has been set using
    173      * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm
    174      * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used.
    175      *
    176      * @param useDefault <code>true</code> or <code>false</code>.
    177      */
    178     public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) {
    179         this.keyManagerFactoryAlgorithmUseDefault = useDefault;
    180     }
    181
    182     /**
    183      * If this is set to <code>true</code> while no {@link TrustManagerFactory}
    184      * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
    185      * no algorithm has been set using
    186      * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm
    187      * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used.
    188      *
    189      * @param useDefault <code>true</code> or <code>false</code>.
    190      */
    191     public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) {
    192         this.trustManagerFactoryAlgorithmUseDefault = useDefault;
    193     }
    194
    195     /**
    196      * Sets the {@link KeyManagerFactory} to use. If this is set the properties
    197      * which are used by this factory bean to create a {@link KeyManagerFactory}
    198      * will all be ignored.
    199      *
    200      * @param factory the factory.
    201      */
    202     public void setKeyManagerFactory(KeyManagerFactory factory) {
    203         this.keyManagerFactory = factory;
    204     }
    205
    206     /**
    207      * Sets the algorithm to use when creating the {@link KeyManagerFactory}
    208      * using {@link KeyManagerFactory#getInstance(java.lang.String)} or
    209      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    210      * <p>
    211      * This property will be ignored if a {@link KeyManagerFactory} has been
    212      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
    213      * </p>
    214      * <p>
    215      * If this property isn't set while no {@link KeyManagerFactory} has been
    216      * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
    217      * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to
    218      * <code>true</code> the value returned
    219      * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead.
    220      * </p>
    221      *
    222      * @param algorithm the algorithm to use.
    223      */
    224     public void setKeyManagerFactoryAlgorithm(String algorithm) {
    225         this.keyManagerFactoryAlgorithm = algorithm;
    226     }
    227
    228     /**
    229      * Sets the provider to use when creating the {@link KeyManagerFactory}
    230      * using
    231      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    232      * <p>
    233      * This property will be ignored if a {@link KeyManagerFactory} has been
    234      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
    235      * </p>
    236      * <p>
    237      * If this property isn't set and no {@link KeyManagerFactory} has been set
    238      * using {@link #setKeyManagerFactory(KeyManagerFactory)}
    239      * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used
    240      * to create the {@link KeyManagerFactory}.
    241      * </p>
    242      *
    243      * @param provider the name of the provider.
    244      */
    245     public void setKeyManagerFactoryProvider(String provider) {
    246         this.keyManagerFactoryProvider = provider;
    247     }
    248
    249     /**
    250      * Sets the {@link KeyStore} which will be used in the call to
    251      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
    252      * the {@link SSLContext} is created.
    253      *
    254      * @param keyStore the key store.
    255      */
    256     public void setKeyManagerFactoryKeyStore(KeyStore keyStore) {
    257         this.keyManagerFactoryKeyStore = keyStore;
    258     }
    259
    260     /**
    261      * Sets the password which will be used in the call to
    262      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
    263      * the {@link SSLContext} is created.
    264      *
    265      * @param password the password. Use <code>null</code> to disable password.
    266      */
    267     public void setKeyManagerFactoryKeyStorePassword(String password) {
    268         if (password != null) {
    269             this.keyManagerFactoryKeyStorePassword = password.toCharArray();
    270         } else {
    271             this.keyManagerFactoryKeyStorePassword = null;
    272         }
    273     }
    274
    275     /**
    276      * Sets the {@link TrustManagerFactory} to use. If this is set the properties
    277      * which are used by this factory bean to create a {@link TrustManagerFactory}
    278      * will all be ignored.
    279      *
    280      * @param factory the factory.
    281      */
    282     public void setTrustManagerFactory(TrustManagerFactory factory) {
    283         this.trustManagerFactory = factory;
    284     }
    285
    286     /**
    287      * Sets the algorithm to use when creating the {@link TrustManagerFactory}
    288      * using {@link TrustManagerFactory#getInstance(java.lang.String)} or
    289      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    290      * <p>
    291      * This property will be ignored if a {@link TrustManagerFactory} has been
    292      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
    293      * </p>
    294      * <p>
    295      * If this property isn't set while no {@link TrustManagerFactory} has been
    296      * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
    297      * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to
    298      * <code>true</code> the value returned
    299      * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead.
    300      * </p>
    301      *
    302      * @param algorithm the algorithm to use.
    303      */
    304     public void setTrustManagerFactoryAlgorithm(String algorithm) {
    305         this.trustManagerFactoryAlgorithm = algorithm;
    306     }
    307
    308     /**
    309      * Sets the {@link KeyStore} which will be used in the call to
    310      * {@link TrustManagerFactory#init(java.security.KeyStore)} when
    311      * the {@link SSLContext} is created.
    312      * <p>
    313      * This property will be ignored if {@link ManagerFactoryParameters} has been
    314      * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}.
    315      * </p>
    316      *
    317      * @param keyStore the key store.
    318      */
    319     public void setTrustManagerFactoryKeyStore(KeyStore keyStore) {
    320         this.trustManagerFactoryKeyStore = keyStore;
    321     }
    322
    323     /**
    324      * Sets the {@link ManagerFactoryParameters} which will be used in the call to
    325      * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when
    326      * the {@link SSLContext} is created.
    327      *
    328      * @param parameters describing provider-specific trust material.
    329      */
    330     public void setTrustManagerFactoryParameters(
    331             ManagerFactoryParameters parameters) {
    332         this.trustManagerFactoryParameters = parameters;
    333     }
    334
    335     /**
    336      * Sets the provider to use when creating the {@link TrustManagerFactory}
    337      * using
    338      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    339      * <p>
    340      * This property will be ignored if a {@link TrustManagerFactory} has been
    341      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
    342      * </p>
    343      * <p>
    344      * If this property isn't set and no {@link TrustManagerFactory} has been set
    345      * using {@link #setTrustManagerFactory(TrustManagerFactory)}
    346      * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used
    347      * to create the {@link TrustManagerFactory}.
    348      * </p>
    349      *
    350      * @param provider the name of the provider.
    351      */
    352     public void setTrustManagerFactoryProvider(String provider) {
    353         this.trustManagerFactoryProvider = provider;
    354     }
    355
    356     /**
    357      * Sets the {@link SecureRandom} to use when initializing the
    358      * {@link SSLContext}. The JVM's default will be used if this isn't set.
    359      *
    360      * @param secureRandom the {@link SecureRandom} or <code>null</code> if the
    361      *        JVM's default should be used.
    362      * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
    363      */
    364     public void setSecureRandom(SecureRandom secureRandom) {
    365         this.secureRandom = secureRandom;
    366     }
    367
    368 }