Package org.ejbca.ui.cli.ca

Source Code of org.ejbca.ui.cli.ca.CaImportCRLCommand

/*************************************************************************
*                                                                       *
*  EJBCA: The OpenSource Certificate Authority                          *
*                                                                       *
*  This software is free software; you can redistribute it and/or       *
*  modify it under the terms of the GNU Lesser General Public           *
*  License as published by the Free Software Foundation; either         *
*  version 2.1 of the License, or any later version.                    *
*                                                                       *
*  See terms of license at gnu.org.                                     *
*                                                                       *
*************************************************************************/

package org.ejbca.ui.cli.ca;

import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Set;

import javax.security.auth.x500.X500Principal;

import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.ejbca.core.model.AlgorithmConstants;
import org.ejbca.core.model.SecConst;
import org.ejbca.core.model.ca.caadmin.CAInfo;
import org.ejbca.core.model.ca.crl.RevokedCertInfo;
import org.ejbca.core.model.ra.AlreadyRevokedException;
import org.ejbca.core.model.ra.UserDataConstants;
import org.ejbca.core.model.ra.UserDataVO;
import org.ejbca.ui.cli.ErrorAdminCommandException;
import org.ejbca.util.CertTools;
import org.ejbca.util.CryptoProviderTools;
import org.ejbca.util.cert.CrlExtensions;
import org.ejbca.util.keystore.KeyTools;

/**
* Imports a CRL file to the database.
*
* @author Anders Rundgren
* @version $Id: CaImportCRLCommand.java 11815 2011-04-26 10:45:31Z anatom $
*/
public class CaImportCRLCommand extends BaseCaAdminCommand {

  @Override
  public String getMainCommand() { return MAINCOMMAND; }
  @Override
  public String getSubCommand() { return "importcrl"; }
  @Override
  public String getDescription() { return "Imports a CRL file (and update certificates) to the database"; }

  private static final String STRICT_OP = "STRICT";
  private static final String LENIENT_OP = "LENIENT";
  private static final String ADAPTIVE_OP = "ADAPTIVE";

  @Override
  public void execute(String[] args) throws ErrorAdminCommandException {
    getLogger().trace(">execute()");
    CryptoProviderTools.installBCProvider();
    if (args.length != 4 || (!args[3].equalsIgnoreCase(STRICT_OP) && !args[3].equalsIgnoreCase(LENIENT_OP) && !args[3].equalsIgnoreCase(ADAPTIVE_OP))) {
      usage();
      return;
    }
    try {
      // Parse arguments
      final String caname = args[1];
      final String crl_file = args[2];
      final boolean strict = args[3].equalsIgnoreCase(STRICT_OP);
      final boolean adaptive = args[3].equalsIgnoreCase(ADAPTIVE_OP);
      // Fetch CA and related info
      final CAInfo cainfo = getCAInfo(caname);
      final X509Certificate cacert = (X509Certificate) cainfo.getCertificateChain().iterator().next();
      final String issuer = CertTools.stringToBCDNString(cacert.getSubjectDN().toString());
      getLogger().info("CA: " + issuer);
      // Read the supplied CRL and verify that it is issued by the specified CA
      final X509CRL x509crl = (X509CRL) CertTools.getCertificateFactory().generateCRL(new FileInputStream (crl_file));
          if (!x509crl.getIssuerX500Principal().getName().equals(cacert.getSubjectX500Principal().getName())){
            throw new IOException ("CRL wasn't issued by this CA");
          }
          x509crl.verify(cacert.getPublicKey());
          int crl_no = CrlExtensions.getCrlNumber(x509crl).intValue();
          getLogger().info("Processing CRL #" + crl_no);
          int miss_count = 0// Number of certs not already in database
          int revoked = 0// Number of certs activly revoked by this algorithm
          int already_revoked = 0// Number of certs already revoked in database and ignored in non-strict mode
          final String missing_user_name = "*** Missing During CRL Import to: " + caname;
          for (final X509CRLEntry entry : (Set<X509CRLEntry>) x509crl.getRevokedCertificates()) {
            final BigInteger serialNr = entry.getSerialNumber();
            final String serialHex = serialNr.toString(16).toUpperCase();
            final String username = ejb.getCertStoreSession().findUsernameByCertSerno(getAdmin(), serialNr, issuer);
            // If this certificate exists and has an assigned username, we keep using that. Otherwise we create this coupling to a user.
            if (username == null) {
              getLogger().info ("Certificate '"+ serialHex +"' missing in the database");
              if (strict) {
                throw new IOException ("Aborted! Running in strict mode and is missing certificate in database.");
              }
              miss_count++;
              if (!adaptive) {
                continue;
              }
              final Date time = new Date();              // time from which certificate is valid
              final KeyPair key_pair = KeyTools.genKeys("1024", AlgorithmConstants.KEYALGORITHM_RSA);   
              final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
              final X500Principal dnName = new X500Principal("CN=Dummy Missing in Imported CRL, serialNumber=" + serialHex);
              certGen.setSerialNumber(serialNr);
              certGen.setIssuerDN(cacert.getSubjectX500Principal());
              certGen.setNotBefore(time);
              certGen.setNotAfter(new Date (time.getTime() + 1000L * 60 * 60 * 24 * 365 * 10))// 10 years of life
              certGen.setSubjectDN(dnName);                       // note: same as issuer
              certGen.setPublicKey(key_pair.getPublic());
              certGen.setSignatureAlgorithm("SHA1withRSA");
              final X509Certificate certificate = certGen.generate(key_pair.getPrivate(), "BC");
              final String fingerprint = CertTools.getFingerprintAsString(certificate);
              // We add all certificates that does not have a user already to "missing_user_name"
              final UserDataVO missingUserDataVO = ejb.getUserAdminSession().findUser(getAdmin(), missing_user_name);
              if (missingUserDataVO == null) {
                // Add the user and change status to REVOKED
                getLogger().debug("Loading/updating user " + missing_user_name);
                final UserDataVO userdataNew = new UserDataVO(missing_user_name, CertTools.getSubjectDN(certificate), cainfo.getCAId(), null, null,
                    UserDataConstants.STATUS_NEW, SecConst.USER_ENDUSER, SecConst.EMPTY_ENDENTITYPROFILE,
                    SecConst.CERTPROFILE_FIXED_ENDUSER, null, null, SecConst.TOKEN_SOFT_BROWSERGEN, SecConst.NO_HARDTOKENISSUER, null);
                userdataNew.setPassword("foo123");
                ejb.getUserAdminSession().addUser(getAdmin(), userdataNew, false);
                getLogger().info("User '" + missing_user_name + "' has been added.");
                ejb.getUserAdminSession().setUserStatus(getAdmin(), missing_user_name, UserDataConstants.STATUS_REVOKED);
                getLogger().info("User '" + missing_user_name + "' has been updated.");
              }
              ejb.getCertStoreSession().storeCertificate(getAdmin(), certificate, missing_user_name, fingerprint,
                  SecConst.CERT_ACTIVE, SecConst.USER_ENDUSER, SecConst.CERTPROFILE_FIXED_ENDUSER, null, new Date().getTime());
              getLogger().info("Dummy certificate  '" + serialHex + "' has been stored.");
            }
            // This check will not catch a certificate with status SecConst.CERT_ARCHIVED
            if (!strict && ejb.getCertStoreSession().isRevoked(issuer, serialNr)) {
              getLogger().info("Certificate '" + serialHex +"' is already revoked");
              already_revoked++;
              continue;
            }
            getLogger().info("Revoking '" + serialHex +"' " + "(" + serialNr.toString() + ")");
            try {
              ejb.getUserAdminSession().revokeCert(getAdmin(), serialNr, entry.getRevocationDate(), issuer, RevokedCertInfo.REVOCATION_REASON_UNSPECIFIED);
              revoked++;
            } catch (AlreadyRevokedException e) {
              already_revoked++;
              getLogger().warn("Failed to revoke '" + serialHex +"'. (Status might be 'Archived'.) Error message was: " + e.getMessage());
            }
          }
          if (ejb.getCrlSession().getLastCRLNumber(getAdmin(), issuer, false) < crl_no) {
            ejb.getCrlSession().storeCRL(getAdmin(), x509crl.getEncoded(), CertTools.getFingerprintAsString(cacert), crl_no, issuer, x509crl.getThisUpdate(), x509crl.getNextUpdate(), -1);
          } else {
            if (strict) {
              throw new IOException("CRL #" + crl_no + " or higher is already in the database");
            }
          }
      getLogger().info("\nSummary:\nRevoked " + revoked + " certificates");
      if (already_revoked > 0) {
        getLogger().info(already_revoked + " certificates were already revoked");
      }
      if (miss_count > 0) {
        getLogger().info("There were " + miss_count + (adaptive ? " dummy certificates added to" : " certificates missing in") " the database");
      }
          getLogger().info("CRL #" + crl_no + " stored in the database");
    } catch (Exception e) {
      getLogger().info("Error: " + e.getMessage());
    }
    getLogger().trace("<execute()");
  }

  private void usage() {
    getLogger().info("Description: " + getDescription());
    getLogger().info("Usage: " + getCommand() + " <caname> <crl file> <" + STRICT_OP + "|" + LENIENT_OP + "|" + ADAPTIVE_OP + ">");
    getLogger().info(STRICT_OP + " means that all certificates must be in the database and that the CRL must not already be in the database");
    getLogger().info(LENIENT_OP + " means not strict and not adaptive");
    getLogger().info(ADAPTIVE_OP + " means that missing certficates will be replaced by dummy certificates to cater for proper CRLs for missing certificates");
    getLogger().info(" Existing CAs: " + getAvailableCasString());
 
}
TOP

Related Classes of org.ejbca.ui.cli.ca.CaImportCRLCommand

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.