diff options
Diffstat (limited to 'spss.server/src/at/gv/egovernment/moa/spss/server/config')
12 files changed, 2331 insertions, 0 deletions
diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationException.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationException.java new file mode 100644 index 000000000..f2b847053 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationException.java @@ -0,0 +1,34 @@ +package at.gv.egovernment.moa.spss.server.config; + +import at.gv.egovernment.moa.spss.MOASystemException; + +/** + * Exception signalling an error in the configuration. + * + * @author Patrick Peck + * @version $Id$ + */ +public class ConfigurationException extends MOASystemException { + + /** + * Create a <code>ConfigurationException</code>. + * + * @see at.gv.egovernment.moa.spss.server.MOAException#MOAException(String, Object[]) + */ + public ConfigurationException(String messageId, Object[] parameters) { + super(messageId, parameters); + } + + /** + * Create a <code>ConfigurationException</code>. + * @see at.gv.egovernment.moa.spss.server.MOAException#MOAException(String, Object[], Throwable) + */ + public ConfigurationException( + String messageId, + Object[] parameters, + Throwable wrapped) { + + super(messageId, parameters, wrapped); + } + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java new file mode 100644 index 000000000..1e966911b --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java @@ -0,0 +1,956 @@ +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.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 + "DigestMethodAlgorithm/@name"; + private static final String C14N_ALGORITHM_XPATH = + ROOT + CONF + "CanonicalizationAlgorithm/@name"; + private static final String HARDWARE_CRYPTO_MODULE_XPATH = + ROOT + CONF + "HardwareCryptoModule"; + private static final String HARDWARE_KEY_XPATH = + ROOT + CONF + "HardwareKeyModule"; + private static final String SOFTWARE_KEY_XPATH = + ROOT + CONF + "SoftwareKeyModule"; + private static final String KEYGROUP_XPATH = ROOT + CONF + "KeyGroup"; + private static final String KEY_XPATH = CONF + "Key"; + private static final String KEY_MODULE_ID_XPATH = CONF + "KeyModuleID"; + private static final String KEY_CERT_XPATH = CONF + "KeyCertIssuerSerial"; + private static final String KEYGROUP_MAPPING_XPATH = + ROOT + CONF + "KeyGroupMapping"; + private static final String KEYGROUP_MAPPING_KEYGROUP_XPATH = + CONF + "KeyGroup"; + private static final String ISSUER_SERIAL_XPATH = CONF + "X509IssuerSerial"; + private static final String ISSUER_XPATH = DSIG + "X509IssuerName"; + private static final String SERIAL_XPATH = DSIG + "X509SerialNumber"; + private static final String CHAINING_MODES_XPATH = + ROOT + CONF + "ChainingModes"; + private static final String CHAINING_MODES_DEFAULT_XPATH = + CHAINING_MODES_XPATH + "/@systemDefaultMode"; + private static final String TRUST_ANCHOR_XPATH = + ROOT + CONF + "ChainingModes/" + CONF + "TrustAnchor"; + private static final String CRL_DISTRIBUTION_POINT_XPATH = + ROOT + CONF + "CRLDistributionPoint"; + private static final String CA_ISSUER_DN_XPATH = CONF + "CAIssuerDN"; + private static final String DISTRIBUTION_POINT_XPATH = + CONF + "DistributionPoint"; + private static final String CRL_ARCHIVE_XPATH = ROOT + CONF + "CRLArchive"; + private static final String GENERIC_CONFIGURATION_XPATH = + ROOT + CONF + "GenericConfiguration"; + private static final String CREATE_TRANSFORMS_INFO_PROFILE_XPATH = + ROOT + CONF + "CreateTransformsInfoProfile"; + private static final String CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH = + ROOT + CONF + "CreateSignatureEnvironmentProfile"; + private static final String VERIFY_TRANSFORMS_INFO_PROFILE_XPATH = + ROOT + CONF + "VerifyTransformsInfoProfile"; + private static final String SUPPLEMENT_PROFILE_XPATH = + ROOT + CONF + "SupplementProfile"; + private static final String TRUST_PROFILE_XPATH = + ROOT + CONF + "TrustProfile"; + + // + // 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; + + /** 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. + */ + public ConfigurationPartsBuilder(Element configElem) { + this.configElem = configElem; + } + + /** + * Returns the root element of the MOA configuration. + * + * @return The root element of the MOA configuration. + */ + public Element getConfigElem() { + return configElem; + } + + /** + * 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 = + getAttributeValue(getConfigElem(), DIGEST_METHOD_XPATH, null); + + if (digestMethod == null + || !ACCEPTED_DIGEST_ALGORITHMS.contains(digestMethod)) { + warn( + "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 = + getAttributeValue(getConfigElem(), C14N_ALGORITHM_XPATH, null); + + if (c14nAlgorithm == null + || !ACCEPTED_C14N_ALGORITHMS.contains(c14nAlgorithm)) { + warn( + "config.23", + new Object[] { "CanonicalizationAlgorithm", C14N_ALGORITHM_DEFAULT }); + c14nAlgorithm = C14N_ALGORITHM_DEFAULT; + } + + return c14nAlgorithm; + } + + /** + * Build the mapping of generic configuration properties. + * + * @return The mapping of generic configuration properties (a name to value + * mapping) from the configuration. + */ + public Map buildGenericConfiguration() { + Map genericConfiguration = new HashMap(); + NodeIterator gcIter = + XPathUtils.selectNodeIterator( + getConfigElem(), + GENERIC_CONFIGURATION_XPATH); + Element gcElem; + + while ((gcElem = (Element) gcIter.nextNode()) != null) { + String gcName = gcElem.getAttribute("name"); + String gcValue = gcElem.getAttribute("value"); + + if (genericConfiguration.containsKey(gcName)) { + warn("config.24", new Object[] { gcName }); + } else { + genericConfiguration.put(gcName, gcValue); + } + } + + return genericConfiguration; + } + + /** + * 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 = modElem.getAttribute("name"); + String slotID = modElem.getAttribute("slotID"); + String userPIN = modElem.getAttribute("userPIN"); + HardwareCryptoModule module = + new HardwareCryptoModule(name, slotID, userPIN); + modules.add(module); + } + + return modules; + } + + /** + * Build the configured hardware keys. + * + * @param 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 = keyElem.getAttribute("id"); + String name = keyElem.getAttribute("name"); + String slotID = keyElem.getAttribute("slotID"); + String userPIN = keyElem.getAttribute("userPIN"); + + 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 The keyModules that the configuration already knows about. To + * prevent multiple key modules with the same ID. + * @param configRoot The directory containing the main configuration file. + * Used to resolve keystore files configured using a relative URI. + * @return The software keys contained in the configuration. + */ + public List buildSoftwareKeyModules(List keyModules, File configRoot) { + 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 = keyElem.getAttribute("id"); + String fileName = keyElem.getAttribute("filename"); + String passWord = keyElem.getAttribute("password"); + + 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 = keyGroupElem.getAttribute("id"); + 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, KEY_XPATH); + while ((keyEntryElem = (Element) keyEntryIter.nextNode()) != null) { + String keyModuleId = + getElementValue(keyEntryElem, KEY_MODULE_ID_XPATH, ""); + Element keyCertElem = + (Element) XPathUtils.selectSingleNode(keyEntryElem, KEY_CERT_XPATH); + 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, ISSUER_SERIAL_XPATH); + IssuerAndSerial issuerAndSerial; + + // build the IssuerAndSerial who has access to the key groups + 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, + KEYGROUP_MAPPING_KEYGROUP_XPATH); + while ((keyGroupElem = (Element) keyGroupIter.nextNode()) != null) { + String keyGroupId = keyGroupElem.getAttribute("id"); + 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 = + getAttributeValue( + getConfigElem(), + CHAINING_MODES_DEFAULT_XPATH, + CM_CHAINING); + + 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(trustAnchorElem); + String mode = trustAnchorElem.getAttribute("mode"); + + 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.CHAIN_MODE; + } + } + + /** + * Build the CRL distribution points mapping. + * + * @return The mapping from certificate authorities to distribution points. + */ + public Map buildCRLDistributionPoints() { + Map crlDps = new HashMap(); + NodeIterator crlDpIter; + Element crlDpElem; + + // select all CRLDistributionPoint elements and build the + // CRLDistributionPoints + crlDpIter = + XPathUtils.selectNodeIterator( + getConfigElem(), + CRL_DISTRIBUTION_POINT_XPATH); + + // build the mapping of CA name to distribution points + while ((crlDpElem = (Element) crlDpIter.nextNode()) != null) { + String caIssuerDNText = + getElementValue(crlDpElem, CA_ISSUER_DN_XPATH, ""); + RFC2253NameParser nameParser = new RFC2253NameParser(caIssuerDNText); + NodeIterator dpIter = + XPathUtils.selectNodeIterator(crlDpElem, DISTRIBUTION_POINT_XPATH); + String caIssuerDN; + Set dps; + Element dpElem; + + try { + caIssuerDN = nameParser.parse().getName(); + + // check, if a mapping exists or make a new mapping + dps = (Set) crlDps.get(caIssuerDN); + if (dps == null) { + dps = new HashSet(); + crlDps.put(caIssuerDN, dps); + } + + // add the distribution points of this CA to the set + while ((dpElem = (Element) dpIter.nextNode()) != null) { + DistributionPoint dp = buildDistributionPoint(dpElem); + dps.add(dp); + } + } catch (RFC2253NameParserException e) { + warn("config.13", new Object[] { caIssuerDNText }, e); + } + + } + + return crlDps; + } + + /** + * Build a distribution point from the DOM representation. + * + * @param dpElem The root element of the distribution point. + * @return The distribution point. + */ + private DistributionPoint buildDistributionPoint(Element dpElem) { + String uri = dpElem.getAttribute("uri"); + String reasonCodes = dpElem.getAttribute("reasonCodes"); + + return new DistributionPoint(uri, reasonCodes != null ? reasonCodes : ""); + } + + /** + * Return the CRL archive duration. + * + * @return The value of the CRL archive duration setting from the + * configuration. + */ + public int getCRLArchiveDuration() { + Element crlArchiveElem = + (Element) XPathUtils.selectSingleNode(getConfigElem(), CRL_ARCHIVE_XPATH); + String crlArchiveDuration; + + if (crlArchiveElem == null) { + return 0; + } + + try { + crlArchiveDuration = crlArchiveElem.getAttribute("duration"); + return Integer.parseInt(crlArchiveDuration); + } catch (NumberFormatException e) { + warn("config.01", null); + return 0; + } + } + + /** + * Build the <code>CreateTransformsInfoProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildCreateTransformsInfoProfiles(File configRoot) { + return loadProfiles( + configRoot, + CREATE_TRANSFORMS_INFO_PROFILE_XPATH, + "CreateTransformsInfoProfile"); + } + + /** + * Build the <code>CreateSignatureEnvironmentProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildCreateSignatureEnvironmentProfiles(File configRoot) { + return loadProfiles( + configRoot, + CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH, + "CreateSignatureEnvironmentProfile"); + } + + /** + * Build the <code>VerifyTransformsInfoProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildVerifyTransformsInfoProfiles(File configRoot) { + return loadProfiles( + configRoot, + VERIFY_TRANSFORMS_INFO_PROFILE_XPATH, + "VerifyTransformsInfoProfile"); + } + + /** + * Build the <code>SupplementProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildSupplementProfiles(File configRoot) { + return loadProfiles( + configRoot, + SUPPLEMENT_PROFILE_XPATH, + "SupplementProfile"); + } + + /** + * Load a profile mapping. + * + * @param root The absolute directory path of the main configuration file. + * @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(File root, String xpath, String profileRoot) { + Map profiles = new HashMap(); + NodeIterator profileIter = + XPathUtils.selectNodeIterator(getConfigElem(), xpath); + Element profileElem; + + while ((profileElem = (Element) profileIter.nextNode()) != null) { + String id = profileElem.getAttribute("id"); + String fileName = profileElem.getAttribute("filename"); + + if (profiles.containsKey(id)) { + warn("config.04", new Object[] { profileRoot, id }); + } else { + Element profile; + + try { + File profileFile = new File(fileName); + + // make profileFile absolute + if (!profileFile.isAbsolute()) { + profileFile = new File(root, fileName); + } + + // load the profile + info( + "config.22", + new Object[] { profileRoot, id, profileFile.getAbsoluteFile()}); + 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. + * + * @param configRoot The absolute path to the main configuration file. + * @return The profile ID to profile mapping. + */ + public Map buildTrustProfiles(File configRoot) { + Map trustProfiles = new HashMap(); + NodeIterator profileIter = + XPathUtils.selectNodeIterator(getConfigElem(), TRUST_PROFILE_XPATH); + Element profileElem; + + while ((profileElem = (Element) profileIter.nextNode()) != null) { + String id = profileElem.getAttribute("id"); + String uriStr = profileElem.getAttribute("uri"); + + try { + URI uri = new URI(uriStr); + TrustProfile profile; + File profileDir; + + if (!uri.isAbsolute()) { // make it absolute to the config file + uri = new URI(configRoot.toURL() + uriStr); + } + + profileDir = new File(uri.getPath()); + if (!profileDir.exists() || !profileDir.isDirectory()) { + warn("config.27", new Object[] { id }); + } + + if (trustProfiles.containsKey(id)) { + warn("config.04", new Object[] { "TrustProfile", id }); + } else { + profile = new TrustProfile(id, uri.toString()); + trustProfiles.put(id, profile); + } + + } catch (URIException e) { + warn("config.14", new Object[] { id, uriStr }, e); + } catch (MalformedURLException e) { + warn("config.15", null, e); + } + } + + return trustProfiles; + } + + // + // 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); + } + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java new file mode 100644 index 000000000..fbae33b72 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java @@ -0,0 +1,666 @@ +package at.gv.egovernment.moa.spss.server.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.net.URL; +import java.security.Principal; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.w3c.dom.Element; + +import iaik.asn1.structures.Name; +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.DOMUtils; + +import at.gv.egovernment.moa.spss.util.MessageProvider; + +/** + * A class providing access to the MOA configuration data. + * + * <p>Configuration data is read from an XML file, whose location is given by + * the <code>moa.spss.server.configuration</code> system property.</p> + * <p>This class implements the Singleton pattern. The <code>reload()</code> + * method can be used to update the configuration data. Therefore, it is not + * guaranteed that consecutive calls to <code>getInstance()</code> will return + * the same <code>ConfigurationProvider</code> all the time. During the + * processing of a web service request, the current + * <code>TransactionContext</code> should be used to obtain the + * <code>ConfigurationProvider</code> local to that request.</p> + * + * @author Patrick Peck + * @author Sven Aigner + * @version $Id$ + */ +public class ConfigurationProvider { + + /** + * The name of the system property which contains the file name of the + * configuration file. + */ + public static final String CONFIG_PROPERTY_NAME = + "moa.spss.server.configuration"; + + /** + * The name of the generic configuration property giving the root directory of + * a directory based cert store. + */ + public static final String DIRECTORY_CERTSTORE_PARAMETER_PROPERTY = + "DirectoryCertStoreParameters.RootDir"; + + /** The name of the generic configuration property which determines if + * certificates should be added to the cert store automatically. */ + public static final String AUTO_ADD_CERTIFICATES_PROPERTY = + "autoAddCertificates"; + + /** The name of the generic configuration property whether the authority + * info access should be used. */ + public static final String USE_AUTHORITY_INFO_ACCESS_PROPERTY = + "useAuthorityInfoAccess"; + + /** The name of the generic configuration property determining the maximum + * age of CRL entries. */ + public static final String MAX_REVOCATION_AGE_PROPERTY = "maxRevocationAge"; + + /** + * The name of the generic configuration property giving the database URL of + * the CRL archive. + */ + public static final String DATABASE_ARCHIVE_PARAMETER_PROPERTY = + "DataBaseArchiveParameter.JDBCUrl"; + + /** The name of the generic configuration property determining whether + * to check the revocation status of signer certificates. */ + public static final String REVOCATION_CHECKING_PROPERTY = "checkRevocation"; + + /** The name of the generic configuration property determining whether to + * archive revocation information. */ + public static final String ARCHIVE_REVOCATION_INFO_PROPERTY = + "archiveRevocationInfo"; + + /** The name of the generic configuration property used for setting the + * signing time to a predefined value. (Use for testing purposes only). */ + public static final String TEST_SIGNING_TIME_PROPERTY = "test.SigningTime"; + + /** + * A fake <code>IssuerAndSerial</code> object for storing KeyGroup information + * accessible by all clients. + */ + private static final IssuerAndSerial ANONYMOUS_ISSUER_SERIAL = + new IssuerAndSerial(new Name(), new BigInteger("0")); + + /** Singleton instance. <code>null</code>, if none has been created. */ + private static ConfigurationProvider instance; + + // + // configuration data + // + + /** The warnings generated when building the configuration. */ + private List warnings = new ArrayList(); + + /** The default digest method algorithm name */ + private String digestMethodAlgorithmName; + + /** The default canonicalization algorithm name */ + private String canonicalizationAlgorithmName; + + /** + * A <code>Map</code> which contains generic configuration information. Maps a + * configuration name (a <code>String</code>) to a configuration value (also a + * <code>String</code>). + */ + private Map genericConfiguration; + + /** + * A <code>List</code> of <code>HardwareCryptoModule</code> objects for + * configuring hardware modules. + */ + private List hardwareCryptoModules; + + /** + * A <code>List</code> of <code>HardwareKey</code> objects containing the + * configuration data for hardware keys. + */ + private List hardwareKeyModules; + + /** + * A <code>List</code> of <code>SoftwareKey</code> objects containing the + * configuration data for software keys. + */ + private List softwareKeyModules; + + /** + * A <code>Map</code> which contains a KeyGroupId (a <code>String</code>) to + * KeyGroup mapping. + */ + private Map keyGroups; + + /** + * A <code>Map</code> which contains the <code>IssuerAndSerial</code> to + * <code>KeyGroup</code> mapping. + */ + private Map keyGroupMappings; + + /** The default chaining mode. */ + private String defaultChainingMode; + + /** + * A <code>Map</code> which contains the <code>IssuerAndSerial</code> to + * chaining mode (a <code>String</code>) mapping. + */ + private Map chainingModes; + + /** + * A <code>Map</code> which contains the CAIssuerDN (a <code>String</code>) + * to distribution points (a <code>Set</code> of + * <code>DistributionPoint</code>s) mapping. + */ + private Map crlDistributionPoints; + + /** The CRL archive duration. */ + private int cRLArchiveDuration; + + /** + * A <code>Map</code> which contains a mapping from + * CreateSignatureEnvironmentProfile Ids (<code>String</code>) to + * CreateSignatureEnvironmentProfile elements (an <code>Element</code>). + */ + private Map createSignatureEnvironmentProfiles; + + /** + * A <code>Map</code> which contains a mapping from + * CreateTransformsInfoProfile Ids (<code>String</code>) to + * CreateTransformsInfoProfile elements (an <code>Element</code>). + */ + private Map createTransformsInfoProfiles; + + /** + * A <code>Map</code> which contains a mapping from + * VerifyTransformsInfoProfile Ids (<code>String</code>) to + * VerifyTransformsInfoProfile elements (an <code>Element</code>). + */ + private Map verifyTransformsInfoProfiles; + + /** + * A <code>Map</code> which contains a mapping from + * SupplementProfile Ids (<code>String</code>) to SupplementProfile elements + * (an <code>Element</code>). + */ + private Map supplementProfiles; + + /** + * A <code>Map</code> which contains a TrustProfile Id (a <code>String</code> + * to trust profile (a <code>TrustProfile</code>) mapping. + */ + private Map trustProfiles; + + /** + * Return the single instance of configuration data. + * + * @return MOAConfigurationProvider The current configuration data. + * @throws ConfigurationException Failure to load the configuration data. + */ + public static synchronized ConfigurationProvider getInstance() + throws ConfigurationException { + + if (instance == null) { + reload(); + } + return instance; + } + + /** + * Reload the configuration data and set it if successful. + * + * @return MOAConfigurationProvider The loaded configuration data. + * @throws ConfigurationException Failure to load the configuration data. + */ + public static synchronized ConfigurationProvider reload() + throws ConfigurationException { + String fileName = System.getProperty(CONFIG_PROPERTY_NAME); + + if (fileName == null) { + // find out where we are running and use the configuration provided + // under WEB-INF/conf/moa-spss/MOA-SPSSConfiguration + URL url = ConfigurationProvider.class.getResource("/"); + fileName = + new File(url.getPath()).getParent() + + "/conf/moa-spss/MOA-SPSSConfiguration.xml"; + info("config.05", new Object[] { CONFIG_PROPERTY_NAME }); + } + + instance = new ConfigurationProvider(fileName); + return instance; + } + + /** + * Constructor for ConfigurationProvider. + * + * @param fileName The name of the configuration file. + * @throws ConfigurationException An error occurred loading the configuration. + */ + public ConfigurationProvider(String fileName) throws ConfigurationException { + load(fileName); + } + + /** + * Load the configuration data from XML file with the given name and build + * the internal data structures representing the MOA configuration. + * + * @param fileName The name of the XML file to load. + * @throws ConfigurationException The MOA configuration could not be + * read/built. + */ + private void load(String fileName) throws ConfigurationException { + FileInputStream stream = null; + File configFile; + File configRoot; + Element configElem; + ConfigurationPartsBuilder builder; + List allKeyModules; + + + // load the main config file + try { + configFile = new File(fileName); + configRoot = new File(configFile.getParent()); + info("config.21", new Object[] { configFile.getAbsoluteFile()}); + stream = new FileInputStream(fileName); + configElem = DOMUtils.parseXmlValidating(new FileInputStream(fileName)); + } catch (Throwable t) { + throw new ConfigurationException("config.10", null, t); + } + + // build the internal datastructures + try { + builder = new ConfigurationPartsBuilder(configElem); + digestMethodAlgorithmName = builder.getDigestMethodAlgorithmName(); + canonicalizationAlgorithmName = + builder.getCanonicalizationAlgorithmName(); + hardwareCryptoModules = builder.buildHardwareCryptoModules(); + hardwareKeyModules = + builder.buildHardwareKeyModules(Collections.EMPTY_LIST); + softwareKeyModules = + builder.buildSoftwareKeyModules(hardwareKeyModules, configRoot); + allKeyModules = new ArrayList(hardwareKeyModules); + allKeyModules.addAll(softwareKeyModules); + keyGroups = builder.buildKeyGroups(allKeyModules); + keyGroupMappings = + builder.buildKeyGroupMappings(keyGroups, ANONYMOUS_ISSUER_SERIAL); + defaultChainingMode = builder.getDefaultChainingMode(); + chainingModes = builder.buildChainingModes(); + crlDistributionPoints = builder.buildCRLDistributionPoints(); + cRLArchiveDuration = builder.getCRLArchiveDuration(); + genericConfiguration = builder.buildGenericConfiguration(); + absolutizeCertStoreRoot(configRoot); + createTransformsInfoProfiles = + builder.buildCreateTransformsInfoProfiles(configRoot); + createSignatureEnvironmentProfiles = + builder.buildCreateSignatureEnvironmentProfiles(configRoot); + verifyTransformsInfoProfiles = + builder.buildVerifyTransformsInfoProfiles(configRoot); + supplementProfiles = builder.buildSupplementProfiles(configRoot); + trustProfiles = builder.buildTrustProfiles(configRoot); + warnings = new ArrayList(builder.getWarnings()); + checkConsistency(); + } catch (Throwable t) { + throw new ConfigurationException("config.11", null, t); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException e) { + // don't complain about this + } + } + } + + /** + * 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; + } + + /** + * Make the <code>DIRECTORY_CERTSTORE_PARAMETER_PROPERTY</code> generic + * configuration value an absolute file name. + * + * @param configRoot The root directory of the main configuration file. + */ + private void absolutizeCertStoreRoot(File configRoot) { + String certStoreRoot = + getGenericConfiguration(DIRECTORY_CERTSTORE_PARAMETER_PROPERTY); + + if (certStoreRoot != null) { + if (!new File(certStoreRoot).isAbsolute()) { + // make the cert store absolute + File absCertStore = new File(configRoot, certStoreRoot); + + setGenericConfiguration( + DIRECTORY_CERTSTORE_PARAMETER_PROPERTY, + absCertStore.getAbsolutePath()); + } + } else { + // no value given: set it to a reasonable (absolute) default + File absCertStore = new File(configRoot, "certstore"); + + setGenericConfiguration( + DIRECTORY_CERTSTORE_PARAMETER_PROPERTY, + absCertStore.getAbsolutePath()); + } + } + + /** + * Do some additional consistency checks on the configuration. + */ + private void checkConsistency() { + // check for valid DirectoryCertStoreParameters.RootDir + String certStoreRoot = + getGenericConfiguration(DIRECTORY_CERTSTORE_PARAMETER_PROPERTY); + + if (certStoreRoot != null) { + File certStore = new File(certStoreRoot); + + if (!certStore.exists() && !certStore.isDirectory()) { + boolean created = false; + + try { + created = certStore.mkdirs(); + } finally { + if (!created) { + warn( + "config.30", + new Object[] { DIRECTORY_CERTSTORE_PARAMETER_PROPERTY }); + } + } + } + } + + } + + /** + * Return the name of the digest algorithm used during signature creation. + * + * @return The digest method algorithm name, or an empty <code>String</code>, + * if none has been configured. + */ + public String getDigestMethodAlgorithmName() { + return digestMethodAlgorithmName; + } + + /** + * Return the name of the canonicalization algorithm used during signature + * creation. + * + * @return The canonicalization algorithm name, or an empty + * <code>String</code> if none has been configured. + */ + public String getCanonicalizationAlgorithmName() { + return canonicalizationAlgorithmName; + } + + /** + * Return the configured hardware crypto modules. + * + * @return A <code>List</code> of <code>HardwareCryptoModule</code> objects + * containing the hardware crypto module configurations. + */ + public List getHardwareCryptoModules() { + return hardwareCryptoModules; + } + + /** + * Return the hardware key modules configuration. + * + * @return A <code>List</code> of <code>HardwareKeyModule</code> objects + * containing the configuration of the hardware key modules. + */ + public List getHardwareKeyModules() { + return hardwareKeyModules; + } + + /** + * Return the software key module configuration. + * + * @return A <code>List</code> of <code>SoftwareKeyModule</code> objects + * containing the configuration of the software key modules. + */ + public List getSoftwareKeyModules() { + return softwareKeyModules; + } + + /** + * Return the key group mapping. + * + * @return A mapping from key group ID (a <code>String</code>) to + * <code>KeyGroup</code> mapping. + */ + public Map getKeyGroups() { + return keyGroups; + } + + /** + * Return the set of <code>KeyGroupEntry</code>s of a given key group, which a + * client (identified by an issuer/serial pair) may access. + * + * @param issuer The issuer of the client certificate. + * @param serial The serial number of the client certificate. + * @param keyGroupId The ID of the key group. + * @return A <code>Set</code> of all the <code>KeyGroupEntry</code>s in the + * given key group, if the user may access them. Returns <code>null</code>, if + * the user may not access the given key group or if the key group does not + * exist. + */ + public Set getKeyGroupEntries( + Principal issuer, + BigInteger serial, + String keyGroupId) { + + IssuerAndSerial issuerAndSerial; + Map mapping; + + if (issuer == null && serial == null) { + issuerAndSerial = ANONYMOUS_ISSUER_SERIAL; + } else { + issuerAndSerial = new IssuerAndSerial(issuer, serial); + } + + mapping = (Map) keyGroupMappings.get(issuerAndSerial); + if (mapping != null) { + KeyGroup keyGroup = (KeyGroup) mapping.get(keyGroupId); + + if (keyGroup != null) { + return keyGroup.getKeyGroupEntries(); + } + } + return null; + } + + /** + * Return the chaining mode for a given trust anchor. + * + * @param trustAnchor The trust anchor for which the chaining mode should be + * returned. + * @return The chaining mode for the given trust anchor. If the trust anchor + * has not been configured separately, the system default will be returned. + */ + public String getChainingMode(X509Certificate trustAnchor) { + Principal issuer = trustAnchor.getIssuerDN(); + BigInteger serial = trustAnchor.getSerialNumber(); + IssuerAndSerial issuerAndSerial = new IssuerAndSerial(issuer, serial); + + String mode = (String) chainingModes.get(issuerAndSerial); + return mode != null ? mode : defaultChainingMode; + } + + /** + * Return the CRL distribution points for a given CA. + * + * @param cert The certificate for which the CRL distribution points should be + * looked up. The issuer information is used to perform the lookup. + * @return A <code>Set</code> of <code>DistributionPoint</code> objects. The + * set will be empty, if no distribution points have been configured for this + * certificate. + */ + public Set getCRLDP(X509Certificate cert) { + try { + RFC2253NameParser nameParser = + new RFC2253NameParser(cert.getIssuerDN().toString()); + String caIssuerDN = nameParser.parse().getName(); + Set dps = (Set) crlDistributionPoints.get(caIssuerDN); + + if (dps == null) { + return Collections.EMPTY_SET; + } + return dps; + } catch (RFC2253NameParserException e) { + return Collections.EMPTY_SET; + } + } + + /** + * Return the CRL archive duration. + * + * @return The duration of how long to keep CRL archive entries (measured in + * days). + */ + public int getCRLArchiveDuration() { + return cRLArchiveDuration; + } + + /** + * Sets a generic configuration value. + * + * Existing values are overridden. + * + * @param name The name of the generic configuration. + * @param value The new value of the generic configuration. + */ + private void setGenericConfiguration(String name, String value) { + genericConfiguration.put(name, value); + } + + /** + * Return the value of a generic configuration. + * + * @param name The name of the generic configuration. + * @return The value of the generic configuration with the given name, or + * <code>null</code>, if none can be found. + */ + public String getGenericConfiguration(String name) { + return (String) genericConfiguration.get(name); + } + + /** + * Return the value of a generic configuration, or a given default value. + * + * @param name The name of the generic configuration. + * @param defaultValue A default value to be returned in case that the generic + * configuration with the given name does not exist. + * @return The value of the generic configuration with the given name, or the + * <code>defaultValue</code>, if none can be found. + */ + public String getGenericConfiguration(String name, String defaultValue) { + String value = (String) genericConfiguration.get(name); + return value != null ? value : defaultValue; + } + + /** + * Return a <code>CreateTransformsInfoProfile</code> with the given ID. + * + * @param id The <code>CreateTransformsInfoProfile</code> ID. + * @return The <code>CreateTransformsInfoProfile</code> with the given + * ID or <code>null</code>, if none exists. + */ + public Element getCreateTransformsInfoProfile(String id) { + return (Element) createTransformsInfoProfiles.get(id); + } + + /** + * Return a <code>CreateSignatureEnvironmentProfile</code> with the given ID. + * + * @param id The <code>CreateSignatureEnvironmentProfile</code> ID. + * @return The <code>CreateSignatureEnvironmentProfile</code> with the given + * ID or <code>null</code>, if none exists. + */ + public Element getCreateSignatureEnvironmentProfile(String id) { + return (Element) createSignatureEnvironmentProfiles.get(id); + } + + /** + * Return a <code>VerifyTransformsInfoProfile</code> with the given ID. + * + * @param id The <code>VerifyTransformsInfoProfile</code> ID. + * @return The <code>VerifyTransformsInfoProfile</code> with the given ID or + * <code>null</code>, if none exists. + */ + public Element getVerifyTransformsInfoProfile(String id) { + return (Element) verifyTransformsInfoProfiles.get(id); + } + + /** + * Return a <code>SupplementProfile</code> with the given ID. + * + * @param id The <code>SupplementProfile</code> ID. + * @return The <code>SupplementProfile</code> with the given ID or + * <code>null</code>, if none exists. + */ + public Element getSupplementProfile(String id) { + return (Element) supplementProfiles.get(id); + } + + /** + * Return a <code>TrustProfile</code> with the given ID. + * + * @param id The <code>TrustProfile</code> ID. + * @return The <code>TrustProfile</code> with the given ID or + * <code>null</code>, if none exists. + */ + public TrustProfile getTrustProfile(String id) { + return (TrustProfile) trustProfiles.get(id); + } + + /** + * Log a warning. + * + * @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); + } + +}
\ No newline at end of file diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/DistributionPoint.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/DistributionPoint.java new file mode 100644 index 000000000..ce9588c87 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/DistributionPoint.java @@ -0,0 +1,134 @@ +package at.gv.egovernment.moa.spss.server.config; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import at.gv.egovernment.moa.logging.LogMsg; +import at.gv.egovernment.moa.logging.Logger; + +import at.gv.egovernment.moa.spss.util.MessageProvider; + +/** + * A class containing information about a CRL distribution point. + * + * @author Sven Aigner + * @author Patrick Peck + * @version $Id$ + */ +public class DistributionPoint { + + private static Map RC_MAPPING = new HashMap(); + + static { + + // create the mapping between reason code strings and their integer values + RC_MAPPING.put( + "unused", + new Integer(iaik.asn1.structures.DistributionPoint.unused)); + RC_MAPPING.put( + "keyCompromise", + new Integer(iaik.asn1.structures.DistributionPoint.keyCompromise)); + RC_MAPPING.put( + "cACompromise", + new Integer(iaik.asn1.structures.DistributionPoint.cACompromise)); + RC_MAPPING.put( + "affiliationChanged", + new Integer(iaik.asn1.structures.DistributionPoint.affiliationChanged)); + RC_MAPPING.put( + "superseded", + new Integer(iaik.asn1.structures.DistributionPoint.superseded)); + RC_MAPPING.put( + "cessationOfOperation", + new Integer(iaik.asn1.structures.DistributionPoint.cessationOfOperation)); + RC_MAPPING.put( + "certificateHold", + new Integer(iaik.asn1.structures.DistributionPoint.certificateHold)); + RC_MAPPING.put( + "privilegeWithdrawn", + new Integer(iaik.asn1.structures.DistributionPoint.privilegeWithdrawn)); + RC_MAPPING.put( + "aACompromise", + new Integer(iaik.asn1.structures.DistributionPoint.aACompromise)); + } + + /** The distribution point URI. */ + private String uri; + /** The reason codes applicable for the distribution point. */ + private int reasonCodes; + + /** + * Create a <code>DistributionPoint</code> with a URI and a list of reason + * codes. + * + * @param uri The URI of the distribution point. + * @param reasonCodeStr A list of reason codes (a space-separated + * enumeration). + */ + public DistributionPoint(String uri, String reasonCodeStr) { + this.uri = uri; + this.reasonCodes = extractReasonCodes(reasonCodeStr); + } + + /** + * Convert a list of reason codes provided as a <code>String</code> to a + * binary representation. + * + * @param reasonCodeStr A <code>String</code> containing a blank-separated, + * textual representation of reason codes. + * @return int A binary representation of reason codes. + * @see iaik.asn1.structures.DistributionPoint + */ + private int extractReasonCodes(String reasonCodeStr) { + int codes = 0; + StringTokenizer tokenizer = new StringTokenizer(reasonCodeStr); + String token; + Integer reasonCode; + + while (tokenizer.hasMoreTokens()) { + token = tokenizer.nextToken(); + reasonCode = (Integer) RC_MAPPING.get(token); + if (reasonCode != null) { + codes |= reasonCode.intValue(); + } else { + MessageProvider msg = MessageProvider.getInstance(); + Logger.warn( + new LogMsg(msg.getMessage("config.07", new Object[] { token }))); + } + } + + return codes; + } + + /** + * Return the URI of the distribution point. + * + * @return The URI of the distribution point. + */ + public String getUri() { + return uri; + } + + /** + * Return a binary representation of the reason codes of this distribution + * point. + * + * @return The binary representation of the reason codes. + */ + public int getReasonCodes() { + return reasonCodes; + } + + /** + * Return a <code>String</code> representation of this distribution point. + * + * @return The <code>String</code> representation of this distribution point. + * @see java.lang.Object#toString() + */ + public String toString() { + return "(DistributionPoint - " + + ("URI<" + getUri()) + + ("> REASONCODES<" + getReasonCodes() + ">)"); + } + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/HardwareCryptoModule.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/HardwareCryptoModule.java new file mode 100644 index 000000000..62e8d63a6 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/HardwareCryptoModule.java @@ -0,0 +1,60 @@ +package at.gv.egovernment.moa.spss.server.config; + +/** + * Contains configuration data for a hardware crypto module. + * + * @author Patrick Peck + * @version $Id$ + */ +public class HardwareCryptoModule { + /** The name of the module. */ + private String name; + /** The slod ID of the module. */ + private String slotID; + /** The user PIN of the module. */ + private String userPIN; + + /** + * Create a new <code>HardwareCryptoModule</code>. + * + * @param name The name of this <code>HardwareCryptoModule</code>. + * @param slotID The slot ID of this <code>HardwareCryptoModule</code>. + * @param userPIN The user PIN to access this + * <code>HardwareCryptoModule</code>. + */ + public HardwareCryptoModule(String name, String slotID, String userPIN) { + this.name = name; + this.slotID = slotID; + this.userPIN = userPIN; + } + + /** + * Returns the name of this <code>HardwareCryptoModule</code>. + * + * @return The name of this <code>HardwareCryptoModule</code>. + */ + public String getName() { + return name; + } + + /** + * Returns the slot ID of this <code>HardwareCryptoModule</code>. + * + * @return The slot ID. + */ + public String getSlotID() { + return slotID; + } + + + /** + * Returns the user PIN of this <code>HardwareCryptoModule</code>. + * + * @return The user PIN used to access the module. + */ + public String getUserPIN() { + return userPIN; + } + + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/HardwareKeyModule.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/HardwareKeyModule.java new file mode 100644 index 000000000..622c8d110 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/HardwareKeyModule.java @@ -0,0 +1,59 @@ +package at.gv.egovernment.moa.spss.server.config; + +/** + * A class that contains information about a hardware key module. + * + * @author Patrick Peck + * @version $Id$ + */ +public class HardwareKeyModule extends KeyModule { + /** The name of the module. */ + private String name; + /** The slod ID of the module. */ + private String slotID; + /** The user PIN of the module. */ + private String userPIN; + + /** + * Create a new <code>HardwareKey</code>. + * + * @param id The key module ID. + * @param name The name of the key. + * @param slotID The slot ID of the key within the hardware module. May be + * <code>null</code>. + * @param userPIN The user PIN to access the key. + */ + public HardwareKeyModule(String id, String name, String slotID, String userPIN) { + super(id); + this.name = name; + this.slotID = slotID; + this.userPIN = userPIN; + } + + /** + * Return the name of this <code>HardwareKey</code>. + * + * @return The name of this <code>HardwareKey</code>. + */ + public String getName() { + return name; + } + + /** + * Return the slot ID of this <code>HardwareKey</code>. + * + * @return The slot ID of this <code>HardwareKey</code>. + */ + public String getSlotID() { + return slotID; + } + + /** + * Return the user PIN to access this <code>HardwareKey</code>. + * + * @return The user PIN to access this <code>HardwareKey</code>. + */ + public String getUserPIN() { + return userPIN; + } +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/IssuerAndSerial.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/IssuerAndSerial.java new file mode 100644 index 000000000..9d9262785 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/IssuerAndSerial.java @@ -0,0 +1,115 @@ +package at.gv.egovernment.moa.spss.server.config; + +import java.math.BigInteger; +import java.security.Principal; + +import iaik.asn1.structures.Name; +import iaik.utils.RFC2253NameParser; +import iaik.utils.RFC2253NameParserException; + +/** + * A class containing the issuer and serial number of a certificate, which can + * be used to uniquely identify the certificate. + * + * The issuer is contained as an RFC2253 encoded <code>String</code>. + * + * @author Patrick Peck + * @version $Id$ + */ +public class IssuerAndSerial { + + /** The issuer distinguished name. */ + private String issuerDN; + /** The certificate serial number. */ + private BigInteger serial; + + /** + * Create an <code>IssuerAndSerial</code> object. + * + * The name of the issuer is converted to RFC2253. If it cannot be parsed, the + * DN contained in the <code>issuer</code> is set. + * + * @param issuer The isser of a certificate. + * @param serial The serial number of the certificate. + */ + public IssuerAndSerial(Principal issuer, BigInteger serial) { + RFC2253NameParser parser = new RFC2253NameParser(issuer.getName()); + + try { + this.issuerDN = ((Name) parser.parse()).getRFC2253String(); + } catch (RFC2253NameParserException e) { + this.issuerDN = issuer.getName(); + } + this.serial = serial; + } + + /** + * Create an <code>IssuerAndSerial</code> object. + * + * @param issuerDN The issuer distinguished name. Should be an RFC2253 name. + * @param serial The serial number of the certificate. + */ + public IssuerAndSerial(String issuerDN, BigInteger serial) { + this.issuerDN = issuerDN; + this.serial = serial; + } + + /** + * Return the issuer DN in RFC2253 format. + * + * @return The issuer part of this object. + */ + public String getIssuerDN() { + return issuerDN; + } + + /** + * Return the serial number. + * + * @return The serial number of this object. + */ + public BigInteger getSerial() { + return serial; + } + + /** + * Compare this <code>IssuerAndSerial</code> to another object. + * + * @param other The object to compare this <code>IssuerAndSerial</code> to. + * @return <code>true</code>, if <code>other</code> is an + * <code>IssuerAndSerial</code> object and the <code>issuer</code> and + * <code>serial</code> fields are both equal. <code>false</code> otherwise. + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object other) { + if (other instanceof IssuerAndSerial) { + IssuerAndSerial ias = (IssuerAndSerial) other; + return getIssuerDN().equals(ias.getIssuerDN()) + && getSerial().equals(ias.getSerial()); + } + return false; + } + + /** + * Return the hash code of this <code>IssuerAndSerial</code>. + * + * @return The hash code of this <code>IssuerAndSerial</code>. + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return issuerDN.hashCode() ^ serial.hashCode(); + } + + /** + * Return a <code>String</code> representation of this + * <code>IssuerAndSerial</code> object. + * + * @return The <code>String</code> representation. + * @see java.lang.Object#toString() + */ + public String toString() { + return ("(IssuerAndSerial - Issuer<" + getIssuerDN()) + + ("> Serial<" + serial.toString() + ">)"); + } + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyGroup.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyGroup.java new file mode 100644 index 000000000..5fd108e1a --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyGroup.java @@ -0,0 +1,69 @@ +package at.gv.egovernment.moa.spss.server.config; + +import java.util.Iterator; +import java.util.Set; + +/** + * A collection of <code>KeyGroupEntry</code>s with its own ID. + * + * @author Sven Aigner + * @author Patrick Peck + * @version $Id$ + */ +public class KeyGroup { + + /** The keys belonging to this key group. */ + private Set keyGroupEntries; + /** The key group ID. */ + private String id; + + /** + * Create a <code>KeyGroup</code>. + * + * @param id The ID of this <code>KeyGroup</code>. + * @param keyGroupEntries The keys belonging to this <code>KeyGroup</code>. + */ + public KeyGroup(String id, Set keyGroupEntries) { + this.id = id; + this.keyGroupEntries = keyGroupEntries; + } + + /** + * Return the <code>KeyEntry</code>s contained in this <code>KeyGroup</code>. + * + * @return The <code>KeyEntry</code>s contained in this <code>KeyGroup</code>. + */ + public Set getKeyGroupEntries() { + return keyGroupEntries; + } + + /** + * Return the ID of this <code>KeyGroup</code>. + * + * @return The <code>KeyGroup</code> ID. + */ + public String getId() { + return id; + } + + /** + * Return a <code>String</code> representation of this <code>KeyGroup</code>. + * + * @return The <code>String</code> representation. + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer sb = new StringBuffer(); + Iterator i; + + if (getKeyGroupEntries() != null) { + i = getKeyGroupEntries().iterator(); + + while (i.hasNext()) { + sb.append(" " + i.next()); + } + } + return "(KeyGroup - ID:" + id + " " + sb.toString() + ")"; + } + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyGroupEntry.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyGroupEntry.java new file mode 100644 index 000000000..2e39d6aa3 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyGroupEntry.java @@ -0,0 +1,106 @@ +package at.gv.egovernment.moa.spss.server.config; + +import java.math.BigInteger; + +/** + * A class containing information about an entry in a key group. + * + * @author Patrick Peck + * @version $Id$ + */ +public class KeyGroupEntry { + /** The module ID of the key. */ + private String moduleID; + /** The issuer DN of the certificate identifying the key. */ + private String issuerDN; + /** The serial number of the certificate identifying the key. */ + private BigInteger serialNumber; + + /** + * Create a new <code>KeyGroupEntry</code>. + * + * @param moduleID The key module ID to which this entry belongs to. + * @param issuerAndSerial The issuer and serial number which uniquely + * identifies a certificate within the key module. + */ + public KeyGroupEntry(String moduleID, IssuerAndSerial issuerAndSerial) { + this.moduleID = moduleID; + this.issuerDN = issuerAndSerial.getIssuerDN(); + this.serialNumber = issuerAndSerial.getSerial(); + } + + /** + * Create a new <code>KeyGroupEntry</code>. + * + * @param moduleID The key module ID to which this entry belongs to. + * @param issuerDN The isser DN of the certificate within the key module. + * @param serialNumber The serial number of the certificate within the key + * module. + */ + public KeyGroupEntry( + String moduleID, + String issuerDN, + BigInteger serialNumber) { + this.moduleID = moduleID; + this.issuerDN = issuerDN; + this.serialNumber = serialNumber; + } + + /** + * Return the key module ID to which this <code>KeyGroupEntry</code> belongs + * to. + * + * @return The key module ID. + */ + public String getModuleID() { + return moduleID; + } + + /** + * Return the issuer DN of this <code>KeyGroupEntry</code> for identifying the + * certificate within the key module. + * + * @return The issuer DN of the certificate. + */ + public String getIssuerDN() { + return issuerDN; + } + + /** + * Return the serial number of this <code>KeyGroupEntry</code> for identifying + * the certificate within the key module. + * + * @return The serial number of the certificate. + */ + public BigInteger getSerialNumber() { + return serialNumber; + } + + /** + * Compare this <code>KeyGroupEntry</code> to another. + * + * @param other The <code>KeyGroupEntry</code> to compare to. + * @return <code>true</code>, if module ID, isser DN and serial number of + * <code>other</code> match the ones contained in this object, otherwise + * <code>false</code>. + * @see java.lang.Object#equals(Object) + */ + public boolean equals(Object other) { + if (other instanceof KeyGroupEntry) { + KeyGroupEntry entry = (KeyGroupEntry) other; + return getModuleID().equals(entry.getModuleID()) + && getIssuerDN().equals(entry.getIssuerDN()) + && getSerialNumber().equals(entry.getSerialNumber()); + } + return false; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return getModuleID().hashCode() + ^ getIssuerDN().hashCode() + ^ getSerialNumber().hashCode(); + } +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyModule.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyModule.java new file mode 100644 index 000000000..412516d82 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/KeyModule.java @@ -0,0 +1,41 @@ +package at.gv.egovernment.moa.spss.server.config; + +/** + * A class that contains information about a key module. + * + * @author Patrick Peck + * @version $Id$ + */ +public class KeyModule { + + /** The key module ID. */ + private String id; + + /** + * Create a <code>Key</code> object. + * + * @param id The key module ID. + */ + public KeyModule(String id) { + this.id = id; + } + + /** + * Return the key ID. + * + * @return The key ID. + */ + public String getId() { + return id; + } + + /** + * Return a <code>String</code> representation of this <code>Key</code>. + * + * @return The <code>String</code> representation. + * @see java.lang.Object#toString() + */ + public String toString() { + return "(Key - Id<" + id + ">)"; + } +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/SoftwareKeyModule.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/SoftwareKeyModule.java new file mode 100644 index 000000000..479e98ca5 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/SoftwareKeyModule.java @@ -0,0 +1,48 @@ +package at.gv.egovernment.moa.spss.server.config; + +/** + * A class containing information about a software key, stored in PKCS12 format. + * + * @author Patrick Peck + * @version $Id$ + */ +public class SoftwareKeyModule extends KeyModule { + /** The name of the file containing the keys. */ + private String fileName; + /** The password for accessing the file. */ + private String passWord; + + /** + * Create a new <code>SoftwareKey</code>. + * + * @param id The key ID. + * @param fileName The name of the PKCS12 keystore file containing the key. + * @param passWord The password to access the keystore file. + */ + public SoftwareKeyModule(String id, String fileName, String passWord) { + super(id); + this.fileName = fileName; + this.passWord = passWord; + } + + /** + * Return the name of the PKCS12 keystore file containing this + * <code>SoftwareKey</code>. + * + * @return The name of the PKCS12 keystore file. + */ + public String getFileName() { + return fileName; + } + + /** + * Return the password to access the keystore file. + * + * @return The password to access the keystore file. + */ + public String getPassWord() { + return passWord; + } + + +} diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/TrustProfile.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/TrustProfile.java new file mode 100644 index 000000000..6ba33be63 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/TrustProfile.java @@ -0,0 +1,43 @@ +package at.gv.egovernment.moa.spss.server.config; + +/** + * Information about a trust profile. + * + * @author Patrick Peck + * @version $Id$ + */ +public class TrustProfile { + /** The ID of the trust profile. */ + private String id; + /** The URI giving the location of the trust profile. */ + private String uri; + + /** + * Create a <code>TrustProfile</code>. + * + * @param id The ID of the <code>TrustProfile</code> to create. + * @param uri The URI of the <code>TrustProfile</code> to create. + */ + public TrustProfile(String id, String uri) { + this.id = id; + this.uri = uri; + } + + /** + * Return the ID of this <code>TrustProfile</code>. + * + * @return The <code>TrustProfile</code> ID. + */ + public String getId() { + return id; + } + + /** + * Return the URI of this <code>TrustProfile</code>. + * + * @return The URI of <code>TrustProfile</code>. + */ + public String getUri() { + return uri; + } +} |