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.filter.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.ManagerFactoryParameters;
    28  import javax.net.ssl.SSLContext;
    29  import javax.net.ssl.SSLSessionContext;
    30  import javax.net.ssl.TrustManager;
    31  import javax.net.ssl.TrustManagerFactory;
    32
    33  /**
    34   * A factory that creates and configures a new {@link SSLContext}.
    35   * <p>
    36   * If no properties are set the returned {@link SSLContext} will
    37   * be equivalent to what the following creates:
    38   * <pre>
    39   *      SSLContext c = SSLContext.getInstance( "TLS" );
    40   *      c.init(null, null, null);
    41   * </pre>
    42   * </p>
    43   * <p>
    44   * Use the properties prefixed with <code>keyManagerFactory</code> to control
    45   * the creation of the {@link KeyManager} to be used.
    46   * </p>
    47   * <p>
    48   * Use the properties prefixed with <code>trustManagerFactory</code> to control
    49   * the creation of the {@link TrustManagerFactory} to be used.
    50   * </p>
    51   *
    52   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    53   */
    54  public class SslContextFactory {
    55
    56      private String provider = null;
    57
    58      private String protocol = "TLS";
    59
    60      private SecureRandom secureRandom = null;
    61
    62      private KeyStore keyManagerFactoryKeyStore = null;
    63
    64      private char[] keyManagerFactoryKeyStorePassword = null;
    65
    66      private KeyManagerFactory keyManagerFactory = null;
    67
    68      private String keyManagerFactoryAlgorithm = null;
    69
    70      private String keyManagerFactoryProvider = null;
    71
    72      private boolean keyManagerFactoryAlgorithmUseDefault = true;
    73
    74      private KeyStore trustManagerFactoryKeyStore = null;
    75
    76      private TrustManagerFactory trustManagerFactory = null;
    77
    78      private String trustManagerFactoryAlgorithm = null;
    79
    80      private String trustManagerFactoryProvider = null;
    81
    82      private boolean trustManagerFactoryAlgorithmUseDefault = true;
    83
    84      private ManagerFactoryParameters trustManagerFactoryParameters = null;
    85
    86      private int clientSessionCacheSize = -1;
    87
    88      private int clientSessionTimeout = -1;
    89
    90      private int serverSessionCacheSize = -1;
    91
    92      private int serverSessionTimeout = -1;
    93
    94      public SSLContext newInstance() throws Exception {
    95          KeyManagerFactory kmf = this.keyManagerFactory;
    96          TrustManagerFactory tmf = this.trustManagerFactory;
    97
    98          if (kmf == null) {
    99              String algorithm = keyManagerFactoryAlgorithm;
    100             if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) {
    101                 algorithm = KeyManagerFactory.getDefaultAlgorithm();
    102             }
    103             if (algorithm != null) {
    104                 if (keyManagerFactoryProvider == null) {
    105                     kmf = KeyManagerFactory.getInstance(algorithm);
    106                 } else {
    107                     kmf = KeyManagerFactory.getInstance(algorithm, keyManagerFactoryProvider);
    108                 }
    109             }
    110         }
    111
    112         if (tmf == null) {
    113             String algorithm = trustManagerFactoryAlgorithm;
    114             if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) {
    115                 algorithm = TrustManagerFactory.getDefaultAlgorithm();
    116             }
    117             if (algorithm != null) {
    118                 if (trustManagerFactoryProvider == null) {
    119                     tmf = TrustManagerFactory.getInstance(algorithm);
    120                 } else {
    121                     tmf = TrustManagerFactory.getInstance(algorithm, trustManagerFactoryProvider);
    122                 }
    123             }
    124         }
    125
    126         KeyManager[] keyManagers = null;
    127         if (kmf != null) {
    128             kmf.init(keyManagerFactoryKeyStore, keyManagerFactoryKeyStorePassword);
    129             keyManagers = kmf.getKeyManagers();
    130         }
    131         TrustManager[] trustManagers = null;
    132         if (tmf != null) {
    133             if (trustManagerFactoryParameters != null) {
    134                 tmf.init(trustManagerFactoryParameters);
    135             } else {
    136                 tmf.init(trustManagerFactoryKeyStore);
    137             }
    138             trustManagers = tmf.getTrustManagers();
    139         }
    140
    141         SSLContext context = null;
    142         if (provider == null) {
    143             context = SSLContext.getInstance(protocol);
    144         } else {
    145             context = SSLContext.getInstance(protocol, provider);
    146         }
    147
    148         context.init(keyManagers, trustManagers, secureRandom);
    149
    150         if (clientSessionCacheSize >= 0) {
    151             context.getClientSessionContext().setSessionCacheSize(clientSessionCacheSize);
    152         }
    153
    154         if (clientSessionTimeout >= 0) {
    155             context.getClientSessionContext().setSessionTimeout(clientSessionTimeout);
    156         }
    157
    158         if (serverSessionCacheSize >= 0) {
    159             context.getServerSessionContext().setSessionCacheSize(serverSessionCacheSize);
    160         }
    161
    162         if (serverSessionTimeout >= 0) {
    163             context.getServerSessionContext().setSessionTimeout(serverSessionTimeout);
    164         }
    165
    166         return context;
    167     }
    168
    169     /**
    170      * Sets the provider of the new {@link SSLContext}. The default value is
    171      * <tt>null</tt>, which means the default provider will be used.
    172      *
    173      * @param provider the name of the {@link SSLContext} provider
    174      */
    175     public void setProvider(String provider) {
    176         this.provider = provider;
    177     }
    178
    179     /**
    180      * Sets the protocol to use when creating the {@link SSLContext}. The
    181      * default is <code>TLS</code>.
    182      *
    183      * @param protocol the name of the protocol.
    184      */
    185     public void setProtocol(String protocol) {
    186         if (protocol == null) {
    187             throw new IllegalArgumentException("protocol");
    188         }
    189         this.protocol = protocol;
    190     }
    191
    192     /**
    193      * If this is set to <code>true</code> while no {@link KeyManagerFactory}
    194      * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
    195      * no algorithm has been set using
    196      * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm
    197      * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used.
    198      * The default value of this property is <tt>true<tt/>.
    199      *
    200      * @param useDefault
    201      *            <code>true</code> or <code>false</code>.
    202      */
    203     public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) {
    204         this.keyManagerFactoryAlgorithmUseDefault = useDefault;
    205     }
    206
    207     /**
    208      * If this is set to <code>true</code> while no {@link TrustManagerFactory}
    209      * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
    210      * no algorithm has been set using
    211      * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm
    212      * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used.
    213      * The default value of this property is <tt>true<tt/>.
    214      *
    215      * @param useDefault <code>true</code> or <code>false</code>.
    216      */
    217     public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) {
    218         this.trustManagerFactoryAlgorithmUseDefault = useDefault;
    219     }
    220
    221     /**
    222      * Sets the {@link KeyManagerFactory} to use. If this is set the properties
    223      * which are used by this factory bean to create a {@link KeyManagerFactory}
    224      * will all be ignored.
    225      *
    226      * @param factory the factory.
    227      */
    228     public void setKeyManagerFactory(KeyManagerFactory factory) {
    229         this.keyManagerFactory = factory;
    230     }
    231
    232     /**
    233      * Sets the algorithm to use when creating the {@link KeyManagerFactory}
    234      * using {@link KeyManagerFactory#getInstance(java.lang.String)} or
    235      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    236      * <p>
    237      * This property will be ignored if a {@link KeyManagerFactory} has been
    238      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
    239      * </p>
    240      * <p>
    241      * If this property isn't set while no {@link KeyManagerFactory} has been
    242      * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
    243      * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to
    244      * <code>true</code> the value returned
    245      * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead.
    246      * </p>
    247      *
    248      * @param algorithm the algorithm to use.
    249      */
    250     public void setKeyManagerFactoryAlgorithm(String algorithm) {
    251         this.keyManagerFactoryAlgorithm = algorithm;
    252     }
    253
    254     /**
    255      * Sets the provider to use when creating the {@link KeyManagerFactory}
    256      * using
    257      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    258      * <p>
    259      * This property will be ignored if a {@link KeyManagerFactory} has been
    260      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
    261      * </p>
    262      * <p>
    263      * If this property isn't set and no {@link KeyManagerFactory} has been set
    264      * using {@link #setKeyManagerFactory(KeyManagerFactory)}
    265      * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used
    266      * to create the {@link KeyManagerFactory}.
    267      * </p>
    268      *
    269      * @param provider the name of the provider.
    270      */
    271     public void setKeyManagerFactoryProvider(String provider) {
    272         this.keyManagerFactoryProvider = provider;
    273     }
    274
    275     /**
    276      * Sets the {@link KeyStore} which will be used in the call to
    277      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
    278      * the {@link SSLContext} is created.
    279      *
    280      * @param keyStore the key store.
    281      */
    282     public void setKeyManagerFactoryKeyStore(KeyStore keyStore) {
    283         this.keyManagerFactoryKeyStore = keyStore;
    284     }
    285
    286     /**
    287      * Sets the password which will be used in the call to
    288      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
    289      * the {@link SSLContext} is created.
    290      *
    291      * @param password the password. Use <code>null</code> to disable password.
    292      */
    293     public void setKeyManagerFactoryKeyStorePassword(String password) {
    294         if (password != null) {
    295             this.keyManagerFactoryKeyStorePassword = password.toCharArray();
    296         } else {
    297             this.keyManagerFactoryKeyStorePassword = null;
    298         }
    299     }
    300
    301     /**
    302      * Sets the {@link TrustManagerFactory} to use. If this is set the
    303      * properties which are used by this factory bean to create a
    304      * {@link TrustManagerFactory} will all be ignored.
    305      *
    306      * @param factory
    307      *            the factory.
    308      */
    309     public void setTrustManagerFactory(TrustManagerFactory factory) {
    310         this.trustManagerFactory = factory;
    311     }
    312
    313     /**
    314      * Sets the algorithm to use when creating the {@link TrustManagerFactory}
    315      * using {@link TrustManagerFactory#getInstance(java.lang.String)} or
    316      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    317      * <p>
    318      * This property will be ignored if a {@link TrustManagerFactory} has been
    319      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
    320      * </p>
    321      * <p>
    322      * If this property isn't set while no {@link TrustManagerFactory} has been
    323      * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
    324      * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to
    325      * <code>true</code> the value returned
    326      * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead.
    327      * </p>
    328      *
    329      * @param algorithm the algorithm to use.
    330      */
    331     public void setTrustManagerFactoryAlgorithm(String algorithm) {
    332         this.trustManagerFactoryAlgorithm = algorithm;
    333     }
    334
    335     /**
    336      * Sets the {@link KeyStore} which will be used in the call to
    337      * {@link TrustManagerFactory#init(java.security.KeyStore)} when
    338      * the {@link SSLContext} is created.
    339      * <p>
    340      * This property will be ignored if {@link ManagerFactoryParameters} has been
    341      * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}.
    342      * </p>
    343      *
    344      * @param keyStore the key store.
    345      */
    346     public void setTrustManagerFactoryKeyStore(KeyStore keyStore) {
    347         this.trustManagerFactoryKeyStore = keyStore;
    348     }
    349
    350     /**
    351      * Sets the {@link ManagerFactoryParameters} which will be used in the call to
    352      * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when
    353      * the {@link SSLContext} is created.
    354      *
    355      * @param parameters describing provider-specific trust material.
    356      */
    357     public void setTrustManagerFactoryParameters(ManagerFactoryParameters parameters) {
    358         this.trustManagerFactoryParameters = parameters;
    359     }
    360
    361     /**
    362      * Sets the provider to use when creating the {@link TrustManagerFactory}
    363      * using
    364      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
    365      * <p>
    366      * This property will be ignored if a {@link TrustManagerFactory} has been
    367      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
    368      * </p>
    369      * <p>
    370      * If this property isn't set and no {@link TrustManagerFactory} has been set
    371      * using {@link #setTrustManagerFactory(TrustManagerFactory)}
    372      * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used
    373      * to create the {@link TrustManagerFactory}.
    374      * </p>
    375      *
    376      * @param provider the name of the provider.
    377      */
    378     public void setTrustManagerFactoryProvider(String provider) {
    379         this.trustManagerFactoryProvider = provider;
    380     }
    381
    382     /**
    383      * Sets the {@link SecureRandom} to use when initializing the
    384      * {@link SSLContext}. The JVM's default will be used if this isn't set.
    385      *
    386      * @param secureRandom the {@link SecureRandom} or <code>null</code> if the
    387      *        JVM's default should be used.
    388      * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
    389      */
    390     public void setSecureRandom(SecureRandom secureRandom) {
    391         this.secureRandom = secureRandom;
    392     }
    393
    394     /**
    395      * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode.
    396      *
    397      * @param size the new session cache size limit; zero means there is no limit.
    398      * @see SSLSessionContext#setSessionCacheSize(int size)
    399      */
    400     public void setClientSessionCacheSize(int size) {
    401         this.clientSessionCacheSize = size;
    402     }
    403
    404     /**
    405      * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode.
    406      *
    407      * @param seconds the new session timeout limit in seconds; zero means there is no limit.
    408      * @see SSLSessionContext#setSessionTimeout(int seconds)
    409      */
    410     public void setClientSessionTimeout(int seconds) {
    411         this.clientSessionTimeout = seconds;
    412     }
    413
    414     /**
    415      * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode.
    416      *
    417      * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit.
    418      * @see SSLSessionContext#setSessionCacheSize(int)
    419      */
    420     public void setServerSessionCacheSize(int serverSessionCacheSize) {
    421         this.serverSessionCacheSize = serverSessionCacheSize;
    422     }
    423
    424     /**
    425      * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode.
    426      *
    427      * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit.
    428      * @see SSLSessionContext#setSessionTimeout(int)
    429      */
    430     public void setServerSessionTimeout(int serverSessionTimeout) {
    431         this.serverSessionTimeout = serverSessionTimeout;
    432     }
    433 }