aboutsummaryrefslogtreecommitdiff
path: root/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java')
-rw-r--r--spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java1305
1 files changed, 1305 insertions, 0 deletions
diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java
new file mode 100644
index 000000000..9e0dc7688
--- /dev/null
+++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java
@@ -0,0 +1,1305 @@
+/*
+* Copyright 2003 Federal Chancellery Austria
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+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.asn1.structures.Name;
+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 CRL_RETENTION_INTERVALS_CA_XPATH =
+ ROOT + CONF + "SignatureVerification/"
+ + CONF + "CertificateValidation/"
+ + CONF + "RevocationChecking/"
+ + CONF + "CrlRetentionIntervals/"
+ + CONF + "CA";
+ 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";
+ private static final String PERMIT_FILE_URIS_XPATH =
+ ROOT + CONF + "SignatureVerification/"
+ + CONF + "PermitFileURIs";
+ //
+ // 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 <code>ConfigurationPartsBuilder</code>.
+ *
+ * @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 <code>List</code> of <code>String</code>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 <code>KeyModule</code>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 <code>KeyModule</code>s.
+ *
+ * @param keyModules The <code>KeyModule</code>s from which to extract the
+ * IDs.
+ * @return The IDs from the given <code>KeyModule</code>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 <code>HardwareKeyModule</code>s and
+ * <code>SoftwareKeyModule</code>s that exist in the configuration.
+ * @param keyGroupElem The <code>KeyGroup</code> DOM element to parse.
+ * @return A <code>Set</code> of <code>KeyGroupEntry</code> 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 <code>IssuerAndSerial</code> 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 <code>IssuerAndSerial</code> from the DOM representation.
+ *
+ * @param root The root element (being of type <code>dsig:
+ * X509IssuerSerialType</code>.
+ * @return The issuer and serial number contained in the <code>root</code>
+ * element or <code>null</code> 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 <code>ChainingModes</code>
+ * 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 <code>null</code>
+ * 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 <code>0</code> 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 <code>CreateTransformsInfoProfile</code>s.
+ *
+ * @return The mapping from profile ID to profile.
+ */
+ public Map buildCreateTransformsInfoProfiles()
+ {
+ return loadProfiles(CREATE_TRANSFORMS_INFO_PROFILE_XPATH, "CreateTransformsInfoProfile");
+ }
+
+ /**
+ * Build the <code>CreateSignatureEnvironmentProfile</code>s.
+ *
+ * @return The mapping from profile ID to profile.
+ */
+ public Map buildCreateSignatureEnvironmentProfiles()
+ {
+ return loadProfiles(CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH, "CreateSignatureEnvironmentProfile");
+ }
+
+ /**
+ * Build the <code>VerifyTransformsInfoProfile</code>s.
+ *
+ * @return The mapping from profile ID to profile.
+ */
+ public Map buildVerifyTransformsInfoProfiles()
+ {
+ return loadProfiles(VERIFY_TRANSFORMS_INFO_PROFILE_XPATH, "VerifyTransformsInfoProfile");
+ }
+
+ /**
+ * Build the <code>SupplementProfile</code>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 (Constants.MOA_NS_URI.equals(profile.getNamespaceURI()) &&
+ profile.getLocalName().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 <code>xpath</code>.
+ * @param xpath The XPath pointing to the element.
+ * @param def The default value, if no element can be found with the given
+ * <code>xpath</code>.
+ * @return The element value or <code>def</code>, 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 <code>xpath</code>.
+ * @param xpath The XPath pointing to the attribute.
+ * @param def The default value, if no attribute can be found with the given
+ * <code>xpath</code>.
+ * @return The element value or <code>def</code>, 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 <code>null</code, if the corresponding
+ * parameter is not set in the configuration.
+ */
+ public String getRevocationArchiveJDBCURL()
+ {
+ String jDBCURL = getElementValue(getConfigElem(), ACHIVE_JDBC_URL_, null);
+ return jDBCURL;
+ }
+
+ /**
+ * Returns the JDBC driver class name for the revocation archive database.
+ *
+ * @return the JDBC driver class name for the revocation archive database, or <code>null</code,
+ * if the corresponding parameter is not set in the configuration.
+ */
+ public String getRevocationArchiveJDBCDriverClass()
+ {
+ String jDBCDriverClass = getElementValue(getConfigElem(), ACHIVE_JDBC_DRIVER_CLASS_, null);
+ return jDBCDriverClass;
+ }
+
+ /**
+ * Returns whether revocation information should be archived.
+ */
+ public boolean getEnableRevocationChecking()
+ {
+ String enableChecking = getElementValue(getConfigElem(), ENABLE_REVOCATION_CHECKING_XPATH_, null);
+ return Boolean.valueOf(enableChecking).booleanValue();
+ }
+
+ /**
+ * Returns the maximum age of a revocation information for considering it
+ * still as valid.
+ *
+ * @return the maximum age of a revocation information for considering it
+ * still as valid.
+ */
+ public long getMaxRevocationAge()
+ {
+ String maxRevocationAge = getElementValue(getConfigElem(), MAX_REVOCATION_AGE_XPATH_, null);
+ if (maxRevocationAge == null) return 0;
+ return Long.valueOf(maxRevocationAge).longValue();
+ }
+
+ /**
+ * Returns the service order for revocation checking.
+ *
+ * @return the service order for revocation checking. Valid array entries are
+ * {@link RevocationSourceTypes#OCSP} and {@link RevocationSourceTypes#CRL}.
+ * An empty array will be returned if no service order is specified in the
+ * configuration.
+ */
+ public String[] getServiceOrder()
+ {
+ ArrayList list = new ArrayList();
+ NodeIterator serviceIter = XPathUtils.selectNodeIterator(getConfigElem(), REVOCATION_SERVICEORDER_XPATH_);
+ Element currentServiceNode;
+ while ((currentServiceNode = (Element)serviceIter.nextNode()) != null)
+ {
+ list.add(getElementValue(currentServiceNode, ".", null));
+ }
+ Object[] serviceOrder = list.toArray();
+ String[] returnValue = new String[serviceOrder.length];
+ for (int i = 0; i < serviceOrder.length; i++)
+ {
+ if (((String)serviceOrder[i]).equalsIgnoreCase(RevocationSourceTypes.CRL)) {
+ returnValue[i] = RevocationSourceTypes.CRL;
+ } else if (((String)serviceOrder[i]).equalsIgnoreCase(RevocationSourceTypes.OCSP)) {
+ returnValue[i] = RevocationSourceTypes.OCSP;
+ }
+
+ }
+ return returnValue;
+ }
+
+ /**
+ * Returns whether the certificate extension Authority Info Access should
+ * be used during certificate path construction.
+ *
+ * @return whether the certificate extension Authority Info Access should
+ * be used during certificate path construction.
+ */
+ public boolean getUseAuthorityInfoAccess()
+ {
+ String useAIA = getElementValue(getConfigElem(), USE_AUTHORITY_INFO_ACCESS_XPATH_, null);
+ return Boolean.valueOf(useAIA).booleanValue();
+ }
+
+ /**
+ * Returns whether certificates found during certificate path construction
+ * should be added to the certificate store.
+ *
+ * @return whether certificates found during certificate path construction
+ * should be added to the certificate store.
+ */
+ public boolean getAutoAddCertificates()
+ {
+ String autoAdd = getElementValue(getConfigElem(), AUTO_ADD_CERTIFICATES_XPATH_, null);
+ return Boolean.valueOf(autoAdd).booleanValue();
+ }
+
+ /**
+ * Returns whether file URIs are permitted
+ * @return whether file URIs are permitted
+ */
+ public boolean getPermitFileURIs()
+ {
+ String permitFileURIs = getElementValue(getConfigElem(), PERMIT_FILE_URIS_XPATH, "false");
+ return Boolean.valueOf(permitFileURIs).booleanValue();
+ }
+
+ /**
+ * Returns a map of CRL retention intervals
+ * @return
+ */
+ public Map getCrlRetentionIntervals() {
+ Map map = new HashMap();
+ NodeIterator modIter = XPathUtils.selectNodeIterator(
+ getConfigElem(),
+ CRL_RETENTION_INTERVALS_CA_XPATH);
+
+ Element modElem;
+ while ((modElem = (Element) modIter.nextNode()) != null) {
+ String x509IssuerName = getElementValue(modElem, CONF + "X509IssuerName", null);
+ String i = getElementValue(modElem, CONF + "Interval", null);
+ Integer interval = new Integer(i);
+ try {
+ RFC2253NameParser parser = new RFC2253NameParser(x509IssuerName);
+ Name name = parser.parse();
+ map.put(name.getRFC2253String(), interval);
+ } catch (RFC2253NameParserException e) {
+ map.put(x509IssuerName, interval);
+ }
+
+ //System.out.println("Name: " + x509IssuerName + " - Interval: " + interval);
+ }
+
+ return map;
+ }
+
+}