001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.util.jsse;
018
019import java.io.IOException;
020import java.security.GeneralSecurityException;
021import java.security.KeyStore;
022import java.security.Security;
023
024import javax.net.ssl.KeyManager;
025import javax.net.ssl.KeyManagerFactory;
026
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029
030/**
031 * A representation of configuration options for creating and loading
032 * {@link KeyManager} instance(s).
033 */
034public class KeyManagersParameters extends JsseParameters {
035
036    private static final Logger LOG = LoggerFactory.getLogger(KeyManagersParameters.class);
037
038    /**
039     * The key store configuration used to create the {@link KeyStoreParameters} that the
040     * {@link KeyManager}s produced by this object's configuration expose.
041     */
042    protected KeyStoreParameters keyStore;
043    
044    /**
045     * The optional password for recovering keys in the key store. Used by the
046     * {@link KeyManagerFactory} that creates the {@link KeyManager}s
047     * represented by this object's configuration.
048     */
049    protected String keyPassword;
050    
051    /**
052     * The optional provider identifier for the {@link KeyManagerFactory} used to create
053     * the {@link KeyManager}s represented by this object's configuration.
054     */
055    protected String provider;
056    
057    /**
058     * The optional algorithm name for the {@link KeyManagerFactory} used to create
059     * the {@link KeyManager}s represented by this object's configuration.  See the <a href=
060     * "http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html"
061     * >Java Secure Socket Extension Reference Guide</a> for information about
062     * standard algorithm names.
063     */
064    protected String algorithm;
065
066    /**
067     * Creates {@link KeyManager}s based on this instance's configuration and the
068     * {@code KeyStore} produced by the configuration returned from
069     * {@link #getKeyStore()}. The {@code KeyManager}s are produced from a
070     * factory created by using the provider and algorithm identifiers returned
071     * by {@link #getProvider()} and {@link #getAlgorithm()}, respectively. If
072     * either of these methods returns null, the default JSSE value is used
073     * instead.
074     * 
075     * @return the initialized {@code KeyManager}s
076     * @throws GeneralSecurityException if there is an error creating the
077     *             {@code KeyManager}s or in creating the {@code KeyStore}
078     * @throws IOException if there is an error loading the {@code KeyStore}
079     *
080     * @see KeyStoreParameters#createKeyStore()
081     */
082    public KeyManager[] createKeyManagers() throws GeneralSecurityException, IOException {
083        
084        LOG.trace("Creating KeyManager[] from KeyManagersParameters [{}].", this);
085
086        KeyManager[] keyManagers;
087        
088        String kmfAlgorithm = this.parsePropertyValue(this.getAlgorithm());
089        if (kmfAlgorithm == null) {
090            kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
091        }
092        
093        KeyManagerFactory kmf;
094        if (this.getProvider() == null) {
095            kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
096        } else {
097            kmf = KeyManagerFactory.getInstance(kmfAlgorithm, this.parsePropertyValue(this.getProvider()));
098        }
099        
100        LOG.debug("KeyManagerFactory [{}], initialized from [{}], is using provider [{}] and algorithm [{}].",
101                  new Object[] {kmf, this, kmf.getProvider(), kmf.getAlgorithm()});
102        
103        char[] kmfPassword = null;
104        if (this.getKeyPassword() != null) {
105            kmfPassword = this.parsePropertyValue(this.getKeyPassword()).toCharArray();
106        }
107        
108        KeyStore ks = this.getKeyStore() == null ? null : this.getKeyStore().createKeyStore();
109        
110        kmf.init(ks, kmfPassword);
111        keyManagers = kmf.getKeyManagers();
112        
113        LOG.debug("KeyManager[] [{}], initialized from KeyManagerFactory [{}].", keyManagers, kmf);
114        
115        return keyManagers;
116    }
117
118    /**
119     * @see #setKeyStore(KeyStoreParameters)
120     */
121    public KeyStoreParameters getKeyStore() {
122        return keyStore;
123    }
124
125    /**
126     * Sets the key store configuration used to create the {@link KeyStore} that the
127     * {@link KeyManager}s produced by this object's configuration expose.
128     * 
129     * @param value the configuration to use
130     */
131    public void setKeyStore(KeyStoreParameters value) {
132        this.keyStore = value;
133    }
134
135    /**
136     * @see #setKeyPassword(String)
137     */
138    public String getKeyPassword() {
139        return keyPassword;
140    }
141
142    /**
143     * Sets the optional password for recovering keys in the key store. Used by the
144     * {@link KeyManagerFactory} that creates the {@link KeyManager}s
145     * represented by this object's configuration.
146     *
147     * @param value the value to use
148     */
149    public void setKeyPassword(String value) {
150        this.keyPassword = value;
151    }
152
153    /**
154     * @see #setProvider(String)
155     */
156    public String getProvider() {
157        return provider;
158    }
159
160    /**
161     * Sets the optional provider identifier for the {@link KeyManagerFactory} used to create
162     * the {@link KeyManager}s represented by this object's configuration.
163     * 
164     * @param value the desired provider identifier or {@code null} to use the
165     *            highest priority provider implementing the algorithm
166     *
167     * @see Security#getProviders()
168     */
169    public void setProvider(String value) {
170        this.provider = value;
171    }
172
173    /**
174     * @see KeyManagerFactory#getDefaultAlgorithm()
175     */
176    public String getAlgorithm() {
177        return algorithm;
178    }
179
180    /**
181     * Sets optional algorithm name for the {@link KeyManagerFactory} used to create
182     * the {@link KeyManager}s represented by this object's configuration.  See the <a href=
183     * "http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html"
184     * >Java Secure Socket Extension Reference Guide</a> for information about
185     * standard algorithm names.
186     * 
187     * @param value the desired algorithm or {@code null} to use default
188     *
189     * @see KeyManagerFactory#getDefaultAlgorithm()
190     */
191    public void setAlgorithm(String value) {
192        this.algorithm = value;
193    }
194
195    @Override
196    public String toString() {
197        StringBuilder builder = new StringBuilder();
198        builder.append("KeyManagersParameters [keyStore=");
199        builder.append(keyStore);
200        builder.append(", keyPassword=");
201        builder.append("********");
202        builder.append(", provider=");
203        builder.append(provider);
204        builder.append(", algorithm=");
205        builder.append(algorithm);
206        builder.append(", getContext()=");
207        builder.append(getCamelContext());
208        builder.append("]");
209        return builder.toString();
210    }
211}