/*
*
* Copyright (c) 2013 - 2017 Lijun Liao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
*
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the XiPKI software without
* disclosing the source code of your own applications.
*
* For more information, please contact Lijun Liao at this
* address: lijun.liao@gmail.com
*/
package org.xipki.pki.ca.dbtool.port.ca;
import java.io.File;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.bouncycastle.util.encoders.Base64;
import org.xipki.commons.common.util.CollectionUtil;
import org.xipki.commons.common.util.ParamUtil;
import org.xipki.commons.common.util.XmlUtil;
import org.xipki.commons.datasource.DataSourceWrapper;
import org.xipki.commons.datasource.springframework.dao.DataAccessException;
import org.xipki.commons.dbtool.InvalidInputException;
import org.xipki.commons.password.PasswordResolverException;
import org.xipki.commons.security.util.X509Util;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.CaHasProfiles;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.CaHasPublishers;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.CaHasRequestors;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Caaliases;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Cas;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Cmpcontrols;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Crlsigners;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Environments;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Profiles;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Publishers;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Requestors;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Responders;
import org.xipki.pki.ca.dbtool.jaxb.ca.CAConfigurationType.Sceps;
import org.xipki.pki.ca.dbtool.port.DbPorter;
import org.xipki.pki.ca.dbtool.jaxb.ca.CaHasProfileType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CaHasPublisherType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CaHasRequestorType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CaType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CaaliasType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CmpcontrolType;
import org.xipki.pki.ca.dbtool.jaxb.ca.CrlsignerType;
import org.xipki.pki.ca.dbtool.jaxb.ca.EnvironmentType;
import org.xipki.pki.ca.dbtool.jaxb.ca.ProfileType;
import org.xipki.pki.ca.dbtool.jaxb.ca.PublisherType;
import org.xipki.pki.ca.dbtool.jaxb.ca.RequestorType;
import org.xipki.pki.ca.dbtool.jaxb.ca.ResponderType;
import org.xipki.pki.ca.dbtool.jaxb.ca.ScepType;
/**
* @author Lijun Liao
* @since 2.0.0
*/
class CaConfigurationDbImporter extends DbPorter {
private final Unmarshaller unmarshaller;
CaConfigurationDbImporter(final DataSourceWrapper datasource, final Unmarshaller unmarshaller,
final String srcDir, final AtomicBoolean stopMe, final boolean evaluateOnly)
throws DataAccessException, PasswordResolverException, IOException {
super(datasource, srcDir, stopMe, evaluateOnly);
this.unmarshaller = ParamUtil.requireNonNull("unmarshaller", unmarshaller);
}
public void importToDb() throws Exception {
CAConfigurationType caconf;
try {
@SuppressWarnings("unchecked")
JAXBElement<CAConfigurationType> root = (JAXBElement<CAConfigurationType>)
unmarshaller.unmarshal(new File(baseDir, FILENAME_CA_CONFIGURATION));
caconf = root.getValue();
} catch (JAXBException ex) {
throw XmlUtil.convert(ex);
}
if (caconf.getVersion() > VERSION) {
throw new InvalidInputException("could not import CA configuration greater than "
+ VERSION + ": " + caconf.getVersion());
}
System.out.println("importing CA configuration to database");
try {
importCmpcontrol(caconf.getCmpcontrols());
importResponder(caconf.getResponders());
importEnvironment(caconf.getEnvironments());
importRequestor(caconf.getRequestors());
importPublisher(caconf.getPublishers());
importProfile(caconf.getProfiles());
importCrlsigner(caconf.getCrlsigners());
importCa(caconf.getCas());
importCaalias(caconf.getCaaliases());
importCaHasRequestor(caconf.getCaHasRequestors());
importCaHasPublisher(caconf.getCaHasPublishers());
importCaHasCertprofile(caconf.getCaHasProfiles());
importScep(caconf.getSceps());
} catch (Exception ex) {
System.err.println("could not import CA configuration to database. message: "
+ ex.getMessage());
throw ex;
}
System.out.println(" imported CA configuration to database");
} // method importToDb
private void importCmpcontrol(final Cmpcontrols controls) throws DataAccessException {
System.out.println("importing table CMPCONTROL");
final String sql = "INSERT INTO CMPCONTROL (NAME,CONF) VALUES (?,?)";
if (controls != null && CollectionUtil.isNonEmpty(controls.getCmpcontrol())) {
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (CmpcontrolType control : controls.getCmpcontrol()) {
try {
int idx = 1;
ps.setString(idx++, control.getName());
ps.setString(idx++, control.getConf());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CMPCONTROL " + control.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
}
System.out.println(" imported table CMPCONTROL");
} // method importCmpcontrol
private void importResponder(final Responders responders)
throws DataAccessException, IOException {
System.out.println("importing table RESPONDER");
if (responders == null) {
System.out.println(" imported table RESPONDER: nothing to import");
return;
}
final String sql = "INSERT INTO RESPONDER (NAME,TYPE,CERT,CONF) VALUES (?,?,?,?)";
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (ResponderType responder : responders.getResponder()) {
byte[] certBytes = getBinary(responder.getCert());
String b64Cert = (certBytes == null) ? null : Base64.toBase64String(certBytes);
try {
int idx = 1;
ps.setString(idx++, responder.getName());
ps.setString(idx++, responder.getType());
ps.setString(idx++, b64Cert);
ps.setString(idx++, getValue(responder.getConf()));
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CRLSIGNER with NAME="
+ responder.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table RESPONDER");
} // method importResponder
private void importEnvironment(final Environments environments) throws DataAccessException {
System.out.println("importing table ENVIRONMENT");
final String sql = "INSERT INTO ENVIRONMENT (NAME,VALUE2) VALUES (?,?)";
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (EnvironmentType environment : environments.getEnvironment()) {
try {
int idx = 1;
ps.setString(idx++, environment.getName());
ps.setString(idx++, environment.getValue());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import ENVIRONMENT with NAME="
+ environment.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table ENVIRONMENT");
} // method importEnvironment
private void importCrlsigner(final Crlsigners crlsigners)
throws DataAccessException, IOException {
System.out.println("importing table CRLSIGNER");
final String sql = "INSERT INTO CRLSIGNER (NAME,SIGNER_TYPE,SIGNER_CERT,CRL_CONTROL,"
+ "SIGNER_CONF) VALUES (?,?,?,?,?)";
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (CrlsignerType crlsigner : crlsigners.getCrlsigner()) {
byte[] certBytes = getBinary(crlsigner.getSignerCert());
String b64Cert = (certBytes == null) ? null : Base64.toBase64String(certBytes);
try {
int idx = 1;
ps.setString(idx++, crlsigner.getName());
ps.setString(idx++, crlsigner.getSignerType());
ps.setString(idx++, b64Cert);
ps.setString(idx++, crlsigner.getCrlControl());
ps.setString(idx++, getValue(crlsigner.getSignerConf()));
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CRLSIGNER with NAME="
+ crlsigner.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table CRLSIGNER");
} // method importCrlsigner
private void importRequestor(final Requestors requestors)
throws DataAccessException, IOException {
System.out.println("importing table REQUESTOR");
final String sql = "INSERT INTO REQUESTOR (ID,NAME,CERT) VALUES (?,?,?)";
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (RequestorType requestor : requestors.getRequestor()) {
byte[] certBytes = getBinary(requestor.getCert());
String b64Cert = (certBytes == null) ? null : Base64.toBase64String(certBytes);
try {
int idx = 1;
ps.setInt(idx++, requestor.getId());
ps.setString(idx++, requestor.getName());
ps.setString(idx++, b64Cert);
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import REQUESTOR with NAME="
+ requestor.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table REQUESTOR");
} // method importRequestor
private void importPublisher(final Publishers publishers)
throws DataAccessException, IOException {
System.out.println("importing table PUBLISHER");
final String sql = "INSERT INTO PUBLISHER (ID,NAME,TYPE,CONF) VALUES (?,?,?,?)";
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (PublisherType publisher : publishers.getPublisher()) {
try {
int idx = 1;
ps.setInt(idx++, publisher.getId());
ps.setString(idx++, publisher.getName());
ps.setString(idx++, publisher.getType());
ps.setString(idx++, getValue(publisher.getConf()));
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import PUBLISHER with NAME="
+ publisher.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table PUBLISHER");
} // method importPublisher
private void importProfile(final Profiles profiles) throws DataAccessException, IOException {
System.out.println("importing table PROFILE");
final String sql = "INSERT INTO PROFILE (ID,NAME,ART,TYPE,CONF) VALUES (?,?,?,?,?)";
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (ProfileType certprofile : profiles.getProfile()) {
try {
int idx = 1;
ps.setInt(idx++, certprofile.getId());
ps.setString(idx++, certprofile.getName());
int art = (certprofile.getArt() == null) ? 1 : certprofile.getArt();
ps.setInt(idx++, art);
ps.setString(idx++, certprofile.getType());
String conf = getValue(certprofile.getConf());
ps.setString(idx++, conf);
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import PROFILE with NAME="
+ certprofile.getName());
throw translate(sql, ex);
} catch (IOException ex) {
System.err.println("could not import PROFILE with NAME="
+ certprofile.getName());
throw ex;
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table PROFILE");
} // method importProfile
private void importCa(final Cas cas)
throws DataAccessException, CertificateException, IOException {
System.out.println("importing table CA");
StringBuilder sqlBuilder = new StringBuilder(500);
sqlBuilder.append("INSERT INTO CA (ID,NAME,ART,SUBJECT,SN_SIZE,NEXT_CRLNO,STATUS,");
sqlBuilder.append("CRL_URIS,DELTACRL_URIS,OCSP_URIS,CACERT_URIS,MAX_VALIDITY,");
sqlBuilder.append("CERT,SIGNER_TYPE,CRLSIGNER_NAME,RESPONDER_NAME,CMPCONTROL_NAME,");
sqlBuilder.append("DUPLICATE_KEY,DUPLICATE_SUBJECT,SAVE_REQ,PERMISSION,");
sqlBuilder.append("NUM_CRLS,EXPIRATION_PERIOD,KEEP_EXPIRED_CERT_DAYS,");
sqlBuilder.append("REV,RR,RT,RIT,VALIDITY_MODE,EXTRA_CONTROL,SIGNER_CONF)");
sqlBuilder.append(" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
final String sql = sqlBuilder.toString();
PreparedStatement ps = null;
try {
ps = prepareStatement(sql);
for (CaType ca : cas.getCa()) {
int art = (ca.getArt() == null) ? 1 : ca.getArt();
try {
byte[] certBytes = getBinary(ca.getCert());
X509Certificate cert = X509Util.parseCert(certBytes);
int idx = 1;
ps.setInt(idx++, ca.getId());
ps.setString(idx++, ca.getName().toUpperCase());
ps.setInt(idx++, art);
ps.setString(idx++, X509Util.cutX500Name(cert.getSubjectX500Principal(),
maxX500nameLen));
ps.setInt(idx++, ca.getSnSize());
ps.setLong(idx++, ca.getNextCrlNo());
ps.setString(idx++, ca.getStatus());
ps.setString(idx++, ca.getCrlUris());
ps.setString(idx++, ca.getDeltacrlUris());
ps.setString(idx++, ca.getOcspUris());
ps.setString(idx++, ca.getCacertUris());
ps.setString(idx++, ca.getMaxValidity());
ps.setString(idx++, Base64.toBase64String(certBytes));
ps.setString(idx++, ca.getSignerType());
ps.setString(idx++, ca.getCrlsignerName());
ps.setString(idx++, ca.getResponderName());
ps.setString(idx++, ca.getCmpcontrolName());
ps.setInt(idx++, ca.getDuplicateKey());
ps.setInt(idx++, ca.getDuplicateSubject());
ps.setInt(idx++, ca.getSaveReq());
ps.setInt(idx++, ca.getPermission());
Integer numCrls = ca.getNumCrls();
int tmpNumCrls = (numCrls == null) ? 30 : numCrls.intValue();
ps.setInt(idx++, tmpNumCrls);
ps.setInt(idx++, ca.getExpirationPeriod());
ps.setInt(idx++, ca.getKeepExpiredCertDays());
setBoolean(ps, idx++, ca.isRevoked());
setInt(ps, idx++, ca.getRevReason());
setLong(ps, idx++, ca.getRevTime());
setLong(ps, idx++, ca.getRevInvTime());
ps.setString(idx++, ca.getValidityMode());
ps.setString(idx++, ca.getExtraControl());
ps.setString(idx++, getValue(ca.getSignerConf()));
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CA with NAME=" + ca.getName());
throw translate(sql, ex);
} catch (CertificateException | IOException ex) {
System.err.println("could not import CA with NAME=" + ca.getName());
throw ex;
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table CA");
} // method importCa
private void importCaalias(final Caaliases caaliases) throws DataAccessException {
System.out.println("importing table CAALIAS");
final String sql = "INSERT INTO CAALIAS (NAME,CA_ID) VALUES (?,?)";
PreparedStatement ps = prepareStatement(sql);
try {
for (CaaliasType caalias : caaliases.getCaalias()) {
try {
int idx = 1;
ps.setString(idx++, caalias.getName());
ps.setInt(idx++, caalias.getCaId());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CAALIAS with NAME=" + caalias.getName());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table CAALIAS");
} // method importCaalias
private void importCaHasRequestor(final CaHasRequestors caHasRequestors)
throws DataAccessException {
System.out.println("importing table CA_HAS_REQUESTOR");
final String sql =
"INSERT INTO CA_HAS_REQUESTOR (CA_ID,REQUESTOR_ID,RA,PERMISSION,PROFILES)"
+ " VALUES (?,?,?,?,?)";
PreparedStatement ps = prepareStatement(sql);
try {
for (CaHasRequestorType entry : caHasRequestors.getCaHasRequestor()) {
try {
int idx = 1;
ps.setInt(idx++, entry.getCaId());
ps.setInt(idx++, entry.getRequestorId());
setBoolean(ps, idx++, entry.isRa());
ps.setInt(idx++, entry.getPermission());
ps.setString(idx++, entry.getProfiles());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CA_HAS_REQUESTOR with CA_ID="
+ entry.getCaId() + " and REQUESTOR_ID=" + entry.getRequestorId());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table CA_HAS_REQUESTOR");
} // method importCaHasRequestor
private void importCaHasPublisher(final CaHasPublishers caHasPublishers) throws Exception {
System.out.println("importing table CA_HAS_PUBLISHER");
final String sql = "INSERT INTO CA_HAS_PUBLISHER (CA_ID,PUBLISHER_ID) VALUES (?,?)";
PreparedStatement ps = prepareStatement(sql);
try {
for (CaHasPublisherType entry : caHasPublishers.getCaHasPublisher()) {
try {
int idx = 1;
ps.setInt(idx++, entry.getCaId());
ps.setInt(idx++, entry.getPublisherId());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CA_HAS_PUBLISHER with CA_ID="
+ entry.getCaId() + " and PUBLISHER_ID=" + entry.getPublisherId());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table CA_HAS_PUBLISHER");
} // method importCaHasPublisher
private void importCaHasCertprofile(final CaHasProfiles caHasCertprofiles)
throws DataAccessException {
System.out.println("importing table CA_HAS_PROFILE");
final String sql = "INSERT INTO CA_HAS_PROFILE (CA_ID,PROFILE_ID) VALUES (?,?)";
PreparedStatement ps = prepareStatement(sql);
try {
for (CaHasProfileType entry : caHasCertprofiles.getCaHasProfile()) {
try {
int idx = 1;
ps.setInt(idx++, entry.getCaId());
ps.setInt(idx++, entry.getProfileId());
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import CA_HAS_PROFILE with CA_ID="
+ entry.getCaId() + " and PROFILE_ID=" + entry.getProfileId());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table CA_HAS_PROFILE");
} // method importCaHasCertprofile
private void importScep(final Sceps sceps) throws DataAccessException, IOException {
System.out.println("importing table SCEP");
final String sql = "INSERT INTO SCEP (NAME,CA_ID,ACTIVE,PROFILES,RESPONDER_TYPE,"
+ "RESPONDER_CERT,CONTROL,RESPONDER_CONF) VALUES (?,?,?,?,?,?,?,?)";
PreparedStatement ps = prepareStatement(sql);
try {
for (ScepType entry : sceps.getScep()) {
byte[] certBytes = getBinary(entry.getResponderCert());
String b64Cert = (certBytes == null) ? null : Base64.toBase64String(certBytes);
try {
int idx = 1;
ps.setString(idx++, entry.getName());
ps.setInt(idx++, entry.getCaId());
ps.setInt(idx++, entry.getActive());
ps.setString(idx++, entry.getProfiles());
ps.setString(idx++, entry.getResponderType());
ps.setString(idx++, b64Cert);
ps.setString(idx++, entry.getControl());
ps.setString(idx++, getValue(entry.getResponderConf()));
ps.executeUpdate();
} catch (SQLException ex) {
System.err.println("could not import SCEP with ID=" + entry.getCaId());
throw translate(sql, ex);
}
}
} finally {
releaseResources(ps, null);
}
System.out.println(" imported table SCEP");
} // method importScep
}