package at.gv.egovernment.moa.spss.server.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.traversal.NodeIterator;
import org.xml.sax.SAXException;
import iaik.ixsil.exceptions.URIException;
import iaik.ixsil.util.URI;
import iaik.pki.pathvalidation.ChainingModes;
import iaik.pki.revocation.RevocationSourceTypes;
import iaik.utils.RFC2253NameParser;
import iaik.utils.RFC2253NameParserException;
import at.gv.egovernment.moa.logging.LogMsg;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.XPathUtils;
import at.gv.egovernment.moa.spss.util.MessageProvider;
/**
* A class that builds configuration data from a DOM based representation.
*
* @author Patrick Peck
* @version $Id$
*/
public class ConfigurationPartsBuilder {
//
// XPath namespace prefix shortcuts
//
private static final String CONF = Constants.MOA_CONFIG_PREFIX + ":";
private static final String DSIG = Constants.DSIG_PREFIX + ":";
//
// chaining mode constants appearing in the configuration file
//
private static final String CM_CHAINING = "chaining";
private static final String CM_PKIX = "pkix";
//
// XPath expressions to select certain parts of the configuration
//
private static final String ROOT = "/" + CONF + "MOAConfiguration/";
private static final String DIGEST_METHOD_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "XMLDSig/"
+ CONF + "DigestMethodAlgorithm";
private static final String C14N_ALGORITHM_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "XMLDSig/"
+ CONF + "CanonicalizationAlgorithm";
private static final String HARDWARE_CRYPTO_MODULE_XPATH =
ROOT + CONF + "Common/"
+ CONF + "HardwareCryptoModule";
private static final String HARDWARE_KEY_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "KeyModules/"
+ CONF + "HardwareKeyModule";
private static final String SOFTWARE_KEY_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "KeyModules/"
+ CONF + "SoftwareKeyModule";
private static final String KEYGROUP_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "KeyGroup";
private static final String KEYGROUP_MAPPING_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "KeyGroupMapping";
private static final String ISSUER_XPATH =
DSIG + "X509IssuerName";
private static final String SERIAL_XPATH =
DSIG + "X509SerialNumber";
private static final String CERTSTORE_LOCATION_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "PathConstruction/"
+ CONF + "CertificateStore/"
+ CONF + "DirectoryStore/"
+ CONF + "Location";
private static final String AUTO_ADD_CERTIFICATES_XPATH_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "PathConstruction/"
+ CONF + "AutoAddCertificates";
private static final String USE_AUTHORITY_INFO_ACCESS_XPATH_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "PathConstruction/"
+ CONF + "UseAuthorityInformationAccess";
private static final String CHAINING_MODES_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "PathValidation/"
+ CONF + "ChainingMode";
private static final String CHAINING_MODES_DEFAULT_XPATH =
CHAINING_MODES_XPATH + "/"
+ CONF + "DefaultMode";
private static final String TRUST_ANCHOR_XPATH =
CHAINING_MODES_XPATH + "/"
+ CONF + "TrustAnchor";
private static final String TRUST_PROFILE_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "PathValidation/"
+ CONF + "TrustProfile";
private static final String DISTRIBUTION_POINTS_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "DistributionPoint";
private static final String ENABLE_REVOCATION_CHECKING_XPATH_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "EnableChecking";
private static final String MAX_REVOCATION_AGE_XPATH_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "MaxRevocationAge";
private static final String REVOCATION_SERVICEORDER_XPATH_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "ServiceOrder/"
+ CONF + "Service";
private static final String ENABLE_ARCHIVING_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "Archiving/"
+ CONF + "EnableArchiving";
private static final String CRL_ARCHIVE_DURATION_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "Archiving/"
+ CONF + "ArchiveDuration";
private static final String ACHIVE_JDBC_URL_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "Archiving/"
+ CONF + "Archive/"
+ CONF + "DatabaseArchive/"
+ CONF + "JDBCURL";
private static final String ACHIVE_JDBC_DRIVER_CLASS_ =
ROOT + CONF + "SignatureVerification/"
+ CONF + "CertificateValidation/"
+ CONF + "RevocationChecking/"
+ CONF + "Archiving/"
+ CONF + "Archive/"
+ CONF + "DatabaseArchive/"
+ CONF + "JDBCDriverClassName";
private static final String CREATE_TRANSFORMS_INFO_PROFILE_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "CreateTransformsInfoProfile";
private static final String CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH =
ROOT + CONF + "SignatureCreation/"
+ CONF + "CreateSignatureEnvironmentProfile";
private static final String VERIFY_TRANSFORMS_INFO_PROFILE_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "VerifyTransformsInfoProfile";
private static final String SUPPLEMENT_PROFILE_XPATH =
ROOT + CONF + "SignatureVerification/"
+ CONF + "SupplementProfile";
//
// default values for configuration parameters
//
/** The accepted canonicalization algorithm URIs, as an array */
private static final String[] ACCEPTED_C14N_ALGORITHMS_ARRAY =
{
Constants.C14N_URI,
Constants.C14N_WITH_COMMENTS_URI,
Constants.EXC_C14N_URI,
Constants.EXC_C14N_WITH_COMMENTS_URI };
/** The accepted canonicalization algorithm URIs, as a Set */
private static final Set ACCEPTED_C14N_ALGORITHMS =
new HashSet(Arrays.asList(ACCEPTED_C14N_ALGORITHMS_ARRAY));
/** Default canonicalization algorithm, if none/illegal has been configured */
private static final String C14N_ALGORITHM_DEFAULT = Constants.C14N_URI;
/** The accepted digest method algorithm URIs, as an array */
private static final String[] ACCEPTED_DIGEST_ALGORITHMS_ARRAY =
{ Constants.SHA1_URI };
/** The accepted digest method algorithm URIs, as a Set */
private static final Set ACCEPTED_DIGEST_ALGORITHMS =
new HashSet(Arrays.asList(ACCEPTED_DIGEST_ALGORITHMS_ARRAY));
/** Default digest algorithm URI, if none/illegal has been configured */
private static final String DIGEST_ALGORITHM_DEFAULT = Constants.SHA1_URI;
/** The root element of the MOA configuration */
private Element configElem;
/**
* The directory containing the underlying configuration file.
*/
private File configRoot_;
/** Whether any warnings were encountered building the configuration. */
private List warnings = new ArrayList();
/**
* Create a new ConfigurationPartsBuilder
.
*
* @param configElem The root element of the MOA configuration.
*
* @param configRoot The directory containing the underlying configuration file.
*/
public ConfigurationPartsBuilder(Element configElem, File configRoot)
{
this.configElem = configElem;
configRoot_ = configRoot;
}
/**
* Returns the root element of the MOA configuration.
*
* @return The root element of the MOA configuration.
*/
public Element getConfigElem() {
return configElem;
}
/**
* Returns the directory containing the underlying configuration file.
*
* @return the directory containing the underlying configuration file.
*/
public File getConfigRoot()
{
return configRoot_;
}
/**
* Returns the warnings encountered during building the configuration.
*
* @return A List
of String
s, containing the
* warning messages.
*/
public List getWarnings() {
return warnings;
}
/**
* Returns the digest method algorithm name.
*
* @return The digest method algorithm name from the configuration.
*/
public String getDigestMethodAlgorithmName()
{
String digestMethod = getElementValue(getConfigElem(), DIGEST_METHOD_XPATH, null);
if (digestMethod == null || !ACCEPTED_DIGEST_ALGORITHMS.contains(digestMethod))
{
info(
"config.23",
new Object[] { "DigestMethodAlgorithm", DIGEST_ALGORITHM_DEFAULT });
digestMethod = DIGEST_ALGORITHM_DEFAULT;
}
return digestMethod;
}
/**
* Returns the canonicalization algorithm name.
*
* @return The canonicalization algorithm name from the configuration.
*/
public String getCanonicalizationAlgorithmName()
{
String c14nAlgorithm = getElementValue(getConfigElem(), C14N_ALGORITHM_XPATH, null);
if (c14nAlgorithm == null || !ACCEPTED_C14N_ALGORITHMS.contains(c14nAlgorithm))
{
info(
"config.23",
new Object[] { "CanonicalizationAlgorithm", C14N_ALGORITHM_DEFAULT });
c14nAlgorithm = C14N_ALGORITHM_DEFAULT;
}
return c14nAlgorithm;
}
/**
* Build the configured hardware crypto modules.
*
* @return The hardware crypto modules from the configuration.
*/
public List buildHardwareCryptoModules()
{
List modules = new ArrayList();
NodeIterator modIter = XPathUtils.selectNodeIterator(
getConfigElem(),
HARDWARE_CRYPTO_MODULE_XPATH);
Element modElem;
while ((modElem = (Element) modIter.nextNode()) != null) {
String name = getElementValue(modElem, CONF + "Name", null);
String slotId = getElementValue(modElem, CONF + "SlotId", null);
String userPIN = getElementValue(modElem, CONF + "UserPIN", null);
HardwareCryptoModule module = new HardwareCryptoModule(name, slotId, userPIN);
modules.add(module);
}
return modules;
}
/**
* Build the configured hardware keys.
*
* @param keyModules The keyModules that the configuration already knows about. To
* prevent multiple key modules with the same ID.
* @return The hardware keys contained in the configuration.
*/
public List buildHardwareKeyModules(List keyModules)
{
Set existingIds = toIdSet(keyModules);
List hardwareKeys = new ArrayList();
NodeIterator hkIter =
XPathUtils.selectNodeIterator(getConfigElem(), HARDWARE_KEY_XPATH);
Element keyElem;
while ((keyElem = (Element) hkIter.nextNode()) != null)
{
String id = getElementValue(keyElem, CONF + "Id", null);
String name = getElementValue(keyElem, CONF + "Name", null);
String slotId = getElementValue(keyElem, CONF + "SlotId", null);
String userPIN = getElementValue(keyElem, CONF + "UserPIN", null);
if (existingIds.contains(id))
{
warn(
"config.04",
new Object[] { "Hardware- oder SoftwareKeyModule", id });
}
else
{
KeyModule key = new HardwareKeyModule(id, name, slotId, userPIN);
hardwareKeys.add(key);
existingIds.add(id);
}
}
return hardwareKeys;
}
/**
* Build the configured software keys.
*
* @param keyModules The keyModules that the configuration already knows about. To
* prevent multiple key modules with the same ID.
*
* @return The software keys contained in the configuration.
*/
public List buildSoftwareKeyModules(List keyModules)
{
Set existingIds = toIdSet(keyModules);
List softwareKeys = new ArrayList();
NodeIterator skIter =
XPathUtils.selectNodeIterator(getConfigElem(), SOFTWARE_KEY_XPATH);
Element keyElem;
while ((keyElem = (Element) skIter.nextNode()) != null)
{
String id = getElementValue(keyElem, CONF + "Id", null);
String fileName = getElementValue(keyElem, CONF + "FileName", null);
String passWord = getElementValue(keyElem, CONF + "Password", null);
if (existingIds.contains(id))
{
warn(
"config.04",
new Object[] { "Hardware- oder SoftwareKeyModule", id });
}
else
{
File keyFile;
KeyModule key;
// make keyFile absolute
keyFile = new File(fileName);
if (!keyFile.isAbsolute()) {
keyFile = new File(configRoot_, fileName);
}
// check for existence
if (!keyFile.exists() || keyFile.isDirectory()) {
warn("config.25", new Object[] { id, keyFile.getAbsolutePath()});
} else {
// create a new key module
key = new SoftwareKeyModule(id, keyFile.getAbsolutePath(), passWord);
softwareKeys.add(key);
existingIds.add(id);
}
}
}
return softwareKeys;
}
/**
* Build the key group configuration.
*
* @param keyModules The KeyModule
s that the configuration
* knows about. Used to check for errors in the configuration.
* @return The mapping between key group IDs and key groups.
*/
public Map buildKeyGroups(List keyModules)
{
Set keyModuleIds = toIdSet(keyModules);
Map keyGroups = new HashMap();
NodeIterator kgIter;
Element keyGroupElem;
// select all KeyGroup elements and build the KeyGroup objects from them
kgIter = XPathUtils.selectNodeIterator(getConfigElem(), KEYGROUP_XPATH);
while ((keyGroupElem = (Element) kgIter.nextNode()) != null)
{
String keyGroupId = getElementValue(keyGroupElem, CONF + "Id", null);
Set keyGroupEntries =
buildKeyGroupEntries(keyGroupId, keyModuleIds, keyGroupElem);
KeyGroup keyGroup = new KeyGroup(keyGroupId, keyGroupEntries);
if (keyGroups.containsKey(keyGroupId))
{
warn("config.04", new Object[] { "KeyGroup", keyGroupId });
}
else
{
keyGroups.put(keyGroup.getId(), keyGroup);
}
}
return keyGroups;
}
/**
* Return the set of IDs contained in the given KeyModule
s.
*
* @param keyModules The KeyModule
s from which to extract the
* IDs.
* @return The IDs from the given KeyModule
s.
*/
private Set toIdSet(List keyModules) {
Set ids = new HashSet();
Iterator iter;
for (iter = keyModules.iterator(); iter.hasNext();) {
KeyModule keyModule = (KeyModule) iter.next();
ids.add(keyModule.getId());
}
return ids;
}
/**
* Build the key entries belonging to a key group.
*
* @param keyGroupId The ID of the key group we are building here. Passed
* for logging purposes.
* @param keyModuleIds The IDs of the HardwareKeyModule
s and
* SoftwareKeyModule
s that exist in the configuration.
* @param keyGroupElem The KeyGroup
DOM element to parse.
* @return A Set
of KeyGroupEntry
objects.
*/
private Set buildKeyGroupEntries(
String keyGroupId,
Set keyModuleIds,
Element keyGroupElem) {
Set entries = new HashSet();
NodeIterator keyEntryIter;
Element keyEntryElem;
// select all Key elements and put them into the Map
keyEntryIter = XPathUtils.selectNodeIterator(keyGroupElem, CONF + "Key");
while ((keyEntryElem = (Element) keyEntryIter.nextNode()) != null)
{
String keyModuleId = getElementValue(keyEntryElem, CONF + "KeyModuleId", "");
Element keyCertElem = (Element) XPathUtils.selectSingleNode(keyEntryElem, CONF + "KeyCertIssuerSerial");
IssuerAndSerial issuerSerial = buildIssuerAndSerial(keyCertElem);
if (!keyModuleIds.contains(keyModuleId)) {
warn("config.26", new Object[] { keyGroupId, keyModuleId });
} else if (issuerSerial != null) {
KeyGroupEntry entry = new KeyGroupEntry(keyModuleId, issuerSerial);
entries.add(entry);
}
}
return entries;
}
/**
* Build the key group mapping.
*
* @param keyGroups The available key groups.
* @param anonymous The IssuerAndSerial
to be used for key group
* mappings not protected by a certificate.
* @return The key group mapping.
*/
public Map buildKeyGroupMappings(Map keyGroups, IssuerAndSerial anonymous) {
Map mappings = new HashMap();
NodeIterator mappingIter;
Element mappingElem;
// select all KeyGroupMapping elements
mappingIter =
XPathUtils.selectNodeIterator(getConfigElem(), KEYGROUP_MAPPING_XPATH);
// build the mapping for each KeyGroupMapping element
while ((mappingElem = (Element) mappingIter.nextNode()) != null)
{
Element issuerSerialElem = (Element) XPathUtils.selectSingleNode(mappingElem, CONF + "CustomerId");
// build the IssuerAndSerial who has access to the key groups
IssuerAndSerial issuerAndSerial;
if (issuerSerialElem != null)
{
issuerAndSerial = buildIssuerAndSerial(issuerSerialElem);
}
else
{
// IssuerSerial element: the keygroup is generally available
issuerAndSerial = anonymous;
}
// add the key groups to the mappings
if (issuerAndSerial != null) {
Map groups = (Map) mappings.get(issuerAndSerial);
NodeIterator keyGroupIter;
Element keyGroupElem;
if (groups == null)
{
// no mapping exist -> build one
groups = new HashMap();
mappings.put(issuerAndSerial, groups);
}
// select the available key groups and add them to the mapping
keyGroupIter = XPathUtils.selectNodeIterator(mappingElem, CONF + "KeyGroupId");
while ((keyGroupElem = (Element) keyGroupIter.nextNode()) != null)
{
String keyGroupId = getElementValue(keyGroupElem, ".", null);
KeyGroup keyGroup = (KeyGroup) keyGroups.get(keyGroupId);
if (keyGroup != null)
{
groups.put(keyGroupId, keyGroup);
} else
{
warn("config.00", new Object[] { keyGroupId });
}
}
}
}
return mappings;
}
/**
* Returns the default chaining mode from the configuration.
*
* @return The default chaining mode.
*/
public String getDefaultChainingMode()
{
String defaultChaining = getElementValue(
getConfigElem(),
CHAINING_MODES_DEFAULT_XPATH,
CM_PKIX);
return translateChainingMode(defaultChaining);
}
/**
* Build the chaining modes for all configured trust anchors.
*
* @return The mapping from trust anchors to chaining modes.
*/
public Map buildChainingModes()
{
Map chainingModes = new HashMap();
NodeIterator trustIter = XPathUtils.selectNodeIterator(getConfigElem(), TRUST_ANCHOR_XPATH);
Element trustAnchorElem;
while ((trustAnchorElem = (Element) trustIter.nextNode()) != null)
{
IssuerAndSerial issuerAndSerial = buildIssuerAndSerial(
(Element)XPathUtils.selectSingleNode(trustAnchorElem, CONF + "Identification"));
String mode = getElementValue(trustAnchorElem, CONF + "Mode", null);
if (issuerAndSerial != null)
{
chainingModes.put(issuerAndSerial, translateChainingMode(mode));
}
}
return chainingModes;
}
/**
* Build an IssuerAndSerial
from the DOM representation.
*
* @param root The root element (being of type dsig:
* X509IssuerSerialType
.
* @return The issuer and serial number contained in the root
* element or null
if could not be built for any reason.
*/
private IssuerAndSerial buildIssuerAndSerial(Element root) {
String issuer = getElementValue(root, ISSUER_XPATH, null);
String serial = getElementValue(root, SERIAL_XPATH, null);
if (issuer != null && serial != null) {
try {
RFC2253NameParser nameParser = new RFC2253NameParser(issuer);
Principal issuerDN = nameParser.parse();
return new IssuerAndSerial(issuerDN, new BigInteger(serial));
} catch (RFC2253NameParserException e) {
warn("config.16", new Object[] { issuer, serial }, e);
return null;
} catch (NumberFormatException e) {
warn("config.16", new Object[] { issuer, serial }, e);
return null;
}
}
return null;
}
/**
* Translate the chaining mode from the configuration file to one used in the
* IAIK MOA API.
*
* @param chainingMode The chaining mode from the configuration.
* @return The chaining mode as provided by the ChainingModes
* interface.
* @see iaik.pki.pathvalidation.ChainingModes
*/
private String translateChainingMode(String chainingMode) {
if (chainingMode.equals(CM_CHAINING)) {
return ChainingModes.CHAIN_MODE;
} else if (chainingMode.equals(CM_PKIX)) {
return ChainingModes.PKIX_MODE;
} else {
return ChainingModes.PKIX_MODE;
}
}
/**
* Build the distribution points mapping.
*
* @return The mapping from certificate authorities to distribution points.
*/
public Map buildDistributionPoints()
{
Map dPs = new HashMap();
NodeIterator dPIter;
Element dPElem;
// select all DistributionPoint elements
dPIter = XPathUtils.selectNodeIterator(getConfigElem(), DISTRIBUTION_POINTS_XPATH);
// build the mapping of CA name to distribution points
while ((dPElem = (Element) dPIter.nextNode()) != null) {
String caIssuerDNText = getElementValue(dPElem, CONF + "CAIssuerDN", "");
RFC2253NameParser nameParser = new RFC2253NameParser(caIssuerDNText);
NodeIterator cRLDPIter = XPathUtils.selectNodeIterator(dPElem, CONF + "CRLDP");
NodeIterator oCSPDPPIter = XPathUtils.selectNodeIterator(dPElem, CONF + "OCSPDP");
try
{
String caIssuerDN = nameParser.parse().getName();
// check, if a mapping exists or make a new mapping
Set dPsForCA = (Set) dPs.get(caIssuerDN);
if (dPsForCA == null)
{
dPsForCA = new HashSet();
dPs.put(caIssuerDN, dPsForCA);
}
// add the CRL distribution points of this CA to the set
Element cRLDPElem;
while ((cRLDPElem = (Element) cRLDPIter.nextNode()) != null)
{
CRLDistributionPoint cRLDP = (CRLDistributionPoint) buildDistributionPoint(cRLDPElem, caIssuerDN);
dPsForCA.add(cRLDP);
}
// add the OCSP distribution points of this CA to the set
Element oCSPPElem;
while ((oCSPPElem = (Element) oCSPDPPIter.nextNode()) != null)
{
OCSPDistributionPoint oCSPDP = (OCSPDistributionPoint) buildDistributionPoint(oCSPPElem, null);
dPsForCA.add(oCSPDP);
}
}
catch (RFC2253NameParserException e)
{
warn("config.13", new Object[] { caIssuerDNText }, e);
}
}
return dPs;
}
/**
* Build a distribution point from the DOM representation.
*
* @param dpElem The root element of the distribution point.
*
* @param issuerName The name of the CA issuing the CRL referred to by this DP, or null
* if this DP refers to an OCSP responder.
*
* @return The distribution point.
*/
private DistributionPoint buildDistributionPoint(Element dpElem, String issuerName)
{
String uri = getElementValue(dpElem, CONF + "Location", null);
if ("CRLDP".equals(dpElem.getLocalName()))
{
NodeIterator reasonCodesIter = XPathUtils.selectNodeIterator(dpElem, CONF + "ReasonCode");
Element reasonCodeElem;
StringBuffer reasonCodesSB = new StringBuffer();
while ((reasonCodeElem = (Element)reasonCodesIter.nextNode()) != null)
{
if (reasonCodesSB.length() > 0) reasonCodesSB.append(" ");
reasonCodesSB.append(getElementValue(reasonCodeElem, ".", "").trim());
}
return new CRLDistributionPoint(issuerName, uri, reasonCodesSB.toString());
}
else
{
return new OCSPDistributionPoint(uri);
}
}
/**
* Return the CRL archive duration.
*
* @return The value of the CRL archive duration setting from the configuration, or 0
if
* no value is set in the configuration.
*/
public int getRevocationArchiveDuration()
{
String archiveDuration = getElementValue(getConfigElem(), CRL_ARCHIVE_DURATION_XPATH, null);
try
{
return Integer.parseInt(archiveDuration);
}
catch (NumberFormatException e)
{
warn("config.01", null);
return 365;
}
}
/**
* Build the CreateTransformsInfoProfile
s.
*
* @return The mapping from profile ID to profile.
*/
public Map buildCreateTransformsInfoProfiles()
{
return loadProfiles(CREATE_TRANSFORMS_INFO_PROFILE_XPATH, "CreateTransformsInfoProfile");
}
/**
* Build the CreateSignatureEnvironmentProfile
s.
*
* @return The mapping from profile ID to profile.
*/
public Map buildCreateSignatureEnvironmentProfiles()
{
return loadProfiles(CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH, "CreateSignatureEnvironmentProfile");
}
/**
* Build the VerifyTransformsInfoProfile
s.
*
* @return The mapping from profile ID to profile.
*/
public Map buildVerifyTransformsInfoProfiles()
{
return loadProfiles(VERIFY_TRANSFORMS_INFO_PROFILE_XPATH, "VerifyTransformsInfoProfile");
}
/**
* Build the SupplementProfile
s.
*
* @return The mapping from profile ID to profile.
*/
public Map buildSupplementProfiles()
{
return loadProfiles(SUPPLEMENT_PROFILE_XPATH, "SupplementProfile");
}
/**
* Load a profile mapping.
*
* @param xpath The XPath to select the profiles from the configuration.
*
* @param profileRoot The name of the profile root element.
*
* @return Map The profile ID to profile mapping.
*/
private Map loadProfiles(String xpath, String profileRoot)
{
Map profiles = new HashMap();
NodeIterator profileIter = XPathUtils.selectNodeIterator(getConfigElem(), xpath);
Element profileElem;
while ((profileElem = (Element) profileIter.nextNode()) != null)
{
String id = getElementValue(profileElem, CONF + "Id", null);
String fileName = getElementValue(profileElem, CONF + "Location", null);
if (profiles.containsKey(id))
{
warn("config.04", new Object[] { profileRoot, id });
}
else
{
try
{
File profileFile = new File(fileName);
// make profileFile absolute
if (!profileFile.isAbsolute()) profileFile = new File(configRoot_, fileName);
// load the profile
info("config.22", new Object[] { profileRoot, id, profileFile.getAbsoluteFile()});
Element profile = loadProfile(profileFile);
if (profile.getTagName().equals(profileRoot))
{
profiles.put(id, profile);
}
else
{
warn("config.02", new Object[] { profileRoot, id, fileName });
}
} catch (ConfigurationException e) {
warn("config.03", new Object[] { profileRoot, id });
}
}
}
return profiles;
}
/**
* Load a profile from a file.
*
* @param root The absolute directory path of the main configuration file.
* @param profileFile The file containing the profile.
* @return The profile in its DOM representation.
* @throws ConfigurationException An error occurred loading the profile.
*/
private Element loadProfile(File profileFile) throws ConfigurationException {
Element profile;
try {
profile = parseXml(new FileInputStream(profileFile));
} catch (Exception e) {
throw new ConfigurationException("config.12", null, e);
}
return profile;
}
/**
* Bulid the trust profile mapping.
*
* @return The profile ID to profile mapping.
*/
public Map buildTrustProfiles()
{
Map trustProfiles = new HashMap();
NodeIterator profileIter = XPathUtils.selectNodeIterator(getConfigElem(), TRUST_PROFILE_XPATH);
Element profileElem;
while ((profileElem = (Element) profileIter.nextNode()) != null)
{
String id = getElementValue(profileElem, CONF + "Id", null);
String trustAnchorsLocStr = getElementValue(profileElem, CONF + "TrustAnchorsLocation", null);
String signerCertsLocStr = getElementValue(profileElem, CONF + "SignerCertsLocation", null);
URI trustAnchorsLocURI = null;
try
{
trustAnchorsLocURI = new URI(trustAnchorsLocStr);
if (!trustAnchorsLocURI.isAbsolute()) { // make it absolute to the config file
trustAnchorsLocURI = new URI(configRoot_.toURL() + trustAnchorsLocStr);
}
}
catch (URIException e) {
warn("config.14", new Object[] { "uri", id, trustAnchorsLocStr }, e);
continue;
}
catch (MalformedURLException e)
{
warn("config.15", new Object[] {id}, e);
continue;
}
File profileDir = new File(trustAnchorsLocURI.getPath());
if (!profileDir.exists() || !profileDir.isDirectory()) {
warn("config.27", new Object[] { "uri", id });
continue;
}
if (trustProfiles.containsKey(id)) {
warn("config.04", new Object[] { "TrustProfile", id });
continue;
}
URI signerCertsLocURI = null;
if (signerCertsLocStr != null && !"".equals(signerCertsLocStr))
{
try
{
signerCertsLocURI = new URI(signerCertsLocStr);
if (!signerCertsLocURI.isAbsolute()) signerCertsLocURI = new URI(configRoot_.toURL() + signerCertsLocStr);
File signerCertsDir = new File(signerCertsLocURI.getPath());
if (!signerCertsDir.exists() || !signerCertsDir.isDirectory()) {
warn("config.27", new Object[] { "signerCertsUri", id });
continue;
}
}
catch (URIException e) {
warn("config.14", new Object[] { "signerCertsUri", id, trustAnchorsLocStr }, e);
continue;
}
catch (MalformedURLException e) {
warn("config.15", new Object[] {id}, e);
continue;
}
}
signerCertsLocStr = (signerCertsLocURI != null) ? signerCertsLocURI.toString() : null;
TrustProfile profile = new TrustProfile(id, trustAnchorsLocURI.toString(), signerCertsLocStr);
trustProfiles.put(id, profile);
}
return trustProfiles;
}
/**
* Returns the location of the certificate store.
*
* @return the location of the certificate store.
*/
public String getCertStoreLocation()
{
String certStoreLocStr = getElementValue(getConfigElem(), CERTSTORE_LOCATION_XPATH, null);
File certStoreLocFile;
// No value specified in configuration file: Set it to a reasonable (absolute) default
if (certStoreLocStr == null)
return new File(configRoot_, "certstore").getAbsolutePath();
// Make cert store location an absolute value
certStoreLocFile = new File(certStoreLocStr);
if (!certStoreLocFile.isAbsolute())
{
certStoreLocFile = new File(configRoot_, certStoreLocStr);
}
// Check if cert store location exists, eventually try to create it
if (!certStoreLocFile.isDirectory())
{
boolean created = false;
try
{
created = certStoreLocFile.mkdirs();
}
finally
{
if (!created)
{
warn("config.32", new Object[] { certStoreLocFile.getAbsolutePath() });
}
}
}
return certStoreLocFile.getAbsolutePath();
}
//
// various utility methods
//
/**
* Parse a configuration XML file.
*
* @param inputStream The stream from which to read the XML data.
* @return The DOM representation of the XML data.
* @throws ParserConfigurationException XML parser not configured properly.
* @throws SAXException An error parsing the XML file.
* @throws IOException An error reading the stream.
*/
private static Element parseXml(InputStream inputStream)
throws ParserConfigurationException, SAXException, IOException {
return DOMUtils
.parseDocument(inputStream, true, Constants.ALL_SCHEMA_LOCATIONS, null)
.getDocumentElement();
}
/**
* Return the value of an element located by an XPath.
*
* @param root The root element from which to evaluate the xpath
.
* @param xpath The XPath pointing to the element.
* @param def The default value, if no element can be found with the given
* xpath
.
* @return The element value or def
, if the element cannot be
* found.
*/
private String getElementValue(Element root, String xpath, String def) {
Element elem = (Element) XPathUtils.selectSingleNode(root, xpath);
return elem != null ? DOMUtils.getText(elem) : def;
}
/**
* Return the value of an attribute located by an XPath.
*
* @param root The root element from which to evaluate the xpath
.
* @param xpath The XPath pointing to the attribute.
* @param def The default value, if no attribute can be found with the given
* xpath
.
* @return The element value or def
, if the attribute cannot be
* found.
*/
private String getAttributeValue(Element root, String xpath, String def) {
Attr attr = (Attr) XPathUtils.selectSingleNode(root, xpath);
return attr != null ? attr.getValue() : def;
}
/**
* Log an info message.
*
* @param messageId The message ID.
* @param parameters Additional parameters for the message.
* @see at.gv.egovernment.moa.spss.server.util.MessageProvider
*/
private static void info(String messageId, Object[] parameters) {
MessageProvider msg = MessageProvider.getInstance();
Logger.info(new LogMsg(msg.getMessage(messageId, parameters)));
}
/**
* Log a warning.
*
* @param messageId The message ID.
* @param args Additional parameters for the message.
* @see at.gv.egovernment.moa.spss.server.util.MessageProvider
*/
private void warn(String messageId, Object[] args) {
MessageProvider msg = MessageProvider.getInstance();
String txt = msg.getMessage(messageId, args);
Logger.warn(new LogMsg(txt));
warnings.add(txt);
}
/**
* Log a warning.
*
* @param messageId The message ID.
* @param args Additional parameters for the message.
* @param t An exception being the cause of the warning.
* @see at.gv.egovernment.moa.spss.server.util.MessageProvider
*/
private void warn(String messageId, Object[] args, Throwable t) {
MessageProvider msg = MessageProvider.getInstance();
String txt = msg.getMessage(messageId, args);
Logger.warn(new LogMsg(txt), t);
warnings.add(txt);
}
/**
* Returns whether revocation information should be archived.
*
* @return whether revocation information should be archived.
*/
public boolean getEnableRevocationArchiving()
{
String enableArchiving = getElementValue(getConfigElem(), ENABLE_ARCHIVING_XPATH, null);
return Boolean.valueOf(enableArchiving).booleanValue();
}
/**
* Returns the JDBC URL for the revocation archive database.
*
* @return the JDBC URL for the revocation archive database, or null
null