package at.gv.egovernment.moa.spss.server.invoke;
import java.math.BigInteger;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
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 iaik.server.modules.algorithms.HashAlgorithms;
import iaik.server.modules.keys.KeyEntryID;
import iaik.server.modules.keys.KeyModule;
import iaik.server.modules.keys.KeyModuleFactory;
import iaik.server.modules.xmlsign.SignatureStructureTypes;
import iaik.server.modules.xmlsign.XMLSignatureCreationProfile;
import iaik.server.modules.xmlsign.XMLSignatureInsertionLocation;
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.spss.MOAApplicationException;
import at.gv.egovernment.moa.spss.MOASystemException;
import at.gv.egovernment.moa.spss.api.common.XMLDataObjectAssociation;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateSignatureEnvironmentProfileExplicit;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateSignatureInfo;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateTransformsInfoProfileExplicit;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateXMLSignatureRequest;
import at.gv.egovernment.moa.spss.api.xmlsign.DataObjectInfo;
import at.gv.egovernment.moa.spss.api.xmlsign.SingleSignatureInfo;
import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider;
import at.gv.egovernment.moa.spss.server.config.KeyGroupEntry;
import at.gv.egovernment.moa.spss.server.iaik.xml.CanonicalizationImpl;
import at.gv.egovernment.moa.spss.server.iaik.xmlsign.DataObjectTreatmentImpl;
import at.gv.egovernment.moa.spss.server.iaik.xmlsign.XMLSignatureCreationProfileImpl;
import at.gv.egovernment.moa.spss.server.iaik.xmlsign.XMLSignatureInsertionLocationImpl;
import at.gv.egovernment.moa.spss.server.logging.TransactionId;
import at.gv.egovernment.moa.spss.server.transaction.TransactionContext;
import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager;
import at.gv.egovernment.moa.spss.server.util.IdGenerator;
import at.gv.egovernment.moa.spss.util.MessageProvider;
/**
* A factory to create XMLSignatureCreationProfile
s from a
* CreateXMLSignatureRequest
, based on the current MOA
* configuration.
*
* @author Patrick Peck
* @version $Id$
*/
public class XMLSignatureCreationProfileFactory {
private static Map HASH_ALGORITHM_MAPPING;
static {
HASH_ALGORITHM_MAPPING = new HashMap();
HASH_ALGORITHM_MAPPING.put(Constants.SHA1_URI, HashAlgorithms.SHA1);
}
/** The CreateXMLSignatureRequest
for which to create the
* profile.*/
private CreateXMLSignatureRequest request;
/** How many profiles have been created based on the same request. */
private int createProfileCount;
/** The Set
of reserved object IDs.*/
private Set reserved;
/**
* Create a new XMLSignatureCreationProfileFactory
.
*
* @param request The request for which to create profiles.
* @param reserved The Set
of reserved object IDs. IDs will
* be added during signature creation.
*/
public XMLSignatureCreationProfileFactory(
CreateXMLSignatureRequest request,
Set reserved) {
this.request = request;
this.reserved = reserved;
createProfileCount = 1;
}
/**
* Create a XMLSignatureCreationProfile
for the given
* SingleSignatureInfo
object..
*
* @param singleSignatureInfo The SingleSignatureInfo
object
* containing information about the creation of a signature.
* @return The XMLSignatureCreationProfile
containing additional
* information for creating an XML signature.
* @throws MOASystemException A system error occurred during creation of the
* profile. See message for details
* @throws MOAApplicationException An application error occurred during
* creation of the profile. See message for details.
*/
public XMLSignatureCreationProfile createProfile(SingleSignatureInfo singleSignatureInfo)
throws MOASystemException, MOAApplicationException {
XMLSignatureCreationProfileImpl profile =
new XMLSignatureCreationProfileImpl(createProfileCount, reserved);
TransactionContext context =
TransactionContextManager.getInstance().getTransactionContext();
ConfigurationProvider config = context.getConfiguration();
CanonicalizationImpl canonicalization;
List dataObjectTreatmentList;
String keyGroupID;
Set keySet;
List transformationSupplements;
List createTransformsProfiles;
// build the transformation supplements
createTransformsProfiles =
getCreateTransformsInfoProfiles(singleSignatureInfo);
transformationSupplements =
buildTransformationSupplements(createTransformsProfiles);
// build and set the data object treatment list
dataObjectTreatmentList =
buildDataObjectTreatmentList(
singleSignatureInfo,
createTransformsProfiles,
transformationSupplements);
profile.setDataObjectTreatmentList(dataObjectTreatmentList);
// set the key set
keyGroupID = request.getKeyIdentifier();
keySet = buildKeySet(keyGroupID);
if (keySet == null) {
throw new MOAApplicationException("2231", null);
} else if (keySet.size() == 0) {
throw new MOAApplicationException("2232", null);
}
profile.setKeySet(keySet);
// set the Security Layer manifest algorithm name
profile.setSecurityLayerManifestTypeURI(Constants.SL_MANIFEST_TYPE_URI);
// set the structure type
if (singleSignatureInfo.getCreateSignatureInfo() != null) {
profile.setSignatureStructureType(SignatureStructureTypes.ENVELOPED);
} else {
profile.setSignatureStructureType(SignatureStructureTypes.DETACHED);
}
// set insertion location
profile.setSignatureInsertionLocation(
getSignatureInsertionLocationIndex(singleSignatureInfo));
// set the canonicalization algorithm
canonicalization =
new CanonicalizationImpl(config.getCanonicalizationAlgorithmName());
profile.setSignedInfoCanonicalization(canonicalization);
// set the signed properties
profile.setSignedProperties(Collections.EMPTY_LIST);
// set security layer conformity
profile.setSecurityLayerConform(
singleSignatureInfo.isSecurityLayerConform());
// update the createProfileCount
createProfileCount++;
return profile;
}
/**
* Get the List
of all CreateTransformsInfoProfile
s
* contained in all the DataObjectInfo
s of the given
* SingleSignatureInfo
.
*
* @param singleSignatureInfo The SingleSignatureInfo
object from
* which to extract the CreateTransformsInfoProfile
s.
* @return All CreateTransformsInfoProfile
s of all
* DataObjectInfo
s of singleSignatureInfo
.
* @throws MOAApplicationException An error occurred creating one of the
* profiles.
*/
List getCreateTransformsInfoProfiles(SingleSignatureInfo singleSignatureInfo)
throws MOAApplicationException {
TransactionContext context =
TransactionContextManager.getInstance().getTransactionContext();
ConfigurationProvider config = context.getConfiguration();
List dataObjInfos = singleSignatureInfo.getDataObjectInfos();
List profiles = new ArrayList();
Iterator dtIter;
for (dtIter = dataObjInfos.iterator(); dtIter.hasNext();) {
DataObjectInfo dataObjInfo = (DataObjectInfo) dtIter.next();
CreateTransformsInfoProfileExplicit profile =
ProfileMapper.mapCreateTransformsInfoProfile(
dataObjInfo.getCreateTransformsInfoProfile(),
config);
profiles.add(profile);
}
return profiles;
}
/**
* Build the List
of transformation supplements contained in a
* SingleSignatureInfo
object.
*
* @param createTransformsInfoProfiles The
* CreateTransformsInfoProfile
object from which to extract the
* transformation supplements.
* @return A List
of DataObject
s containing the
* transformation supplements.
* @throws MOASystemException A system error occurred creating one of the
* transformation supplements.
* @throws MOAApplicationException An error occurred creating one of the
* transformation supplements.
*/
private List buildTransformationSupplements(List createTransformsInfoProfiles)
throws MOASystemException, MOAApplicationException {
List transformationSupplements = new ArrayList();
DataObjectFactory factory = DataObjectFactory.getInstance();
Iterator iter;
for (iter = createTransformsInfoProfiles.iterator(); iter.hasNext();) {
CreateTransformsInfoProfileExplicit profile =
(CreateTransformsInfoProfileExplicit) iter.next();
List supplements = profile.getSupplements();
if (supplements != null) {
Iterator supplIter;
for (supplIter = supplements.iterator(); supplIter.hasNext();) {
XMLDataObjectAssociation supplement =
(XMLDataObjectAssociation) supplIter.next();
transformationSupplements.add(
factory.createFromXmlDataObjectAssociation(
supplement,
false,
true));
}
}
}
return transformationSupplements;
}
/**
* Build the List
of DataObjectTreatment
s for the
* given SingleSignatureInfo
object..
*
* @param singleSignatureInfo The SingleSignatureInfo
object
* from which to exctract the CreateTransformsInfoProfile
s
* containing the data for the DataObjectTreatment
s.
* @param createTransformsInfoProfiles The
* CreateTransformsInfoProfile
s contained in the
* singleSignatureInfo
.
* @param transformationSupplements Additional parameters for
* transformations contained in DataObjectTreatment
s.
* @return A List
of DataObjectTreatment
objects.
* @throws MOAApplicationException An error occurred building one of the
* DataObjectTreatment
s.
* @throws MOASystemException A system error occurred building one of the
* DataObjectTreatment
s.
*/
private List buildDataObjectTreatmentList(
SingleSignatureInfo singleSignatureInfo,
List createTransformsInfoProfiles,
List transformationSupplements)
throws MOASystemException, MOAApplicationException {
TransactionContext context =
TransactionContextManager.getInstance().getTransactionContext();
ConfigurationProvider config = context.getConfiguration();
List treatments = new ArrayList();
List dataObjInfos = singleSignatureInfo.getDataObjectInfos();
int dataObjectTreatmentCount = 1;
String hashAlgorithmName;
Iterator dtIter;
Iterator prIter;
prIter = createTransformsInfoProfiles.iterator();
for (dtIter = dataObjInfos.iterator(); dtIter.hasNext();) {
CreateTransformsInfoProfileExplicit profile =
(CreateTransformsInfoProfileExplicit) prIter.next();
DataObjectInfo dataObjInfo = (DataObjectInfo) dtIter.next();
IdGenerator objIdGen =
new IdGenerator(
("signed-data-" + createProfileCount)
+ ("-" + dataObjectTreatmentCount++),
reserved);
DataObjectTreatmentImpl treatment = new DataObjectTreatmentImpl(objIdGen);
treatment.setFinalContentType(
profile.getCreateTransformsInfo().getFinalDataMetaInfo().getMimeType());
treatment.setTransformationList(buildTransformationList(profile));
treatment.setReferenceInManifest(dataObjInfo.isChildOfManifest());
hashAlgorithmName =
(String) HASH_ALGORITHM_MAPPING.get(
config.getDigestMethodAlgorithmName());
if (hashAlgorithmName == null) {
error(
"config.17",
new Object[] { config.getDigestMethodAlgorithmName()});
throw new MOASystemException("2900", null);
}
treatment.setHashAlgorithmName(hashAlgorithmName);
treatment.setIncludedInSignature(
DataObjectInfo.STRUCTURE_ENVELOPING.equals(dataObjInfo.getStructure()));
treatment.setTransformationSupplements(transformationSupplements);
treatments.add(treatment);
}
return treatments;
}
/**
* Build the List
of transformations contained in a
* CreateTransformsInfoProfile
object.
*
* @param profile The CreateTransformsInfoProfile
object
* from which to extract the Transform
s.
* @return A List
of Transformation
s contained in
* the given CreateTransformsInfoProfile
.
* @throws MOAApplicationException An error occurred building one of the
* Transformation
s.
*/
private List buildTransformationList(CreateTransformsInfoProfileExplicit profile)
throws MOAApplicationException {
TransformationFactory factory = TransformationFactory.getInstance();
List transforms = profile.getCreateTransformsInfo().getTransforms();
return transforms != null
? factory.createTransformationList(transforms)
: Collections.EMPTY_LIST;
}
/**
* Build the set of KeyEntryID
s available to the given
* keyGroupID
.
*
* @param keyGroupID The keygroup ID for which the available keys should be
* returned.
* @return The Set
of KeyEntryID
s
* identifying the available keys.
*/
private Set buildKeySet(String keyGroupID) {
TransactionContext context =
TransactionContextManager.getInstance().getTransactionContext();
ConfigurationProvider config = context.getConfiguration();
Set keyGroupEntries;
// get the KeyGroup entries from the configuration
if (context.getClientCertificate() != null) {
X509Certificate cert = context.getClientCertificate()[0];
Principal issuer = cert.getIssuerDN();
BigInteger serialNumber = cert.getSerialNumber();
keyGroupEntries =
config.getKeyGroupEntries(issuer, serialNumber, keyGroupID);
} else {
keyGroupEntries = config.getKeyGroupEntries(null, null, keyGroupID);
}
// map the KeyGroup entries to a set of KeyEntryIDs
if (keyGroupEntries == null) {
return null;
} else if (keyGroupEntries.size() == 0) {
return Collections.EMPTY_SET;
} else {
KeyModule module =
KeyModuleFactory.getInstance(
new TransactionId(context.getTransactionID()));
Set keyEntryIDs = module.getPrivateKeyEntryIDs();
Set keySet = new HashSet();
Iterator iter;
// filter out the keys that do not exist in the IAIK configuration
// by walking through the key entries and checking if the exist in the
// keyGroupEntries
for (iter = keyEntryIDs.iterator(); iter.hasNext();) {
KeyEntryID entryID = (KeyEntryID) iter.next();
KeyGroupEntry entry =
new KeyGroupEntry(
entryID.getModuleID(),
entryID.getCertificateIssuer(),
entryID.getCertificateSerialNumber());
if (keyGroupEntries.contains(entry)) {
keySet.add(entryID);
}
}
return keySet;
}
}
/**
* Get the signature location index where the signature will be inserted into
* the signature parent element.
*
* @param singleSignatureInfo The SingleSignatureInfo
object
* containing the CreateSignatureLocation
.
* @return The index at which to insert the signature into the signature
* environment.
* @throws MOAApplicationException An error occurred parsing the
* CreateSignatureEnvironmentProfile
.
*/
private XMLSignatureInsertionLocation getSignatureInsertionLocationIndex(SingleSignatureInfo singleSignatureInfo)
throws MOAApplicationException {
CreateSignatureInfo createInfo =
singleSignatureInfo.getCreateSignatureInfo();
if (createInfo != null) {
TransactionContext context =
TransactionContextManager.getInstance().getTransactionContext();
ConfigurationProvider config = context.getConfiguration();
CreateSignatureEnvironmentProfileExplicit profile =
ProfileMapper.mapCreateSignatureEnvironmentProfile(
createInfo.getCreateSignatureEnvironmentProfile(),
config);
int index = profile.getCreateSignatureLocation().getIndex();
return new XMLSignatureInsertionLocationImpl(index);
} else {
return new XMLSignatureInsertionLocationImpl(0);
}
}
/**
* Utility function to issue an error message to the log.
*
* @param messageId The ID of the message to log.
* @param parameters Additional message parameters.
*/
private static void error(String messageId, Object[] parameters) {
MessageProvider msg = MessageProvider.getInstance();
Logger.error(new LogMsg(msg.getMessage(messageId, parameters)));
}
}