Coverage Report - org.kuali.rice.ksb.security.admin.service.impl.JavaSecurityManagementServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
JavaSecurityManagementServiceImpl
0%
0/118
0%
0/28
2.333
 
 1  
 /*
 2  
  * Copyright 2006-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.kuali.rice.ksb.security.admin.service.impl;
 18  
 
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.bouncycastle.jce.X509Principal;
 21  
 import org.bouncycastle.x509.X509V3CertificateGenerator;
 22  
 import org.kuali.rice.core.api.config.property.Config;
 23  
 import org.kuali.rice.core.api.config.property.ConfigContext;
 24  
 import org.kuali.rice.ksb.security.admin.KeyStoreEntryDataContainer;
 25  
 import org.kuali.rice.ksb.security.admin.service.JavaSecurityManagementService;
 26  
 import org.springframework.beans.factory.InitializingBean;
 27  
 
 28  
 import java.io.File;
 29  
 import java.io.FileInputStream;
 30  
 import java.io.IOException;
 31  
 import java.security.GeneralSecurityException;
 32  
 import java.security.KeyPair;
 33  
 import java.security.KeyPairGenerator;
 34  
 import java.security.KeyStore;
 35  
 import java.security.KeyStoreException;
 36  
 import java.security.NoSuchAlgorithmException;
 37  
 import java.security.PrivateKey;
 38  
 import java.security.Security;
 39  
 import java.security.UnrecoverableEntryException;
 40  
 import java.security.cert.Certificate;
 41  
 import java.util.ArrayList;
 42  
 import java.util.Calendar;
 43  
 import java.util.Date;
 44  
 import java.util.Enumeration;
 45  
 import java.util.List;
 46  
 
 47  
 /**
 48  
  * This is an implementation of the {@link JavaSecurityManagementService} interface used by the KSB module 
 49  
  * 
 50  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 51  
  *
 52  
  */
 53  0
 public class JavaSecurityManagementServiceImpl implements JavaSecurityManagementService, InitializingBean {
 54  
 
 55  0
     protected final String CLIENT_KEY_GENERATOR_ALGORITHM = "RSA";
 56  0
     protected final String CLIENT_SECURE_RANDOM_ALGORITHM = "SHA1PRNG";
 57  0
     protected final int CLIENT_KEY_PAIR_KEY_SIZE = 512;
 58  0
     private final int CLIENT_CERT_EXPIRATION_DAYS = 9999;
 59  
 
 60  
     private static final String MODULE_SHA_RSA_ALGORITHM = "SHA1withRSA";
 61  
     private static final String MODULE_JKS_TYPE = "JKS";
 62  
 
 63  
     private String moduleKeyStoreLocation;
 64  
     private String moduleKeyStoreAlias;
 65  
     private String moduleKeyStorePassword;
 66  
 
 67  
     private KeyStore moduleKeyStore;
 68  
     private PrivateKey modulePrivateKey;
 69  
 
 70  
     /**
 71  
      * Load the module's keystore and private key for this "application"
 72  
      */
 73  
     public void afterPropertiesSet() throws Exception {
 74  0
         if (StringUtils.isEmpty(getModuleKeyStoreLocation())) {
 75  0
             setModuleKeyStoreLocation(ConfigContext.getCurrentContextConfig().getKeystoreFile());
 76  
         }
 77  0
         if (StringUtils.isEmpty(getModuleKeyStoreAlias())) {
 78  0
             setModuleKeyStoreAlias(ConfigContext.getCurrentContextConfig().getKeystoreAlias());
 79  
         }
 80  0
         if (StringUtils.isEmpty(getModuleKeyStorePassword())) {
 81  0
             setModuleKeyStorePassword(ConfigContext.getCurrentContextConfig().getKeystorePassword());
 82  
         }
 83  0
         verifyConfiguration();
 84  0
         this.moduleKeyStore = loadKeyStore();
 85  0
         this.modulePrivateKey = loadPrivateKey();
 86  0
     }
 87  
 
 88  
     /**
 89  
      * Verifies the configuration of this service and throws an exception if it is not configured properly.
 90  
      */
 91  
     protected void verifyConfiguration() {
 92  0
         if (StringUtils.isEmpty(getModuleKeyStoreLocation())) {
 93  0
             throw new RuntimeException("Value for configuration parameter '" + Config.KEYSTORE_FILE + "' could not be found.  Please ensure that the keystore is configured properly.");
 94  
         }
 95  0
         if (StringUtils.isEmpty(getModuleKeyStoreAlias())) {
 96  0
             throw new RuntimeException("Value for configuration parameter '" + Config.KEYSTORE_ALIAS + "' could not be found.  Please ensure that the keystore is configured properly.");
 97  
         }
 98  0
         if (StringUtils.isEmpty(getModuleKeyStorePassword())) {
 99  0
             throw new RuntimeException("Value for configuration parameter '" + Config.KEYSTORE_PASSWORD + "' could not be found.  Please ensure that the keystore is configured properly.");
 100  
         }
 101  0
         File keystoreFile = new File(getModuleKeyStoreLocation());
 102  0
         if (!keystoreFile.exists()) {
 103  0
             throw new RuntimeException("Value for configuration parameter '" + Config.KEYSTORE_FILE + "' is invalid.  The file does not exist on the filesystem, location was: '" + getModuleKeyStoreLocation() + "'");
 104  
         }
 105  0
         if (!keystoreFile.canRead()) {
 106  0
             throw new RuntimeException("Value for configuration parameter '" + Config.KEYSTORE_FILE + "' is invalid.  The file exists but is not readable (please check permissions), location was: '" + getModuleKeyStoreLocation() + "'");
 107  
         }
 108  0
     }
 109  
 
 110  
     protected KeyStore loadKeyStore() throws GeneralSecurityException, IOException {
 111  0
         KeyStore keyStore = KeyStore.getInstance(getModuleKeyStoreType());
 112  0
         FileInputStream stream = null;
 113  
         try {
 114  0
             stream = new FileInputStream(getModuleKeyStoreLocation());
 115  0
             keyStore.load(stream, getModuleKeyStorePassword().toCharArray());
 116  0
             stream.close();
 117  0
         } catch (Exception e) {
 118  0
             if (stream != null) {
 119  
                 try {
 120  0
                     stream.close();
 121  0
                 } catch (Exception ignored) {
 122  0
                 }
 123  
             }
 124  0
         }
 125  0
         return keyStore;
 126  
     }
 127  
 
 128  
     protected PrivateKey loadPrivateKey() throws GeneralSecurityException {
 129  0
         return (PrivateKey)getModuleKeyStore().getKey(getModuleKeyStoreAlias(), getModuleKeyStorePassword().toCharArray());
 130  
     }
 131  
 
 132  
     public void removeClientCertificate(String alias) throws KeyStoreException {
 133  0
         KeyStore moduleKeyStore = getModuleKeyStore();
 134  0
         if (!moduleKeyStore.entryInstanceOf(alias, KeyStore.TrustedCertificateEntry.class)) {
 135  0
             throw new RuntimeException("Only entries of type " + KeyStoreEntryDataContainer.DISPLAYABLE_ENTRY_TYPES.get(KeyStore.TrustedCertificateEntry.class) + " can be removed");
 136  
         }
 137  0
         getModuleKeyStore().deleteEntry(alias);
 138  0
     }
 139  
     
 140  
     protected void addClientCertificateToModuleKeyStore(String alias, Certificate clientCertificate) throws KeyStoreException {
 141  0
         getModuleKeyStore().setEntry(alias, new KeyStore.TrustedCertificateEntry(clientCertificate), null);
 142  0
     }
 143  
     
 144  
     public boolean isAliasInKeystore(String alias) throws KeyStoreException {
 145  0
         return getModuleKeyStore().containsAlias(alias);
 146  
     }
 147  
     
 148  
     public String getCertificateAlias(Certificate certificate) throws KeyStoreException {
 149  0
         return getModuleKeyStore().getCertificateAlias(certificate);
 150  
     }
 151  
     
 152  
     public KeyStore generateClientKeystore(String alias, String clientPassphrase) throws GeneralSecurityException {
 153  0
         if (isAliasInKeystore(alias)) {
 154  0
             throw new KeyStoreException("Alias '" + alias + "' already exists in module keystore");
 155  
         }
 156  
 //        Certificate[] clientCertificateChain = {};
 157  
 //        PrivateKey clientPrivateKey = null;
 158  0
         KeyStore ks = null;
 159  
         try {
 160  
             // generate a key pair for the client
 161  0
             KeyPairGenerator keyGen = KeyPairGenerator.getInstance(CLIENT_KEY_GENERATOR_ALGORITHM);
 162  
 //            SecureRandom random = SecureRandom.getInstance(CLIENT_SECURE_RANDOM_ALGORITHM);
 163  0
             keyGen.initialize(CLIENT_KEY_PAIR_KEY_SIZE);
 164  
 //            keyGen.initialize(new RSAKeyGenParameterSpec(512,RSAKeyGenParameterSpec.F0));
 165  0
             KeyPair pair = keyGen.generateKeyPair();
 166  
 
 167  
 //            PublicKey clientPublicKey = pair.getPublic();
 168  
 //            clientPrivateKey = pair.getPrivate();
 169  
 //            // generate the Certificate
 170  
 //            X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
 171  
 ////            X509Name nameInfo = new X509Name(false,"CN=" + alias);
 172  
 //            certificateGenerator.setSignatureAlgorithm("MD5WithRSA");
 173  
 //            certificateGenerator.setSerialNumber(new java.math.BigInteger("1"));
 174  
 //            X509Principal nameInfo = new X509Principal("CN=" + alias);
 175  
 //            certificateGenerator.setIssuerDN(nameInfo);
 176  
 //            certificateGenerator.setSubjectDN(nameInfo);                       // note: same as issuer
 177  
 //            certificateGenerator.setNotBefore(new Date());
 178  
 //            Calendar c = Calendar.getInstance();
 179  
 //            c.add(Calendar.DATE, CLIENT_CERT_EXPIRATION_DAYS);
 180  
 //            certificateGenerator.setNotAfter(c.getTime());
 181  
 //            certificateGenerator.setPublicKey(clientPublicKey);
 182  
 //            X509Certificate cert = certificateGenerator.generateX509Certificate(clientPrivateKey);
 183  
 //            clientCertificateChain = new Certificate[]{cert};
 184  
 //
 185  
 //            // generate client keyStore file
 186  
 //            ks = KeyStore.getInstance(getModuleKeyStoreType());
 187  
 //            ks.load(null, clientPassphrase.toCharArray());
 188  
 //            // set client private key on keyStore file
 189  
 //            ks.setEntry(alias, new KeyStore.PrivateKeyEntry(clientPrivateKey, clientCertificateChain), new KeyStore.PasswordProtection(clientPassphrase.toCharArray()));
 190  0
             Certificate cert = generateCertificate(pair, alias);
 191  0
             ks = generateKeyStore(cert, pair.getPrivate(), alias, clientPassphrase);
 192  
             
 193  
             // set the module certificate on the client keyStore file
 194  0
             ks.setEntry(getModuleKeyStoreAlias(), new KeyStore.TrustedCertificateEntry(getCertificate(getModuleKeyStoreAlias())),  null);
 195  
 
 196  
             // add the client certificate to the module keyStore
 197  0
             addClientCertificateToModuleKeyStore(alias, cert);
 198  
             
 199  0
             return ks;
 200  0
         } catch (IOException e) {
 201  0
             throw new RuntimeException("Could not create new KeyStore",e);
 202  
         }
 203  
     }
 204  
     
 205  
     protected Certificate generateCertificate(KeyPair keyPair, String alias) throws GeneralSecurityException {
 206  
       
 207  
       //test that Bouncy Castle provider is present and add it if it's not
 208  0
       if( Security.getProvider(org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) == null) {
 209  0
               Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
 210  
       }
 211  0
       X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
 212  
 //      X509Name nameInfo = new X509Name(false,"CN=" + alias);
 213  0
       certificateGenerator.setSignatureAlgorithm("MD5WithRSA");
 214  0
       certificateGenerator.setSerialNumber(new java.math.BigInteger("1"));
 215  0
       X509Principal nameInfo = new X509Principal("CN=" + alias);
 216  0
       certificateGenerator.setIssuerDN(nameInfo);
 217  0
       certificateGenerator.setSubjectDN(nameInfo);  // note: same as issuer for self signed
 218  0
       certificateGenerator.setNotBefore(new Date());
 219  0
       Calendar c = Calendar.getInstance();
 220  0
       c.add(Calendar.DATE, CLIENT_CERT_EXPIRATION_DAYS);
 221  0
       certificateGenerator.setNotAfter(c.getTime());
 222  0
       certificateGenerator.setPublicKey(keyPair.getPublic());
 223  0
       return certificateGenerator.generate(keyPair.getPrivate(), org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME);
 224  
     }
 225  
     
 226  
     protected KeyStore generateKeyStore(Certificate cert, PrivateKey privateKey, String alias, String keyStorePassword) throws GeneralSecurityException, IOException {
 227  0
         KeyStore ks = KeyStore.getInstance(getModuleKeyStoreType());
 228  0
         ks.load(null, keyStorePassword.toCharArray());
 229  
         // set client private key on keyStore file
 230  0
         ks.setEntry(alias, new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{cert}), new KeyStore.PasswordProtection(keyStorePassword.toCharArray()));
 231  0
         return ks;
 232  
     }
 233  
 
 234  
     public List<KeyStoreEntryDataContainer> getListOfModuleKeyStoreEntries() {
 235  0
         List<KeyStoreEntryDataContainer> keyStoreEntries = new ArrayList<KeyStoreEntryDataContainer>();
 236  
         try {
 237  0
             KeyStore moduleKeyStore = getModuleKeyStore();
 238  
 
 239  
             // List the aliases
 240  0
             for (Enumeration<String> enumer = moduleKeyStore.aliases(); enumer.hasMoreElements();) {
 241  0
                 String alias = (String) enumer.nextElement();
 242  0
                 KeyStoreEntryDataContainer dataContainer = new KeyStoreEntryDataContainer(alias,moduleKeyStore.getCreationDate(alias));
 243  0
                 KeyStore.PasswordProtection passwordProtection = null;
 244  0
                 if (moduleKeyStore.isKeyEntry(alias)) {
 245  0
                     passwordProtection = new KeyStore.PasswordProtection(getModuleKeyStorePassword().toCharArray());
 246  
                 }
 247  0
                 KeyStore.Entry entry = moduleKeyStore.getEntry(alias, passwordProtection);
 248  0
                 dataContainer.setType(entry.getClass());
 249  0
                 keyStoreEntries.add(dataContainer);
 250  0
             }
 251  0
         } catch (KeyStoreException e) {
 252  0
             e.printStackTrace();
 253  0
             throw new RuntimeException(e);
 254  0
         } catch (NoSuchAlgorithmException e) {
 255  0
             e.printStackTrace();
 256  0
             throw new RuntimeException(e);
 257  0
         } catch (UnrecoverableEntryException e) {
 258  0
             e.printStackTrace();
 259  0
             throw new RuntimeException(e);
 260  0
         }
 261  0
         return keyStoreEntries;
 262  
     }
 263  
 
 264  
     public String getModuleSignatureAlgorithm() {
 265  0
         return getModuleAlgorithm();
 266  
     }
 267  
 
 268  
     /**
 269  
      * @see java.security.KeyStore#getCertificate(java.lang.String)
 270  
      */
 271  
     public Certificate getCertificate(String alias) throws KeyStoreException {
 272  0
         return getModuleKeyStore().getCertificate(alias);
 273  
     }
 274  
     
 275  
     protected String getModuleKeyStoreType() {
 276  0
         return MODULE_JKS_TYPE;
 277  
     }
 278  
 
 279  
     protected String getModuleAlgorithm() {
 280  0
         return MODULE_SHA_RSA_ALGORITHM;
 281  
     }
 282  
 
 283  
     public String getModuleKeyStoreLocation() {
 284  0
         return this.moduleKeyStoreLocation;
 285  
     }
 286  
 
 287  
     public void setModuleKeyStoreLocation(String moduleKeyStoreLocation) {
 288  0
         this.moduleKeyStoreLocation = moduleKeyStoreLocation;
 289  0
     }
 290  
 
 291  
     public String getModuleKeyStoreAlias() {
 292  0
         return this.moduleKeyStoreAlias;
 293  
     }
 294  
 
 295  
     public void setModuleKeyStoreAlias(String moduleKeyStoreAlias) {
 296  0
         this.moduleKeyStoreAlias = moduleKeyStoreAlias;
 297  0
     }
 298  
 
 299  
     public String getModuleKeyStorePassword() {
 300  0
         return this.moduleKeyStorePassword;
 301  
     }
 302  
 
 303  
     public void setModuleKeyStorePassword(String moduleKeyStorePassword) {
 304  0
         this.moduleKeyStorePassword = moduleKeyStorePassword;
 305  0
     }
 306  
 
 307  
     public KeyStore getModuleKeyStore() {
 308  0
         return this.moduleKeyStore;
 309  
     }
 310  
     
 311  
     public PrivateKey getModulePrivateKey() {
 312  0
         return this.modulePrivateKey;
 313  
     }
 314  
     
 315  
 }