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