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     */
017    package org.apache.camel.util.jsse;
018    
019    import java.io.IOException;
020    import java.security.GeneralSecurityException;
021    import java.security.KeyStore;
022    import java.security.Security;
023    
024    import javax.net.ssl.KeyManager;
025    import javax.net.ssl.KeyManagerFactory;
026    
027    import org.slf4j.Logger;
028    import org.slf4j.LoggerFactory;
029    
030    /**
031     * A representation of configuration options for creating and loading
032     * {@link KeyManager} instance(s).
033     */
034    public 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    }