Package org.ejbca.core.protocol.cmp

Source Code of org.ejbca.core.protocol.cmp.CmpRAUnidTest

/*************************************************************************
*                                                                       *
*  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.core.protocol.cmp;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.X509Principal;
import org.cesecore.core.ejb.ca.store.CertificateProfileSessionRemote;
import org.cesecore.core.ejb.ra.raadmin.EndEntityProfileSessionRemote;
import org.ejbca.config.CmpConfiguration;
import org.ejbca.core.ejb.ca.caadmin.CAAdminSessionRemote;
import org.ejbca.core.ejb.ca.caadmin.CaSessionRemote;
import org.ejbca.core.ejb.config.ConfigurationSessionRemote;
import org.ejbca.core.model.AlgorithmConstants;
import org.ejbca.core.model.ca.caadmin.CAInfo;
import org.ejbca.core.model.ca.certificateprofiles.CertificateProfile;
import org.ejbca.core.model.ca.certificateprofiles.CertificateProfileExistsException;
import org.ejbca.core.model.ca.certificateprofiles.EndUserCertificateProfile;
import org.ejbca.core.model.log.Admin;
import org.ejbca.core.model.ra.raadmin.EndEntityProfile;
import org.ejbca.core.model.ra.raadmin.EndEntityProfileExistsException;
import org.ejbca.core.protocol.unid.UnidFnrHandler;
import org.ejbca.util.CertTools;
import org.ejbca.util.CryptoProviderTools;
import org.ejbca.util.InterfaceCache;
import org.ejbca.util.keystore.KeyTools;

import com.novosec.pkix.asn1.cmp.PKIMessage;

/**
* Tests the unid-fnr plugin.
* Read the assert printout {@link #test01()} to understand how to set things up for the test.
*
* @author primelars
* @version $Id: CmpRAUnidTest.java 12052 2011-05-21 07:29:28Z anatom $
*/
public class CmpRAUnidTest extends CmpTestCase {

  private static final Logger log = Logger.getLogger(CmpRAUnidTest.class);

  private static final String PBEPASSWORD = "password";
  private static final String UNIDPREFIX = "1234-5678-";
  private static final String CPNAME = UNIDPREFIX+CmpRAUnidTest.class.getName();
  private static final String EEPNAME = UNIDPREFIX+CmpRAUnidTest.class.getName();

  /**
   * SUBJECT_DN of user used in this test, this contains special, escaped,
   * characters to test that this works with CMP RA operations
   */
  private static final String FNR = "90123456789";
  private static final String LRA = "01234";
  private static final String SUBJECT_SN = FNR+'-'+LRA;
  private static final String SUBJECT_DN = "C=SE,SN="+SUBJECT_SN+",CN=unid-frn";

  private final String issuerDN;
  private final KeyPair keys;

  private final int caid;
  private final Admin admin = new Admin(Admin.TYPE_BATCHCOMMANDLINE_USER);
  private final X509Certificate cacert;

  private final CAAdminSessionRemote caAdminSession = InterfaceCache.getCAAdminSession();
  private final CaSessionRemote caSession = InterfaceCache.getCaSession();
  private final CertificateProfileSessionRemote certificateProfileSession = InterfaceCache.getCertificateProfileSession();
  private final ConfigurationSessionRemote configurationSession = InterfaceCache.getConfigurationSession();
  private final EndEntityProfileSessionRemote endEntityProfileSession = InterfaceCache.getEndEntityProfileSession();

  public CmpRAUnidTest(String arg0) throws Exception {
    super(arg0);
    CryptoProviderTools.installBCProvider();
    // Try to use AdminCA1 if it exists
    final CAInfo adminca1 = this.caAdminSession.getCAInfo(this.admin, "AdminCA1");
    if (adminca1 == null) {
      final Collection<Integer> caids = this.caSession.getAvailableCAs(this.admin);
      final Iterator<Integer> iter = caids.iterator();
      int tmp = 0;
      while (iter.hasNext()) {
        tmp = iter.next().intValue();
        if ( tmp!=0 ) {
          break;
        }
      }
      this.caid = tmp;
    } else {
      this.caid = adminca1.getCAId();
    }
    if (this.caid == 0) {
      assertTrue("No active CA! Must have at least one active CA to run tests!", false);
    }
    final CAInfo cainfo = this.caAdminSession.getCAInfo(this.admin, this.caid);
    final Collection<Certificate> certs = cainfo.getCertificateChain();
    if (certs.size() > 0) {
      final Iterator<Certificate> certiter = certs.iterator();
      final Certificate cert = certiter.next();
      final String subject = CertTools.getSubjectDN(cert);
      if (StringUtils.equals(subject, cainfo.getSubjectDN())) {
        // Make sure we have a BC certificate
        this.cacert = (X509Certificate) CertTools.getCertfromByteArray(cert.getEncoded());
      } else {
        this.cacert = null;
      }
    } else {
      this.cacert = null;
      log.error("NO CACERT for caid " + this.caid);
    }
    this.issuerDN = this.cacert.getIssuerDN().getName();
    // Configure CMP for this test
    updatePropertyOnServer(CmpConfiguration.CONFIG_OPERATIONMODE, "ra");
    updatePropertyOnServer(CmpConfiguration.CONFIG_ALLOWRAVERIFYPOPO, "true");
    updatePropertyOnServer(CmpConfiguration.CONFIG_RESPONSEPROTECTION, "pbe");
    updatePropertyOnServer(CmpConfiguration.CONFIG_RA_AUTHENTICATIONSECRET, PBEPASSWORD);
    updatePropertyOnServer(CmpConfiguration.CONFIG_RA_CERTIFICATEPROFILE, "KeyId");
    updatePropertyOnServer(CmpConfiguration.CONFIG_RA_ENDENTITYPROFILE, "KeyId");
    updatePropertyOnServer(CmpConfiguration.CONFIG_RACANAME, cainfo.getName());
    updatePropertyOnServer(CmpConfiguration.CONFIG_CERTREQHANDLER_CLASS, UnidFnrHandler.class.getName());
    // Configure a Certificate profile (CmpRA) using ENDUSER as template
    if (this.certificateProfileSession.getCertificateProfile(this.admin, CPNAME) == null) {
      final CertificateProfile cp = new EndUserCertificateProfile();
      try { // TODO: Fix this better
        this.certificateProfileSession.addCertificateProfile(this.admin, CPNAME, cp);
      } catch (CertificateProfileExistsException e) {
        log.error("Certificate profile exists: ", e);
      }
    }
    final int cpId = this.certificateProfileSession.getCertificateProfileId(this.admin, CPNAME);
    if (this.endEntityProfileSession.getEndEntityProfile(this.admin, EEPNAME) == null) {
      final EndEntityProfile eep = new EndEntityProfile(true);
      eep.setValue(EndEntityProfile.AVAILCERTPROFILES, 0, "" + cpId);
      try {
        this.endEntityProfileSession.addEndEntityProfile(this.admin, EEPNAME, eep);
      } catch (EndEntityProfileExistsException e) {
        log.error("Could not create end entity profile.", e);
      }
    }
    this.keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA);
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();
  }

  @Override
  public void tearDown() throws Exception {
    super.tearDown();
  }
  @Override
  protected void checkDN(String sExpected, X509Name actual) {
    final X509Name expected = new X509Name(sExpected);
    final Vector<DERObjectIdentifier> expectedOIDs = expected.getOIDs();
    final Vector<String> expectedValues = expected.getValues();
    final Vector<DERObjectIdentifier> actualOIDs = actual.getOIDs();
    final Vector<String> actualValues = actual.getValues();
    assertEquals("Not the expected number of elements in the created certificate.", expectedOIDs.size(), actualOIDs.size());
    for ( int i=0; i<expectedOIDs.size(); i++ ) {
      final DERObjectIdentifier oid = expectedOIDs.get(i);
      final int j = actualOIDs.indexOf(oid);
      if ( !oid.equals(X509Name.SN) ) {
        log.debug("Check that "+oid.getId()+" is OK. Expected '"+expectedValues.get(i)+"'. Actual '"+actualValues.get(j)+"'.");
        assertEquals("Not expected "+oid, expectedValues.get(i), actualValues.get(j));
        continue;
      }
      log.debug("Special handling of the SN "+oid.getId()+". Input '"+expectedValues.get(i)+"'. Transformed '"+actualValues.get(j)+"'.");
      final String expectedSNPrefix=UNIDPREFIX+LRA;
      final String actualSNPrefix=actualValues.get(j).substring(0, expectedSNPrefix.length());
      assertEquals("New serial number prefix not as expected.", expectedSNPrefix,actualSNPrefix);
      final String actualSNRandom=actualValues.get(j).substring(expectedSNPrefix.length());
      assertTrue( "Random in serial number not OK: "+actualSNRandom, Pattern.compile("^\\w{6}$").matcher(actualSNRandom).matches() );
    }
  }
  public void test01() throws Exception {
    final Connection connection;
    final String host="localhost";
    final String user="uniduser";
    final String pass="unidpass";
    final String name="unid";
    try {
      connection = DriverManager.getConnection("jdbc:mysql://"+host+":3306/"+name, user, pass);
    } catch (SQLException e) {
      final StringWriter sw = new StringWriter();
      final PrintWriter pw = new PrintWriter(sw);
      pw.println();
      pw.println("You have not set up a unid-fnr DB properly to run the test.");
      pw.println("If you don't bother about it (don't if you don't know what it is) please just ignore this error.");
      pw.println("But if you want to run the test please make sure that the mysql unid-fnr DB is set up.");
      pw.println("Then execute next line at the mysql prompt:");
      pw.println("mysql> grant all on "+name+".* to "+user+"@'"+host+"' identified by '"+pass+"';");
      pw.println("And then create the DB:");
      pw.println("$ mysqladmin -u"+host+" -u"+user+" -p"+pass+" create "+name+";.");
      pw.println("These properties must the also be defined for the jboss data source. The name of the DS must be set in cmp.properties. Not that the datasource must be a 'no-tx-datasource', like OcspDS.");
      pw.println("You also have to set the path to the 'mysql.jar' as the 'mysql.lib' system property for the test.");
      pw.println("Example how to the test with this property:");
      pw.println("ant -Dmysql.lib=/usr/share/java/mysql.jar test:run");
      log.error(sw, e);
      assertTrue(sw.toString(),false);
      return;
    }
    try {
      doTest(connection);
    } finally {
      connection.close();
    }
  }
  private void doTest(Connection dbConn) throws Exception {

    final byte[] nonce = CmpMessageHelper.createSenderNonce();
    final byte[] transid = CmpMessageHelper.createSenderNonce();
    final int reqId;
    final String unid;
    {
      // In this test SUBJECT_DN contains special, escaped characters to verify
      // that that works with CMP RA as well
      final PKIMessage one = genCertReq(this.issuerDN, SUBJECT_DN, this.keys, this.cacert, nonce, transid, true, null, null, null, null);
      final PKIMessage req = protectPKIMessage(one, false, PBEPASSWORD, CPNAME, 567);
      assertNotNull(req);

      reqId = req.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue();
      final ByteArrayOutputStream bao = new ByteArrayOutputStream();
      final DEROutputStream out = new DEROutputStream(bao);
      out.writeObject(req);
      final byte[] ba = bao.toByteArray();
      // Send request and receive response
      final byte[] resp = sendCmpHttp(ba, 200);
      checkCmpResponseGeneral(resp, this.issuerDN, SUBJECT_DN, this.cacert, nonce, transid, false, PBEPASSWORD);
      final X509Certificate cert = checkCmpCertRepMessage(SUBJECT_DN, this.cacert, resp, reqId);
      unid = (String)new X509Principal( cert.getSubjectX500Principal().getEncoded() ).getValues(X509Name.SN).get(0);
      log.debug("Unid: "+unid);
    }
    {
      final PreparedStatement ps = dbConn.prepareStatement("select fnr from UnidFnrMapping where unid=?");
      ps.setString(1, unid);
      final ResultSet result = ps.executeQuery();
      assertTrue("Unid '"+unid+"' not found in DB.", result.next());
      final String fnr = result.getString(1);
      log.debug("FNR read from DB: "+fnr);
      assertEquals("Right FNR not found in DB.", FNR, fnr);
    }
    {
      // Send a confirm message to the CA
      final String hash = "foo123";
      final PKIMessage confirm = genCertConfirm(SUBJECT_DN, this.cacert, nonce, transid, hash, reqId);
      assertNotNull(confirm);
      final PKIMessage req1 = protectPKIMessage(confirm, false, PBEPASSWORD, 567);
      final ByteArrayOutputStream bao = new ByteArrayOutputStream();
      final DEROutputStream out = new DEROutputStream(bao);
      out.writeObject(req1);
      final byte[] ba = bao.toByteArray();
      // Send request and receive response
      final byte[] resp = sendCmpHttp(ba, 200);
      checkCmpResponseGeneral(resp, this.issuerDN, SUBJECT_DN, this.cacert, nonce, transid, false, PBEPASSWORD);
      checkCmpPKIConfirmMessage(SUBJECT_DN, this.cacert, resp);
    }
  }

  public void testZZZCleanUp() throws Exception {
    log.trace(">testZZZCleanUp");
    this.endEntityProfileSession.removeEndEntityProfile(this.admin, EEPNAME);
    this.certificateProfileSession.removeCertificateProfile(this.admin, CPNAME);
    assertTrue("Unable to clean up properly.", this.configurationSession.restoreConfiguration());
    log.trace("<testZZZCleanUp");
  }
}
TOP

Related Classes of org.ejbca.core.protocol.cmp.CmpRAUnidTest

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.