Package org.wso2.carbon.security.keystore

Source Code of org.wso2.carbon.security.keystore.KeyStoreAdmin

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you under the Apache License,
*  Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License.
*  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.security.keystore;

import org.apache.axiom.om.util.Base64;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.core.RegistryResources;
import org.wso2.carbon.core.util.CryptoUtil;
import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.core.util.KeyStoreUtil;
import org.wso2.carbon.registry.core.Association;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.security.SecurityConfigException;
import org.wso2.carbon.security.SecurityConstants;
import org.wso2.carbon.security.keystore.service.CertData;
import org.wso2.carbon.security.keystore.service.CertDataDetail;
import org.wso2.carbon.security.keystore.service.KeyStoreData;
import org.wso2.carbon.security.util.KeyStoreMgtUtil;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

public class KeyStoreAdmin {

  private Registry registry = null;

   
  private static Log log = LogFactory.getLog(KeyStoreAdmin.class);
 
  private boolean includeCert = false;
    private boolean isSuperTenant = true;

  public boolean isIncludeCert() {
    return includeCert;
  }

  public void setIncludeCert(boolean includeCert) {
    this.includeCert = includeCert;
  }

  public KeyStoreAdmin(Registry registry) {
    this.registry = registry;
        //Check whether it is the super tenant, used to deny permission for accessing the primary KS
        if(((UserRegistry)registry).getTenantId() != 0){
            isSuperTenant = false;
        }
  }

  public KeyStoreData[] getKeyStores() throws SecurityConfigException {
    KeyStoreData[] names = new KeyStoreData[0];
    try {
      if (registry.resourceExists(SecurityConstants.KEY_STORES)) {
        Collection collection = (Collection) registry.get(SecurityConstants.KEY_STORES);
        String[] ks = collection.getChildren();
        List<KeyStoreData> lst = new ArrayList<KeyStoreData>();
        for (int i = 0; i < ks.length; i++) {
          String fullname = ks[i];

          if (RegistryResources.SecurityManagement.PRIMARY_KEYSTORE_PHANTOM_RESOURCE
              .equals(fullname)) {
            continue;
          }

          Resource store = registry.get(ks[i]);
          int lastIndex = fullname.lastIndexOf("/");
          String name = fullname.substring(lastIndex + 1);
          String type = store.getProperty(SecurityConstants.PROP_TYPE);
          String provider = store.getProperty(SecurityConstants.PROP_PROVIDER);

          KeyStoreData data = new KeyStoreData();
          data.setKeyStoreName(name);
          data.setKeyStoreType(type);
          data.setProvider(provider);

          String alias = store.getProperty(SecurityConstants.PROP_PRIVATE_KEY_ALIAS);
          if (alias != null) {
            data.setPrivateStore(true);
          } else {
            data.setPrivateStore(false);
          }

                    // Dump the generated public key to the file system for sub tenants
                    if(!isSuperTenant){
                        Association[] associations = registry.getAssociations(
                                ks[i],SecurityConstants.ASSOCIATION_TENANT_KS_PUB_KEY);
                        if(associations != null && associations.length > 0){
                            Resource pubKeyResource = registry.get(associations[0].getDestinationPath());
                            String fileName = generatePubCertFileName(ks[i],
                                                                      pubKeyResource.getProperty(
                                                                              SecurityConstants.PROP_TENANT_PUB_KEY_FILE_NAME_APPENDER));
                            String pubKeyFilePath = KeyStoreMgtUtil.dumpCert(
                                    MessageContext.getCurrentMessageContext().getConfigurationContext(),
                                    (byte[])pubKeyResource.getContent(), fileName);
                            data.setPubKeyFilePath(pubKeyFilePath);
                        }
                    }
          lst.add(data);

        }
        names = new KeyStoreData[lst.size() + 1];
        Iterator<KeyStoreData> ite = lst.iterator();
        int count = 0;
        while (ite.hasNext()) {
          names[count] = ite.next();
          count++;
        }

                if (isSuperTenant) {
                    KeyStoreData data = new KeyStoreData();
                    ServerConfiguration config = ServerConfiguration.getInstance();
                    String fileName = config
                            .getFirstProperty(RegistryResources.SecurityManagement.SERVER_PRIMARY_KEYSTORE_FILE);
                    String type = config
                            .getFirstProperty(RegistryResources.SecurityManagement.SERVER_PRIMARY_KEYSTORE_TYPE);
                    String name = KeyStoreUtil.getKeyStoreFileName(fileName);
                    data.setKeyStoreName(name);
                    data.setKeyStoreType(type);
                    data.setProvider(" ");
                    data.setPrivateStore(true);

                    names[count] = data;
                }

            }
      return names;
    } catch (RegistryException e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage(), e);
    }
  }

  public void addKeyStoreWithFilePath(String filePath, String filename, String password,
      String provider, String type, String pvtkeyPass) throws SecurityConfigException {
    try {
      addKeyStore(readBytesFromFile(filePath), filename, password, provider, type, pvtkeyPass);
    } catch (IOException e) {
      throw new SecurityConfigException("Error while loading keystore from file " + filePath);
    }

  }

  public void addKeyStore(String fileData, String filename, String password, String provider,
      String type, String pvtkeyPass) throws SecurityConfigException {
    byte[] content = Base64.decode(fileData);
    addKeyStore(content, filename, password, provider, type, pvtkeyPass);
  }

  public void addKeyStore(byte[] content, String filename, String password, String provider,
      String type, String pvtkeyPass) throws SecurityConfigException {
    if (filename == null) {
      throw new SecurityConfigException("Key Store name can't be null");
    }
    try {
      if (KeyStoreUtil.isPrimaryStore(filename)) {
        throw new SecurityConfigException("Key store "+ filename + " already available");
      }

      String path = SecurityConstants.KEY_STORES + "/" + filename;
      if (registry.resourceExists(path)) {
        throw new SecurityConfigException("Key store "+ filename + " already available");
      }

      KeyStore keyStore = KeyStore.getInstance(type);
      keyStore.load(new ByteArrayInputStream(content), password.toCharArray());

      // check for more private keys
      Enumeration enumeration = keyStore.aliases();
      String pvtKeyAlias = null;
      while (enumeration.hasMoreElements()) {
        String alias = (String) enumeration.nextElement();
        if (keyStore.isKeyEntry(alias)) {
          if (pvtKeyAlias == null) {
            pvtKeyAlias = alias;
          } else {
            // more than one private key
            throw new SecurityConfigException("more than one private key");
          }
        }
      }

      // just to test weather pvt key password is correct.
      keyStore.getKey(pvtKeyAlias, pvtkeyPass.toCharArray());

      CryptoUtil cryptoUtil = CryptoUtil.getDefaultCryptoUtil();

      Resource resource = registry.newResource();
      resource.addProperty(SecurityConstants.PROP_PASSWORD, cryptoUtil
          .encryptAndBase64Encode(password.getBytes()));
      resource.addProperty(SecurityConstants.PROP_PROVIDER, provider);
      resource.addProperty(SecurityConstants.PROP_TYPE, type);

      if (pvtKeyAlias != null) {
        resource.addProperty(SecurityConstants.PROP_PRIVATE_KEY_ALIAS, pvtKeyAlias);
        resource.addProperty(SecurityConstants.PROP_PRIVATE_KEY_PASS, cryptoUtil
            .encryptAndBase64Encode(pvtkeyPass.getBytes()));
      }

      resource.setContent(content);
      registry.put(path, resource);
    } catch (SecurityConfigException e) {
      throw e;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage(), e);
    }
  }

  public void deleteStore(String keyStoreName) throws SecurityConfigException {
    try {
      if (keyStoreName == null || (keyStoreName = keyStoreName.trim()).length() == 0) {
        throw new SecurityConfigException("Key Store name can't be null");
      }

      if (KeyStoreUtil.isPrimaryStore(keyStoreName)) {
        throw new SecurityConfigException("Not allowed to delete the primary key store : "
                        + keyStoreName);
      }

      String path = SecurityConstants.KEY_STORES + "/" + keyStoreName;
      boolean isFound = false;
      Association[] assocs = registry.getAllAssociations(path);
      if (assocs.length > 0) {
        isFound = true;
      }

            if (isFound) {
                throw new SecurityConfigException("Key store : " + keyStoreName +
                        " is already in use and can't be deleted");
      }
      registry.delete(path);
    } catch (RegistryException e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage(), e);
    }
  }

  public void importCertToStore(String fileName, String certData, String keyStoreName)
      throws SecurityConfigException {
    try {
      if (keyStoreName == null) {
        throw new SecurityConfigException("Key Store name can't be null");
      }

      KeyStoreManager keyMan = KeyStoreManager.getInstance((UserRegistry)registry);
      KeyStore ks = keyMan.getKeyStore(keyStoreName);

      byte[] bytes = Base64.decode(certData);
      CertificateFactory factory = CertificateFactory.getInstance("X.509");
      X509Certificate cert;
            try {
                cert = (X509Certificate) factory
                    .generateCertificate(new ByteArrayInputStream(bytes));
            } catch (CertificateException e) {
                log.error(e.getMessage(), e);
                throw new SecurityConfigException("Invalid format of the provided certificate file");
            }

      if (ks.getCertificateAlias(cert) != null) {
        // We already have this certificate in the key store - ignore
        // adding it twice
        return;
      }

      // String alias = this.getAlias(cert);
      ks.setCertificateEntry(fileName, cert);

      keyMan.updateKeyStore(keyStoreName, ks);

    } catch (SecurityConfigException e) {
      throw e;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage(), e);
    }

  }

  public String importCertToStore(String certData, String keyStoreName)
      throws SecurityConfigException {
    String alias = null;

    try {
      if (keyStoreName == null) {
        throw new SecurityConfigException("Key Store name can't be null");
      }

      KeyStoreManager keyMan = KeyStoreManager.getInstance((UserRegistry)registry);
      KeyStore ks = keyMan.getKeyStore(keyStoreName);

      byte[] bytes = Base64.decode(certData);
      CertificateFactory factory = CertificateFactory.getInstance("X.509");
      X509Certificate cert;
            try {
                cert = (X509Certificate) factory
                    .generateCertificate(new ByteArrayInputStream(bytes));
            } catch (Exception e) {
                throw new SecurityConfigException("Invalid format of the provided certificate file");
            }

      if (ks.getCertificateAlias(cert) != null) {
        // We already have this certificate in the key store - ignore
        // adding it twice
        return null;
      }
      alias = cert.getSubjectDN().getName();
      // String alias = this.getAlias(cert);
      ks.setCertificateEntry(alias, cert);

      keyMan.updateKeyStore(keyStoreName, ks);

      return alias;

    } catch (SecurityConfigException e) {
      throw e;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage() ,
          e);
    }
  }

  public void removeCertFromStore(String alias, String keyStoreName)
      throws SecurityConfigException {
    try {
      if (keyStoreName == null) {
        throw new SecurityConfigException("Key Store name can't be null");
      }

      KeyStoreManager keyMan = KeyStoreManager.getInstance((UserRegistry)registry);
      KeyStore ks = keyMan.getKeyStore(keyStoreName);

      if (ks.getCertificate(alias) == null) {
        return;
      }

      ks.deleteEntry(alias);
      keyMan.updateKeyStore(keyStoreName, ks);
    } catch (SecurityConfigException e) {
      throw e;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage(), e);
    }
  }

  public String[] getStoreEntries(String keyStoreName) throws SecurityConfigException {
    String[] names;
    try {
      if (keyStoreName == null) {
        throw new Exception("keystore name cannot be null");
      }

      KeyStoreManager keyMan = KeyStoreManager.getInstance((UserRegistry)registry);
      KeyStore ks = keyMan.getKeyStore(keyStoreName);

      Enumeration<String> enm = ks.aliases();
      List<String> lst = new ArrayList<String>();
      while (enm.hasMoreElements()) {
        lst.add(enm.nextElement());
      }

      names = lst.toArray(new String[lst.size()]);
    } catch (SecurityConfigException e) {
      throw e;
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new SecurityConfigException(e.getMessage(), e);
    }

    return names;
  }

  private String getAlias(X509Certificate cert) throws SecurityConfigException {
    // Alias should be the host name
    String name = cert.getSubjectDN().getName();
    String[] parts = name.split(",");
    String alias = null;
    for (int i = 0; i < parts.length; i++) {
      String cnStr = parts[i].trim();
      if (cnStr.startsWith("CN")) {
        alias = cnStr.substring(3).toLowerCase();
        break;
      }
    }
    if (alias == null) {
      throw new SecurityConfigException("Null Alias");
    }
    return alias;
  }

  /**
   * This method will list 1. Certificate aliases 2. Private key alise 3. Private key value to a
   * given keystore.
   *
   * @param keyStoreName The name of the keystore
   * @return Instance of KeyStoreData
   * @throws SecurityConfigException will be thrown
   */
  public KeyStoreData getKeystoreInfo(String keyStoreName) throws SecurityConfigException {
    try {

      if (keyStoreName == null) {
        throw new Exception("keystore name cannot be null");
      }

      KeyStore keyStore;
      String keyStoreType;
      String privateKeyPassowrd;
      if (KeyStoreUtil.isPrimaryStore(keyStoreName)) {
        KeyStoreManager keyMan = KeyStoreManager.getInstance((UserRegistry)registry);
        keyStore = keyMan.getPrimaryKeyStore();
        ServerConfiguration serverConfig = ServerConfiguration.getInstance();
        keyStoreType = serverConfig
            .getFirstProperty(RegistryResources.SecurityManagement.SERVER_PRIMARY_KEYSTORE_TYPE);
        privateKeyPassowrd = serverConfig
            .getFirstProperty(RegistryResources.SecurityManagement.SERVER_PRIVATE_KEY_PASSWORD);
      } else {
        String path = SecurityConstants.KEY_STORES + "/" + keyStoreName;
        if (!registry.resourceExists(path)) {
          throw new SecurityConfigException("Key Store not found");
        }
        Resource resource = registry.get(path);
        KeyStoreManager manager = KeyStoreManager.getInstance((UserRegistry)registry);
        keyStore = manager.getKeyStore(keyStoreName);
        keyStoreType = resource.getProperty(SecurityConstants.PROP_TYPE);

        String encpass = resource.getProperty(SecurityConstants.PROP_PRIVATE_KEY_PASS);

        CryptoUtil util = CryptoUtil.getDefaultCryptoUtil();
        privateKeyPassowrd = new String(util.base64DecodeAndDecrypt(encpass));

      }
      // Fill the information about the certificates
      Enumeration<String> aliases = keyStore.aliases();
      List<org.wso2.carbon.security.keystore.service.CertData> certDataList = new ArrayList<CertData>();
      Format formatter = new SimpleDateFormat("dd/MM/yyyy");

      while (aliases.hasMoreElements()) {
        String alias = aliases.nextElement();
        if (keyStore.isCertificateEntry(alias)) {
          X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
          certDataList.add(fillCertData(cert, alias, formatter));
        }
      }

      // Create a cert array
      CertData[] certs = certDataList.toArray(new CertData[certDataList.size()]);

      // Create a KeyStoreData bean, set the name and fill in the cert information
      KeyStoreData keyStoreData = new KeyStoreData();
      keyStoreData.setKeyStoreName(keyStoreName);
      keyStoreData.setCerts(certs);
      keyStoreData.setKeyStoreType(keyStoreType);

      aliases = keyStore.aliases();
      while (aliases.hasMoreElements()) {
        String alias = aliases.nextElement();
        // There be only one entry in WSAS related keystores
        if (keyStore.isKeyEntry(alias)) {
          X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
          keyStoreData.setKey(fillCertData(cert, alias, formatter));

          PrivateKey key = (PrivateKey) keyStore.getKey(alias, privateKeyPassowrd
              .toCharArray());
          String pemKey;
          pemKey = "-----BEGIN PRIVATE KEY-----\n";
          pemKey += Base64.encode(key.getEncoded());
          pemKey += "\n-----END PRIVATE KEY-----";
          keyStoreData.setKeyValue(pemKey);
          break;

        }
      }
      return keyStoreData;
    } catch (Exception e) {
      String msg = "Error has encounted while loading the keystore to the given keystore name "
          + keyStoreName;
      log.error(msg, e);
      throw new SecurityConfigException(msg);
    }

  }

  public Key getPrivateKey(String alias) throws SecurityConfigException {
    KeyStoreData[] keystores = getKeyStores();
    KeyStore keyStore = null;
    String privateKeyPassowrd = null;

    try {

      for (int i = 0; i < keystores.length; i++) {
        if (KeyStoreUtil.isPrimaryStore(keystores[i].getKeyStoreName())) {
          KeyStoreManager keyMan = KeyStoreManager.getInstance((UserRegistry)registry);
          keyStore = keyMan.getPrimaryKeyStore();
          ServerConfiguration serverConfig = ServerConfiguration.getInstance();
          privateKeyPassowrd = serverConfig
              .getFirstProperty(RegistryResources.SecurityManagement.SERVER_PRIVATE_KEY_PASSWORD);
          return keyStore.getKey(alias, privateKeyPassowrd.toCharArray());
        }
      }
    } catch (Exception e) {
      String msg = "Error has encounted while loading the key for the given alias " + alias;
      log.error(msg, e);
      throw new SecurityConfigException(msg);
    }
    return null;
  }

  private CertData fillCertData(X509Certificate cert, String alise, Format formatter)
            throws CertificateEncodingException {
        CertData certData = null;

        if (includeCert) {
            certData = new CertDataDetail();
        } else {
            certData = new CertData();
        }
        certData.setAlias(alise);
        certData.setSubjectDN(cert.getSubjectDN().getName());
        certData.setIssuerDN(cert.getIssuerDN().getName());
        certData.setSerialNumber(cert.getSerialNumber());
        certData.setVersion(cert.getVersion());
        certData.setNotAfter(formatter.format(cert.getNotAfter()));
        certData.setNotBefore(formatter.format(cert.getNotBefore()));
        certData.setPublicKey(Base64.encode(cert.getPublicKey().getEncoded()));

        if (includeCert) {
            ((CertDataDetail) certData).setCertificate(cert);
        }

        return certData;
    }

  private byte[] readBytesFromFile(String filePath) throws IOException {
    InputStream inputStream = null;
    File file = new File(filePath);
    long length;
    byte[] bytes;
    int offset = 0;
    int numRead = 0;

    try {
      inputStream = new FileInputStream(file);
      length = file.length();
      bytes = new byte[(int) length];

      while (offset < bytes.length
          && (numRead = inputStream.read(bytes, offset, bytes.length - offset)) >= 0) {
        offset += numRead;
      }
    } finally {
      if (inputStream != null) {
        inputStream.close();
      }
    }

    return bytes;
  }

    /**
     * This method is used to generate the file name of the pub. cert of a tenant
     * @param ksLocation keystore location in the registry
     * @param uuid UUID appender
     * @return file name of the pub. cert
     */
    private String generatePubCertFileName(String ksLocation, String uuid){
        String tenantName = ksLocation.substring(ksLocation.lastIndexOf("/"));
        if(tenantName.endsWith(".jks")){
            tenantName = tenantName.replace(".jks", "");
        }
        return tenantName + "-" + uuid + ".cert";
    }

}
TOP

Related Classes of org.wso2.carbon.security.keystore.KeyStoreAdmin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.