Java tutorial
/************************************************************************* * * * SignServer: The OpenSource Automated Signing Server * * * * 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.signserver.module.renewal.worker; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.Socket; import java.net.URL; import java.security.*; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.*; import javax.ejb.EJB; import javax.naming.NamingException; import javax.net.ssl.*; import javax.persistence.EntityManager; import javax.xml.namespace.QName; import org.apache.log4j.Logger; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.X509Extension; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.util.Selector; import org.bouncycastle.util.Store; import org.bouncycastle.util.encoders.Base64; import org.ejbca.util.CertTools; import org.signserver.common.*; import org.signserver.common.CryptoTokenOfflineException; import org.signserver.common.util.RandomPasswordGenerator; import org.signserver.ejb.interfaces.IWorkerSession; import org.signserver.module.renewal.common.RenewalWorkerProperties; import org.signserver.module.renewal.ejbcaws.gen.*; import org.signserver.server.WorkerContext; import org.signserver.server.cryptotokens.KeystoreCryptoToken; import org.signserver.server.log.IWorkerLogger; import org.signserver.server.log.LogMap; import org.signserver.server.signers.BaseSigner; /** * Worker renewing certificate (and optionally keys) for a signer by sending * a certificate signing request using the EJBCA Web Service interface. * * @author Markus Kils * @version $Id: RenewalWorker.java 5581 2014-12-11 12:29:13Z malu9369 $ */ public class RenewalWorker extends BaseSigner { /** Logger for this class. */ private static final Logger LOG = Logger.getLogger(RenewalWorker.class); public static final String PROPERTY_RENEWENDENTITY = "RENEWENDENTITY"; public static final String PROPERTY_REQUESTDN = "REQUESTDN"; public static final String PROPERTY_SIGNATUREALGORITHM = "SIGNATUREALGORITHM"; public static final String PROPERTY_KEYALG = "KEYALG"; public static final String PROPERTY_KEYSPEC = "KEYSPEC"; private static final String NEXTCERTSIGNKEY = "NEXTCERTSIGNKEY"; private static final String TRUSTSTORE_TYPE_PEM = "PEM"; private static final String TRUSTSTORE_TYPE_JKS = "JKS"; private static final String WS_PATH = "/ejbcaws/ejbcaws?wsdl"; private static final int MATCH_WITH_USERNAME = 0; private static final int MATCH_TYPE_EQUALS = 0; private static final int STATUS_NEW = 10; // From CertificateHelper: /** * Indicates that the requester want a BASE64 encoded certificate in the * CertificateResponse object. */ //private static String RESPONSETYPE_CERTIFICATE = "CERTIFICATE"; /** * Indicates that the requester want a BASE64 encoded pkcs7 in the * CertificateResponse object. */ //private static String RESPONSETYPE_PKCS7 = "PKCS7"; /** * Indicates that the requester want a BASE64 encoded pkcs7 with the * complete chain in the CertificateResponse object. */ private static final String RESPONSETYPE_PKCS7WITHCHAIN = "PKCS7WITHCHAIN"; private List<String> fatalErrors; /** Workersession. */ @EJB private IWorkerSession workerSession; /** Configuration parameters. */ private String alias; private String truststoreValue; private String truststoreType; private String truststorePath; private String truststorePass; private String ejbcaWsUrl; @Override public void init(final int workerId, final WorkerConfig config, final WorkerContext workerContext, final EntityManager workerEM) { initInternal(workerId, config, workerContext, workerEM); getWorkerSession(); } /** * Internal init method used by the unit test to initialize configuration * without looking up the worker session. */ void initInternal(final int workerId, final WorkerConfig config, final WorkerContext workerContext, final EntityManager workerEM) { super.init(workerId, config, workerContext, workerEM); fatalErrors = new LinkedList<String>(); setupConfig(); } /** * Setup configuration and update fatal errors. */ private void setupConfig() { alias = config.getProperty("DEFAULTKEY"); if (alias == null) { fatalErrors.add("Missing DEFAULTKEY property"); } truststoreType = config.getProperty("TRUSTSTORETYPE"); if (truststoreType == null) { fatalErrors.add("Missing TRUSTSTORETYPE property"); } truststorePath = config.getProperty("TRUSTSTOREPATH"); truststoreValue = config.getProperty(TRUSTSTOREVALUE); if (truststorePath == null && truststoreValue == null) { fatalErrors.add("Missing TRUSTSTOREPATH or TRUSTSTOREVALUE property"); } if (truststorePath != null && truststoreValue != null) { fatalErrors.add("Can not specify both TRUSTSTOREPATH and TRUSTSTOREVALUE property"); } truststorePass = config.getProperty("TRUSTSTOREPASSWORD"); if (truststorePass == null && !TRUSTSTORE_TYPE_PEM.equals(truststoreType)) { fatalErrors.add("Missing TRUSTSTOREPASSWORD property"); } ejbcaWsUrl = config.getProperty("EJBCAWSURL"); if (ejbcaWsUrl == null) { fatalErrors.add("Missing EJBCAWSURL property"); } } @Override public ProcessResponse processData(final ProcessRequest request, final RequestContext requestContext) throws IllegalRequestException, CryptoTokenOfflineException, SignServerException { final ProcessResponse ret; final Properties requestData, responseData; // Check that the request contains a valid request if (request instanceof GenericPropertiesRequest) { requestData = ((GenericPropertiesRequest) request).getProperties(); } else if (request instanceof GenericSignRequest) { requestData = new Properties(); try { requestData.load(new ByteArrayInputStream(((GenericSignRequest) request).getRequestData())); } catch (IOException ex) { LOG.error("Error in request: " + requestContext.get(RequestContext.TRANSACTION_ID), ex); throw new IllegalRequestException("Error parsing request. " + "See server log for information."); } } else { throw new IllegalRequestException("Recieved request was not of expected type."); } // Log values final LogMap logMap = LogMap.getInstance(requestContext); responseData = process(requestData, logMap, requestContext); // Log result logMap.put(RenewalWorkerProperties.LOG_RESPONSE_RESULT, responseData.getProperty(RenewalWorkerProperties.RESPONSE_RESULT)); logMap.put(RenewalWorkerProperties.LOG_RESPONSE_MESSAGE, responseData.getProperty(RenewalWorkerProperties.RESPONSE_MESSAGE)); if (request instanceof GenericSignRequest) { final GenericSignRequest signRequest = (GenericSignRequest) request; try { final ByteArrayOutputStream bout = new ByteArrayOutputStream(); responseData.store(bout, null); if (request instanceof GenericServletRequest) { ret = new GenericServletResponse(signRequest.getRequestID(), bout.toByteArray(), null, null, null, "text/plain"); } else { ret = new GenericSignResponse(signRequest.getRequestID(), signRequest.getRequestData(), null, null, null); } } catch (IOException ex) { LOG.error("Error constructing response for request: " + requestContext.get(RequestContext.TRANSACTION_ID), ex); throw new SignServerException("Error constructing response." + "See server log for information."); } } else { ret = new GenericPropertiesResponse(responseData); } return ret; } /** * Processes the request. * @param requestData * @return * @throws IllegalRequestException * @throws CryptoTokenOfflineException * @throws SignServerException */ private Properties process(final Properties requestData, final LogMap logMap, final RequestContext requestContext) throws IllegalRequestException, CryptoTokenOfflineException, SignServerException { final String workerName = requestData.getProperty(RenewalWorkerProperties.REQUEST_WORKER); final Properties responseData; if (workerName == null) { throw new IllegalRequestException("No worker name in request."); } responseData = new Properties(); // Log renewee logMap.put(RenewalWorkerProperties.LOG_RENEWEE, workerName); try { int reneweeId; try { reneweeId = Integer.parseInt(workerName); } catch (NumberFormatException ex) { if (LOG.isDebugEnabled()) { LOG.debug("Not a workerId, maybe workerName: " + workerName); } reneweeId = getWorkerSession().getWorkerId(workerName); } // Get the worker config final WorkerConfig workerConfig = getWorkerSession().getCurrentWorkerConfig(reneweeId); final String sigAlg = workerConfig.getProperty(PROPERTY_SIGNATUREALGORITHM); final String subjectDN = workerConfig.getProperty(PROPERTY_REQUESTDN); final String endEntity = workerConfig.getProperty(PROPERTY_RENEWENDENTITY); final String keyAlg = workerConfig.getProperty(PROPERTY_KEYALG); final String keySpec = workerConfig.getProperty(PROPERTY_KEYSPEC); final String explicitEccParameters = workerConfig.getProperty(WorkerConfig.PROPERTY_EXPLICITECC, String.valueOf(false)); String nextCertSignKey = workerConfig.getProperty(NEXTCERTSIGNKEY); // If we should use the default key (instead of nextKey, // if existing) can be specified in the request (but only if we // don't generate a new key) final String forDefaultKeyValue = requestData.getProperty(RenewalWorkerProperties.REQUEST_FORDEFAULTKEY, Boolean.FALSE.toString()); final boolean requestForDefaultKey = Boolean.TRUE.toString().equalsIgnoreCase(forDefaultKeyValue); final boolean renewKey = !requestForDefaultKey && nextCertSignKey == null; final String authCode = requestData.getProperty(RenewalWorkerProperties.REQUEST_AUTHCODE); if (LOG.isDebugEnabled()) { final StringBuilder buff = new StringBuilder(); buff.append("Renewer[").append(workerId).append("]: Got request for renewal of Worker[") .append(reneweeId).append("]: \n"); buff.append("Transaction:\n\t").append("LOG_ID: ").append(logMap.get(IWorkerLogger.LOG_ID)) .append("\n"); buff.append("Renewee config:\n\t").append(PROPERTY_SIGNATUREALGORITHM).append("=").append(sigAlg) .append("\n\t").append(PROPERTY_REQUESTDN).append("=").append(subjectDN).append("\n\t") .append(PROPERTY_KEYALG).append("=").append(keyAlg).append("\n\t").append(PROPERTY_KEYSPEC) .append("=").append(keySpec).append("\n\t").append(WorkerConfig.PROPERTY_EXPLICITECC) .append("=").append(explicitEccParameters).append("\n\t").append(PROPERTY_RENEWENDENTITY) .append("=").append(endEntity).append("\n"); buff.append("Request config:\n\t"); buff.append(RenewalWorkerProperties.REQUEST_FORDEFAULTKEY).append("=").append(requestForDefaultKey) .append("\n\t"); buff.append(RenewalWorkerProperties.REQUEST_AUTHCODE).append("="); if (authCode == null) { buff.append("null"); } else { final char[] masked = new char[authCode.length()]; Arrays.fill(masked, '*'); buff.append(new String(masked)); } LOG.debug(buff.toString()); } if (endEntity == null || endEntity.isEmpty()) { renewalFailure(responseData, "Property " + PROPERTY_RENEWENDENTITY + " not specified for worker: " + workerName); } else if (subjectDN == null || subjectDN.isEmpty()) { renewalFailure(responseData, "Property " + PROPERTY_REQUESTDN + " not specified for worker: " + workerName); } else if (sigAlg == null || sigAlg.isEmpty()) { renewalFailure(responseData, "Property " + PROPERTY_SIGNATUREALGORITHM + " not specified for worker: " + workerName); } else if (renewKey && (keyAlg == null || keyAlg.isEmpty())) { renewalFailure(responseData, "Property " + PROPERTY_KEYALG + " not specified for worker: " + workerName); } else if (renewKey && (keySpec == null || keySpec.isEmpty())) { renewalFailure(responseData, "Property " + PROPERTY_KEYSPEC + " not specified for worker: " + workerName); } else { final boolean defaultKey; // (Renew key if specified in request) // OR (if specified in worker but not denied in request) if (renewKey) { // If we renew the key then we want to use that key defaultKey = false; LOG.debug("Will renew key"); // Renew the key nextCertSignKey = renewKey(reneweeId, keyAlg, keySpec, authCode == null ? null : authCode.toCharArray(), logMap); } else { // Request might say that we should use the default key defaultKey = requestForDefaultKey; LOG.debug("Use default key: " + defaultKey); } // Renew worker renewWorker(reneweeId, sigAlg, subjectDN, endEntity, Boolean.valueOf(explicitEccParameters), defaultKey, nextCertSignKey, logMap); responseData.setProperty(RenewalWorkerProperties.RESPONSE_RESULT, RenewalWorkerProperties.RESPONSE_RESULT_OK); // The client can be charged for the request requestContext.setRequestFulfilledByWorker(true); } } catch (Exception ex) { renewalFailure(responseData, ex.getMessage(), ex); } return responseData; } private String renewKey(final int workerId, final String keyAlg, final String keySpec, final char[] authcode, final LogMap logMap) throws Exception { LOG.debug("<renewKey"); if (authcode == null) { throw new IllegalArgumentException("Missing authcode in request"); } final String newAlias = getWorkerSession().generateSignerKey(workerId, keyAlg, keySpec, null, authcode); // Log logMap.put(RenewalWorkerProperties.LOG_GENERATEDKEYALIAS, newAlias); if (LOG.isDebugEnabled()) { LOG.debug("Generated new key: " + newAlias); } final Collection<KeyTestResult> results = getWorkerSession().testKey(workerId, newAlias, authcode); if (results.size() != 1) { throw new CryptoTokenOfflineException("Key testing failed: " + "No result"); } final KeyTestResult result = results.iterator().next(); if (LOG.isDebugEnabled()) { LOG.debug("Key test result: " + result); } if (result.isSuccess()) { // Log logMap.put(RenewalWorkerProperties.LOG_GENERATEDKEYHASH, result.getPublicKeyHash()); getWorkerSession().setWorkerProperty(workerId, NEXTCERTSIGNKEY, newAlias); getWorkerSession().reloadConfiguration(workerId); LOG.debug("Key generated, tested and set"); getWorkerSession().activateSigner(workerId, String.valueOf(authcode)); LOG.debug("Worker activated"); LOG.debug(">renewKey"); return newAlias; } else { throw new CryptoTokenOfflineException("Key testing failed: " + result.getStatus()); } } private void renewWorker(final int workerId, final String sigAlg, final String subjectDN, final String endEntity, final boolean explicitEccParameters, final boolean defaultKey, final String nextCertSignKey, final LogMap logMap) throws Exception { final String pkcs10 = createRequestPEM(workerId, sigAlg, subjectDN, explicitEccParameters, defaultKey); if (LOG.isDebugEnabled()) { LOG.debug("PKCS10: " + pkcs10); } // Connect to EjbcaWS final EjbcaWS ejbcaws = getEjbcaWS(ejbcaWsUrl, alias, truststoreType, truststorePath, truststoreValue, truststorePass); if (ejbcaws == null) { LOG.debug("Could not get EjbcaWS"); } else { LOG.debug("Got EjbcaWS"); final UserMatch usermatch = new UserMatch(); usermatch.setMatchwith(MATCH_WITH_USERNAME); usermatch.setMatchtype(MATCH_TYPE_EQUALS); usermatch.setMatchvalue(endEntity); final List<UserDataVOWS> result = ejbcaws.findUser(usermatch); if (LOG.isDebugEnabled()) { LOG.debug("Got users: " + result); } if (result.isEmpty()) { throw new IllegalArgumentException("End entity not found in EJBCA: " + endEntity); } else { // Update user with status and new password final UserDataVOWS user1 = result.get(0); final char[] password = RandomPasswordGenerator.getInstance().generate(20); if (LOG.isDebugEnabled()) { LOG.debug("Changing to status to NEW from " + user1.getStatus() + " for end entity " + endEntity + "."); } user1.setStatus(STATUS_NEW); user1.setPassword(new String(password)); ejbcaws.editUser(user1); // Send request to CA final CertificateResponse resp = ejbcaws.pkcs10Request(endEntity, new String(password), pkcs10, null, RESPONSETYPE_PKCS7WITHCHAIN); RandomPasswordGenerator.getInstance().fill(password); final String b64Cert = new String(resp.getData()); if (LOG.isDebugEnabled()) { LOG.debug("Got PKCS7: " + b64Cert); } final CMSSignedData signedData = new CMSSignedData(Base64.decode(b64Cert)); final Store certStore = signedData.getCertificates(); final List<X509CertificateHolder> certChain = getCertificateChain( certStore.getMatches(new RenewalWorker.AllSelector())); if (LOG.isDebugEnabled()) { LOG.debug("Got certificates: " + certChain); } final X509CertificateHolder signerCert = getEndEntityCertificate(certChain); if (LOG.isDebugEnabled()) { LOG.debug("New certificate subject DN: " + signerCert.getSubject()); } // Log logMap.put(RenewalWorkerProperties.LOG_NEWCERTISSUERDN, signerCert.getIssuer().toString()); logMap.put(RenewalWorkerProperties.LOG_NEWCERTSERIALNO, signerCert.getSerialNumber().toString(16)); logMap.put(RenewalWorkerProperties.LOG_NEWCERTSUBJECTDN, signerCert.getSubject().toString()); // TODO: Check the certificate // Public key should match // Update worker to use the new certificate getWorkerSession().uploadSignerCertificate(workerId, signerCert.getEncoded(), GlobalConfiguration.SCOPE_GLOBAL); getWorkerSession().uploadSignerCertificateChain(workerId, getCertificateChainBytes(certChain), GlobalConfiguration.SCOPE_GLOBAL); // If not the default key we need to promote the key // Set DEFAULTKEY to NEXTCERTSIGNKEY if (defaultKey) { LOG.debug("Uploaded was for DEFAULTKEY"); } else if (!defaultKey && nextCertSignKey != null) { LOG.debug("Uploaded was for NEXTCERTSIGNKEY"); getWorkerSession().setWorkerProperty(workerId, "DEFAULTKEY", nextCertSignKey); getWorkerSession().removeWorkerProperty(workerId, NEXTCERTSIGNKEY); } getWorkerSession().reloadConfiguration(workerId); LOG.debug("New configuration applied"); } } } public static final String TRUSTSTOREVALUE = "TRUSTSTOREVALUE"; protected IWorkerSession getWorkerSession() { if (workerSession == null) { try { workerSession = ServiceLocator.getInstance().lookupLocal(IWorkerSession.class); } catch (NamingException ex) { throw new RuntimeException("Unable to lookup worker session", ex); } } return workerSession; } private String createRequestPEM(int workerId, final String sigAlg, final String subjectDN, final boolean explicitEccParameters, final boolean defaultKey) throws CryptoTokenOfflineException, InvalidWorkerIdException { final PKCS10CertReqInfo certReqInfo = new PKCS10CertReqInfo(sigAlg, subjectDN, null); final Base64SignerCertReqData reqData = (Base64SignerCertReqData) getWorkerSession() .getCertificateRequest(workerId, certReqInfo, explicitEccParameters, defaultKey); if (reqData == null) { throw new RuntimeException( "Base64SignerCertReqData returned was null." + " Unable to generate certificate request."); } final StringBuilder buff = new StringBuilder(); buff.append("-----BEGIN CERTIFICATE REQUEST-----\n"); buff.append(new String(reqData.getBase64CertReq())); buff.append("\n-----END CERTIFICATE REQUEST-----\n"); return buff.toString(); } private EjbcaWS getEjbcaWS(final String ejbcaUrl, final String alias, final String truststoreType, final String truststorePath, final String truststoreValue, final String truststorePass) throws CryptoTokenOfflineException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, IOException, CertificateException, NoSuchProviderException, KeyManagementException, SignServerException { EjbcaWS result; final String urlstr = ejbcaUrl + WS_PATH; final KeyStore keystore = getCryptoToken().getKeyStore(); // TODO: Check that keystore contains key with the specified alias LOG.info("aliases in keystore follows:"); Enumeration<String> e = keystore.aliases(); while (e.hasMoreElements()) { LOG.info("alias: " + e.nextElement()); } final String keystorePassword = getConfig().getProperty(KeystoreCryptoToken.KEYSTOREPASSWORD); final KeyManagerFactory kKeyManagerFactory = KeyManagerFactory.getInstance("SunX509"); kKeyManagerFactory.init(keystore, keystorePassword != null ? keystorePassword.toCharArray() : null); final KeyStore keystoreTrusted; if (truststoreValue != null) { if (TRUSTSTORE_TYPE_PEM.equals(truststoreType)) { keystoreTrusted = KeyStore.getInstance("JKS"); keystoreTrusted.load(null, null); final Collection certs = CertTools .getCertsFromPEM(new ByteArrayInputStream(truststoreValue.getBytes("UTF-8"))); int i = 0; for (Object o : certs) { if (o instanceof Certificate) { keystoreTrusted.setCertificateEntry("cert-" + i, (Certificate) o); i++; } } if (LOG.isDebugEnabled()) { LOG.debug("Loaded " + i + " certs to truststore"); } } else { if (TRUSTSTORE_TYPE_JKS.equals(truststoreType)) { keystoreTrusted = KeyStore.getInstance(truststoreType); keystoreTrusted.load(new ByteArrayInputStream(Base64.decode(truststoreValue)), truststorePass.toCharArray()); } else { keystoreTrusted = KeyStore.getInstance(truststoreType, "BC"); keystoreTrusted.load(new ByteArrayInputStream(Base64.decode(truststoreValue)), truststorePass.toCharArray()); } } } else { FileInputStream in = null; try { in = new FileInputStream(truststorePath); if (TRUSTSTORE_TYPE_PEM.equals(truststoreType)) { keystoreTrusted = KeyStore.getInstance("JKS"); keystoreTrusted.load(null, null); final Collection certs = CertTools.getCertsFromPEM(in); int i = 0; for (Object o : certs) { if (o instanceof Certificate) { keystoreTrusted.setCertificateEntry("cert-" + i, (Certificate) o); i++; } } if (LOG.isDebugEnabled()) { LOG.debug("Loaded " + i + " certs to truststore"); } } else if (TRUSTSTORE_TYPE_JKS.equals(truststoreType)) { keystoreTrusted = KeyStore.getInstance(truststoreType); keystoreTrusted.load(in, truststorePass.toCharArray()); } else { keystoreTrusted = KeyStore.getInstance(truststoreType, "BC"); keystoreTrusted.load(in, truststorePass.toCharArray()); } } finally { if (in != null) { try { in.close(); } catch (IOException ignored) { } // NOPMD } } } final TrustManagerFactory tTrustManagerFactory = TrustManagerFactory.getInstance("SunX509"); tTrustManagerFactory.init(keystoreTrusted); KeyManager[] keyManagers = kKeyManagerFactory.getKeyManagers(); for (int i = 0; i < keyManagers.length; i++) { if (keyManagers[i] instanceof X509KeyManager) { keyManagers[i] = new AliasKeyManager((X509KeyManager) keyManagers[i], alias); } } // Now construct a SSLContext using these (possibly wrapped) // KeyManagers, and the TrustManagers. We still use a null // SecureRandom, indicating that the defaults should be used. final SSLContext context = SSLContext.getInstance("TLS"); context.init(keyManagers, tTrustManagerFactory.getTrustManagers(), new SecureRandom()); // Finally, we get a SocketFactory, and pass it to SimpleSSLClient. SSLSocketFactory factory = context.getSocketFactory(); HttpsURLConnection.setDefaultSSLSocketFactory(factory); // TODO: This could if multiple renewal workers are used LOG.info("Getting WS"); EjbcaWSService service = new EjbcaWSService(new URL(urlstr), new QName("http://ws.protocol.core.ejbca.org/", "EjbcaWSService")); result = service.getEjbcaWSPort(); return result; } // TODO: We are assuming here that a CA certificate is not used for signing private static X509CertificateHolder getEndEntityCertificate( final Collection<? extends X509CertificateHolder> certs) { X509CertificateHolder result = null; for (X509CertificateHolder cert : certs) { Extension extension = cert.getExtension(X509Extension.basicConstraints); if (extension == null) { result = cert; break; } else { BasicConstraints bc = BasicConstraints.getInstance(extension.getParsedValue()); if (!bc.isCA()) { result = cert; break; } } } return result; } // TODO: We are not ordering this chain and assumes that is not important private static List<X509CertificateHolder> getCertificateChain(final Collection certs) { final LinkedList<X509CertificateHolder> result = new LinkedList<X509CertificateHolder>(); for (Object cert : certs) { if (cert instanceof X509CertificateHolder) { result.add((X509CertificateHolder) cert); } } return result; } private static List<byte[]> getCertificateChainBytes(final Collection<? extends X509CertificateHolder> certs) throws CertificateEncodingException, IOException { final LinkedList<byte[]> result = new LinkedList<byte[]>(); for (X509CertificateHolder cert : certs) { result.add(cert.getEncoded()); } return result; } private void renewalFailure(final Properties responseData, final String message) { renewalFailure(responseData, message, null); } private void renewalFailure(final Properties responseData, final String message, final Throwable ex) { LOG.error(message, ex); responseData.setProperty(RenewalWorkerProperties.RESPONSE_RESULT, RenewalWorkerProperties.RESPONSE_RESULT_FAILURE); responseData.setProperty(RenewalWorkerProperties.RESPONSE_MESSAGE, message == null ? "" : message); } class AliasKeyManager implements X509KeyManager { private final X509KeyManager base; private final String alias; public AliasKeyManager(final X509KeyManager base, final String alias) { this.base = base; this.alias = alias; } @Override public String[] getClientAliases(String string, Principal[] prncpls) { return base.getClientAliases(string, prncpls); } @Override public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { return alias; } @Override public String[] getServerAliases(String string, Principal[] prncpls) { return base.getClientAliases(string, prncpls); } @Override public String chooseServerAlias(String string, Principal[] prncpls, Socket socket) { return base.chooseServerAlias(string, prncpls, socket); } @Override public X509Certificate[] getCertificateChain(String string) { try { final List<Certificate> chain = getSigningCertificateChain(); return chain.toArray(new X509Certificate[chain.size()]); } catch (CryptoTokenOfflineException ex) { LOG.error("Offline getting chain", ex); return new X509Certificate[0]; } } @Override public PrivateKey getPrivateKey(String string) { final PrivateKey key = base.getPrivateKey(string); return key; } } /** * Simply matches true on all objects found. */ private static class AllSelector implements Selector { @Override public boolean match(Object obj) { return true; } @Override public Object clone() { return new RenewalWorker.AllSelector(); } } @Override protected List<String> getFatalErrors() { final List<String> errors = super.getFatalErrors(); errors.addAll(getLocalFatalErrors()); return errors; } /** * Internal method used by the unit test to get locally * added fatal errors, bypassing the token setup in BaseProcessable. * * @return List of fatal errors added in this class. */ List<String> getLocalFatalErrors() { return fatalErrors; } }