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.geronimo.console.keystores;
018    
019    import java.io.ByteArrayInputStream;
020    import java.io.InputStream;
021    import java.io.Serializable;
022    import java.security.cert.Certificate;
023    import java.security.cert.CertificateFactory;
024    import java.security.cert.X509Certificate;
025    import java.util.Collection;
026    import java.util.HashMap;
027    import java.util.Map;
028    
029    import javax.portlet.ActionResponse;
030    import javax.portlet.PortletRequest;
031    import javax.portlet.PortletSession;
032    
033    import org.apache.commons.logging.Log;
034    import org.apache.commons.logging.LogFactory;
035    import org.apache.geronimo.console.MultiPageAbstractHandler;
036    import org.apache.geronimo.console.MultiPageModel;
037    import org.apache.geronimo.management.geronimo.KeystoreException;
038    import org.apache.geronimo.management.geronimo.KeystoreInstance;
039    import org.apache.geronimo.crypto.CertificateUtil;
040    
041    /**
042     * The base class for all handlers for this portlet
043     *
044     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
045     */
046    public abstract class BaseKeystoreHandler extends MultiPageAbstractHandler {
047        private final static Log log = LogFactory.getLog(BaseKeystoreHandler.class);
048        protected static final String KEYSTORE_DATA_PREFIX="org.apache.geronimo.keystore.";
049        protected static final String LIST_MODE = "list";
050        protected static final String UNLOCK_KEYSTORE_FOR_EDITING = "unlockEdit";
051        protected static final String UNLOCK_KEYSTORE_FOR_USAGE = "unlockKeystore";
052        protected static final String UNLOCK_KEY = "unlockKey";
053        protected static final String LOCK_KEYSTORE_FOR_EDITING = "lockEdit";
054        protected static final String LOCK_KEYSTORE_FOR_USAGE = "lockKeystore";
055        protected static final String CREATE_KEYSTORE = "createKeystore";
056        protected static final String VIEW_KEYSTORE = "viewKeystore";
057        protected static final String UPLOAD_CERTIFICATE = "uploadCertificate";
058        protected static final String CONFIRM_CERTIFICATE = "confirmCertificate";
059        protected static final String CONFIGURE_KEY = "configureKey";
060        protected static final String CONFIRM_KEY = "confirmKey";
061        protected static final String CERTIFICATE_DETAILS = "certificateDetails";
062        protected static final String GENERATE_CSR = "generateCSR";
063        protected static final String IMPORT_CA_REPLY = "importCAReply";
064        protected static final String DELETE_ENTRY = "deleteEntry";
065        protected static final String CHANGE_PASSWORD = "changePassword";
066    
067        // Name of the attribute for error message to be displayed in a page
068        protected static final String ERROR_MSG = "errorMsg";
069        // Name of the attribute for information message to be displayed in a page
070        protected static final String INFO_MSG = "infoMsg";
071        
072    
073        protected BaseKeystoreHandler(String mode, String viewName) {
074            super(mode, viewName);
075        }
076    
077        public final static class KeystoreModel implements MultiPageModel {
078            public KeystoreModel(PortletRequest request) {
079            }
080    
081            public void save(ActionResponse response, PortletSession session) {
082            }
083        }
084    
085        public final static class KeystoreData implements Serializable {
086            private transient KeystoreInstance instance;
087            private char[] password;
088            private String[] certificates;
089            private String[] keys;
090            private Map fingerprints;
091            private Map keyPasswords;
092    
093            public String getName() {
094                return instance.getKeystoreName();
095            }
096            
097            public String getType() {
098                return instance.getKeystoreType();
099            }
100    
101            public KeystoreInstance getInstance() {
102                return instance;
103            }
104    
105            public void setInstance(KeystoreInstance instance) {
106                this.instance = instance;
107            }
108    
109            public boolean isLockedEdit() {
110                return password == null;
111            }
112            
113            public boolean isLockedUse() {
114                return instance.isKeystoreLocked();
115            }
116    
117            public String[] getCertificates() {
118                return certificates;
119            }
120    
121            public String[] getKeys() {
122                return keys;
123            }
124    
125            public Map getFingerprints() throws KeystoreException {
126                if(fingerprints == null) {
127                    fingerprints = new HashMap();
128                    for (int i = 0; i < certificates.length; i++) {
129                        String alias = certificates[i];
130                        try {
131                            fingerprints.put(alias, CertificateUtil.generateFingerprint(instance.getCertificate(alias, password), "MD5"));
132                        } catch (Exception e) {
133                            log.error("Unable to generate certificate fingerprint", e);
134                        }
135                    }
136                    for (int i = 0; i < keys.length; i++) {
137                        String alias = keys[i];
138                        try {
139                            fingerprints.put(alias, CertificateUtil.generateFingerprint(instance.getCertificate(alias, password), "MD5"));
140                        } catch (Exception e) {
141                            log.error("Unable to generate certificate fingerprint", e);
142                        }
143                    }
144                }
145                return fingerprints;
146            }
147            
148            public void importTrustCert(String fileName, String alias) throws KeystoreException {
149                try {
150                    // Uploading certificate using a disk file fails on Windows.  Certificate text is used instead.
151                    //InputStream is = new FileInputStream(fileName);
152                    InputStream is = new ByteArrayInputStream(fileName.getBytes());
153                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
154                    Collection certs = cf.generateCertificates(is);
155                    X509Certificate cert = (X509Certificate) certs.iterator().next();
156                    instance.importTrustCertificate(cert, alias, password);
157                    String[] update = new String[certificates.length+1];
158                    System.arraycopy(certificates, 0, update, 0, certificates.length);
159                    update[certificates.length] = alias;
160                    certificates = update;
161                    if (fingerprints != null) {
162                        fingerprints.put(alias, CertificateUtil.generateFingerprint(instance.getCertificate(alias, password), "MD5"));
163                    }
164                } catch (KeystoreException e) {
165                    throw e;
166                } catch (Exception e) {
167                    throw new KeystoreException("Unable to import trust certificate", e);
168                }
169            }
170    
171            public void createKeyPair(String alias, String keyPassword, String keyAlgorithm, int keySize,
172                                         String signatureAlgorithm, int validity, String commonName, String orgUnit,
173                                         String organization, String locality, String state, String country) throws KeystoreException {
174                try {
175                    instance.generateKeyPair(alias, password, keyPassword.toCharArray(), keyAlgorithm, keySize,
176                                             signatureAlgorithm, validity, commonName, orgUnit, organization, locality, state, country);
177                    String[] update = new String[keys.length+1];
178                    System.arraycopy(keys, 0, update, 0, keys.length);
179                    update[keys.length] = alias;
180                    keys = update;
181                    if (fingerprints != null) {
182                        fingerprints.put(alias, CertificateUtil.generateFingerprint(instance.getCertificate(alias, password), "MD5"));
183                    }
184                } catch (KeystoreException e) {
185                    throw e;
186                } catch (Exception e) {
187                    throw new KeystoreException("Unable to create key pair", e);
188                }
189            }
190    
191            public Certificate getCertificate(String alias) throws KeystoreException {
192                return instance.getCertificate(alias, password);
193            }
194    
195            public void unlockPrivateKey(String alias, char[] keyPassword) throws KeystoreException {
196                if(keyPasswords == null) {
197                    keyPasswords = new HashMap();
198                }
199                instance.unlockPrivateKey(alias, password, keyPassword);
200                keyPasswords.put(alias, keyPassword);
201            }
202    
203            public void deleteEntry(String alias) throws KeystoreException {
204                for(int i = 0; i < keys.length; ++i) {
205                    if(keys[i].equals(alias)) {
206                        String[] temp = new String[keys.length-1];
207                        for(int j = 0; j < i; ++j) {
208                            temp[j] = keys[j];
209                        }
210                        for(int j = i+1; j < keys.length; ++j) {
211                            temp[j-1] = keys[j];
212                        }
213                        keys = temp;
214                        break;
215                    }
216                }
217    
218                for(int i = 0; i < certificates.length; ++i) {
219                    if(certificates[i].equals(alias)) {
220                        String[] temp = new String[certificates.length-1];
221                        for(int j = 0; j < i; ++j) {
222                            temp[j] = certificates[j];
223                        }
224                        for(int j = i+1; j < certificates.length; ++j) {
225                            temp[j-1] = certificates[j];
226                        }
227                        certificates = temp;
228                        break;
229                    }
230                }
231                instance.deleteEntry(alias, password);
232                if(keyPasswords != null)
233                    keyPasswords.remove(alias);
234                if(fingerprints != null)
235                    fingerprints.remove(alias);
236            }
237    
238                    public void importPKCS7Certificate(String alias, String pkcs7cert) throws KeystoreException {
239                            try {
240                                    instance.importPKCS7Certificate(alias, pkcs7cert, password);
241                                    fingerprints.put(alias, CertificateUtil.generateFingerprint(instance.getCertificate(alias, password), "MD5"));
242                } catch (KeystoreException e) {
243                    throw e;
244                } catch (Exception e) {
245                    throw new KeystoreException("Unable to import PKCS7 certificate", e);
246                            }
247                    }
248            
249            public String generateCSR(String alias) throws KeystoreException {
250                return instance.generateCSR(alias, password);
251            }
252    
253            public void unlockEdit(char[] password) throws KeystoreException {
254                this.certificates = instance.listTrustCertificates(password);
255                this.keys = instance.listPrivateKeys(password);
256                // Set password last, so that if an error occurs, the keystore
257                // still appears locked (lockedEdit == false)
258                this.password = password;
259                this.fingerprints = null;
260            }
261            
262            public void lockEdit() {
263                this.password = null;
264                this.certificates = null;
265                this.keyPasswords = null;
266                this.keys = null;
267                this.fingerprints = null;
268            }
269            
270            public void lockUse() throws KeystoreException {
271                instance.lockKeystore(password);
272            }
273            
274            public void unlockUse(char[] password) throws KeystoreException {
275                instance.unlockKeystore(password);
276            }
277            
278            public void changeKeystorePassword(char[] oldPassword, char[] newPassword) throws KeystoreException {
279                instance.changeKeystorePassword(oldPassword, newPassword);
280                this.password = newPassword;
281            }
282    
283            public void changeKeyPassword(String alias, char[] keyPassword, char[] newKeyPassword) throws KeystoreException {
284                instance.changeKeyPassword(alias, password, keyPassword, newKeyPassword);
285                if(keyPasswords != null && keyPasswords.containsKey(alias)) {
286                    keyPasswords.put(alias, newKeyPassword);
287                }
288            }
289        }
290    }