diff options
author | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2015-11-03 14:38:34 +0100 |
---|---|---|
committer | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2015-11-03 14:38:34 +0100 |
commit | 0872d2d8a64fd701776b272f49222428d8def07f (patch) | |
tree | 0954a523ad2cc7ad615dbbae5282dd56497e4c6e /moaSig/moa-sig/src/main/java | |
parent | e635718b8d6a12e4e80207c8bdf30b02eed3f2ab (diff) | |
download | moa-sig-0872d2d8a64fd701776b272f49222428d8def07f.tar.gz moa-sig-0872d2d8a64fd701776b272f49222428d8def07f.tar.bz2 moa-sig-0872d2d8a64fd701776b272f49222428d8def07f.zip |
initial commit
Diffstat (limited to 'moaSig/moa-sig/src/main/java')
22 files changed, 2714 insertions, 0 deletions
diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/initializer/PDFASInitializer.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/initializer/PDFASInitializer.java new file mode 100644 index 0000000..bacd7cb --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/initializer/PDFASInitializer.java @@ -0,0 +1,18 @@ +package at.gv.egovernment.moa.spss.server.initializer; + +import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; +import at.gv.egovernment.moa.spss.server.init.ExternalInitializer; +import at.gv.egovernment.moa.spss.server.invoke.PDFASInvoker; + +public class PDFASInitializer implements ExternalInitializer { + + @Override + public void initialize(ConfigurationProvider configurationProvider) { + String pdfAsConfiguration = configurationProvider.getPDFASConfiguration(); + if(pdfAsConfiguration != null) { + PDFASInvoker + .init(pdfAsConfiguration); + } + } + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/invoke/PDFASInvoker.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/invoke/PDFASInvoker.java new file mode 100644 index 0000000..97bf58b --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/invoke/PDFASInvoker.java @@ -0,0 +1,132 @@ +package at.gv.egovernment.moa.spss.server.invoke; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.io.IOUtils; + +import at.gv.egiz.pdfas.common.exceptions.PDFASError; +import at.gv.egiz.pdfas.lib.api.ByteArrayDataSource; +import at.gv.egiz.pdfas.lib.api.Configuration; +import at.gv.egiz.pdfas.lib.api.PdfAs; +import at.gv.egiz.pdfas.lib.api.PdfAsFactory; +import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; +import at.gv.egiz.pdfas.lib.api.sign.SignParameter; +import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.sigs.pades.PAdESSigner; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.server.logging.TransactionId; +import at.gv.egovernment.moa.spss.server.pdfas.InternalMoaConnector; +import at.gv.egovernment.moa.spss.server.xmlbind.CreatePDFRequest; +import at.gv.egovernment.moa.spss.server.xmlbind.CreatePDFRespone; +import at.gv.egovernment.moa.spss.server.xmlbind.PDFSignatureInfo; +import at.gv.egovernment.moa.spss.server.xmlbind.SignedPDFInfo; +import at.gv.egovernment.moa.spss.server.xmlbind.VerifyPDFRequest; +import at.gv.egovernment.moa.spss.server.xmlbind.VerifyPDFResponse; + +public class PDFASInvoker { + + private static PDFASInvoker instance = null; + + private PdfAs pdfAS; + + private PDFASInvoker(File configuration) { + pdfAS = PdfAsFactory.createPdfAs(configuration); + } + + public synchronized static void init(String pdfAsConfiguration) { + instance = new PDFASInvoker(new File(pdfAsConfiguration)); + } + + public synchronized static PDFASInvoker getInstance() { + if (instance == null) { + throw new RuntimeException("PDF PDFASInvoker not initialized"); + } + return instance; + } + + public VerifyPDFResponse verifyPDFSignature(VerifyPDFRequest verifyPDFRequest, String transactionId) { + Configuration pdfConfiguration = this.pdfAS.getConfiguration(); + + VerifyPDFResponse verifyPDFResponse = new VerifyPDFResponse(); + + VerifyParameter verifyParameter = PdfAsFactory.createVerifyParameter(pdfConfiguration, new ByteArrayDataSource( + verifyPDFRequest.getSignedPDF())); + + try { + List<VerifyResult> verifyResults = this.pdfAS.verify(verifyParameter); + verifyPDFResponse.setResponseType(VerifyPDFResponse.SUCCESS_SIGNATURE); + verifyPDFResponse.setVerificationResults(verifyResults); + } catch (Throwable e) { + if (e instanceof PDFASError) { + PDFASError pdfAsError = (PDFASError) e; + Logger.warn("Failed to generate signed PDF document", e); + verifyPDFResponse.setErrorCode((int) pdfAsError.getCode()); + verifyPDFResponse.setErrorInfo(pdfAsError.getInfo()); + } else { + Logger.error("Unknown exception!: ", e); + verifyPDFResponse.setErrorCode(9999); + verifyPDFResponse.setErrorInfo("Nicht klassifizierter Fehler"); + } + } + + return verifyPDFResponse; + } + + public CreatePDFRespone createPDFSignature(CreatePDFRequest createPDFRequest, String transactionId) { + Configuration pdfConfiguration = this.pdfAS.getConfiguration(); + + String keyIdentifier = createPDFRequest.getKeyIdentifier(); + + Iterator<PDFSignatureInfo> signatureInfoIterator = createPDFRequest.getSignatureInfoList().iterator(); + + CreatePDFRespone createPDFRespone = new CreatePDFRespone(); + + while (signatureInfoIterator.hasNext()) { + PDFSignatureInfo pdfSignatureInfo = signatureInfoIterator.next(); + SignedPDFInfo signedPDFInfo = new SignedPDFInfo(pdfSignatureInfo.getSignatureID()); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SignParameter signParameter = PdfAsFactory.createSignParameter(pdfConfiguration, + new ByteArrayDataSource(pdfSignatureInfo.getPdfDocument()), baos); + + signParameter.setSignaturePosition(pdfSignatureInfo.getSignaturePosition()); + signParameter.setSignatureProfileId(pdfSignatureInfo.getSignatureProfile()); + + IPlainSigner signer = new PAdESSigner( + new InternalMoaConnector(keyIdentifier, new TransactionId(transactionId), null)); + + signParameter.setPlainSigner(signer); + + try { + this.pdfAS.sign(signParameter); + signedPDFInfo.setPdfDocument(baos.toByteArray()); + signedPDFInfo.setResponseType(SignedPDFInfo.SUCCESS_SIGNATURE); + } catch (Throwable e) { + signedPDFInfo.setResponseType(SignedPDFInfo.ERROR_RESPONSE); + + if (e instanceof PDFASError) { + PDFASError pdfAsError = (PDFASError) e; + Logger.warn("Failed to generate signed PDF document", e); + signedPDFInfo.setErrorCode((int) pdfAsError.getCode()); + signedPDFInfo.setErrorInfo(pdfAsError.getInfo()); + } else { + Logger.error("Unknown exception!: ", e); + signedPDFInfo.setErrorCode(9999); + signedPDFInfo.setErrorInfo("Nicht klassifizierter Fehler"); + } + } finally { + IOUtils.closeQuietly(baos); + } + + } finally { + createPDFRespone.getSignatureInfoList().add(signedPDFInfo); + } + + } + return createPDFRespone; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/ExtendedVerifyResult.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/ExtendedVerifyResult.java new file mode 100644 index 0000000..30bf148 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/ExtendedVerifyResult.java @@ -0,0 +1,61 @@ +package at.gv.egovernment.moa.spss.server.pdfas; + +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl; + +public class ExtendedVerifyResult extends VerifyResultImpl implements VerifyResult { + private String qcSource; + private boolean publicAuthority; + private String publicAuthorityID; + private boolean SSCD; + private String sscdSource; + private String issureCountryCode; + + public synchronized String getIssureCountryCode() { + return issureCountryCode; + } + + public synchronized void setIssureCountryCode(String issureCountryCode) { + this.issureCountryCode = issureCountryCode; + } + + public synchronized String getQcSource() { + return qcSource; + } + + public synchronized void setQcSource(String qcSource) { + this.qcSource = qcSource; + } + + public synchronized boolean isPublicAuthority() { + return publicAuthority; + } + + public synchronized void setPublicAuthority(boolean publicAuthority) { + this.publicAuthority = publicAuthority; + } + + public synchronized String getPublicAuthorityID() { + return publicAuthorityID; + } + + public synchronized void setPublicAuthorityID(String publicAuthorityID) { + this.publicAuthorityID = publicAuthorityID; + } + + public synchronized boolean isSSCD() { + return SSCD; + } + + public synchronized void setSSCD(boolean sSCD) { + SSCD = sSCD; + } + + public synchronized String getSscdSource() { + return sscdSource; + } + + public synchronized void setSscdSource(String sscdSource) { + this.sscdSource = sscdSource; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/InternalMoaConnector.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/InternalMoaConnector.java new file mode 100644 index 0000000..6edee0d --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/InternalMoaConnector.java @@ -0,0 +1,226 @@ +package at.gv.egovernment.moa.spss.server.pdfas; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.lib.api.sign.SignParameter; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; +import at.gv.egiz.sl.util.ISignatureConnector; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.cmssign.CMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.cmssign.CreateCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.cmssign.CreateCMSSignatureResponseElement; +import at.gv.egovernment.moa.spss.api.impl.CMSContentExplicitImpl; +import at.gv.egovernment.moa.spss.api.impl.CMSDataObjectImpl; +import at.gv.egovernment.moa.spss.api.impl.CreateCMSSignatureRequestImpl; +import at.gv.egovernment.moa.spss.api.impl.DataObjectInfoCMSImpl; +import at.gv.egovernment.moa.spss.api.impl.MetaInfoImpl; +import at.gv.egovernment.moa.spss.api.impl.SingleSignatureInfoCMSImpl; +import at.gv.egovernment.moa.spss.api.xmlsign.ErrorResponse; +import at.gv.egovernment.moa.spss.server.config.ConfigurationException; +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.invoke.CMSSignatureCreationInvoker; +import at.gv.egovernment.moa.util.Base64Utils; +import iaik.logging.TransactionId; +import iaik.server.modules.keys.KeyEntryID; +import iaik.server.modules.keys.KeyModule; +import iaik.server.modules.keys.KeyModuleFactory; +import iaik.server.modules.keys.UnknownKeyException; +import iaik.x509.X509Certificate; + +public class InternalMoaConnector implements ISignatureConnector { + + private String keyIdentifier; + private X509Certificate clientCert; + private TransactionId transactionId; + + public InternalMoaConnector(String keyIdentifier, TransactionId transactionId, X509Certificate clientCert) { + this.keyIdentifier = keyIdentifier; + this.transactionId = transactionId; + this.clientCert = clientCert; + } + + private Set buildKeySet(String keyGroupID, KeyModule module) throws ConfigurationException { + ConfigurationProvider config = ConfigurationProvider.getInstance(); + Set keyGroupEntries; + + // get the KeyGroup entries from the configuration + if (clientCert != null) { + Principal issuer = clientCert.getIssuerDN(); + BigInteger serialNumber = clientCert.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 Collections.EMPTY_SET; + } else if (keyGroupEntries.size() == 0) { + return Collections.EMPTY_SET; + } else { + + 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; + } + } + + @Override + public X509Certificate getCertificate(SignParameter parameter) throws PdfAsException { + KeyModule module = KeyModuleFactory.getInstance(this.transactionId); + + Set keySet = null; + try { + keySet = buildKeySet(this.keyIdentifier, module); + } catch (ConfigurationException e2) { + Logger.warn("MOA not correctly configured!", e2); + throw new PdfAsException("MOA not correctly configured!"); + } + + if (keySet == null || keySet.isEmpty()) { + Logger.warn("No keys available for Key Identifier " + this.keyIdentifier + " and given authentication."); + throw new PdfAsException("Invalid Key Identifier: " + this.keyIdentifier); + } + + if (keySet.size() != 1) { + Logger.warn( + "Too many keys available for Key Identifier " + this.keyIdentifier + " and given authentication."); + throw new PdfAsException("Too many keys available for Key Identifier: " + this.keyIdentifier); + } + + 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 = keySet.iterator(); iter.hasNext();) { + KeyEntryID entryID = (KeyEntryID) iter.next(); + + List certChain = null; + try { + certChain = module.getPrivateKeyEntry(entryID).getCertificateChain(); + } catch (UnknownKeyException e1) { + Logger.warn("Unknown KeyIdentifier found!", e1); + throw new PdfAsException("Unknown Key Identifier: " + this.keyIdentifier); + } + + if (certChain != null && !certChain.isEmpty()) { + Logger.trace("Returning Certificate!"); + Certificate keyCert = ((Certificate) certChain.get(0)); + if (keyCert instanceof X509Certificate) { + return (X509Certificate) keyCert; + } else { + try { + return new X509Certificate(keyCert.getEncoded()); + } catch (CertificateEncodingException e) { + Logger.warn("Invalid certificate found!", e); + throw new PdfAsException("Invalid certificate for Key Identifier: " + this.keyIdentifier); + } catch (CertificateException e) { + Logger.warn("Invalid certificate found!", e); + throw new PdfAsException("Invalid certificate for Key Identifier: " + this.keyIdentifier); + } + } + } + + break; + } + + // No Certificate could be found! + Logger.warn("Failed to find keys available for Key Identifier " + this.keyIdentifier + + " and given authentication."); + throw new PdfAsException("Failed to find keys available for Key Identifier: " + this.keyIdentifier); + } + + @Override + public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter, RequestedSignature requestedSignature) + throws PdfAsException { + + CreateCMSSignatureRequestImpl createCMSSignatureRequest = new CreateCMSSignatureRequestImpl(); + createCMSSignatureRequest.setKeyIdentifier(this.keyIdentifier); + SingleSignatureInfoCMSImpl singleSignatureInfos = new SingleSignatureInfoCMSImpl(); + + DataObjectInfoCMSImpl dataObjectInfoCMSImpl = new DataObjectInfoCMSImpl(); + + dataObjectInfoCMSImpl.setStructure(DataObjectInfoCMSImpl.STRUCTURE_DETACHED); + + CMSDataObjectImpl cmsDataObjectImpl = new CMSDataObjectImpl(); + + CMSContentExplicitImpl cmsContent = new CMSContentExplicitImpl(); + cmsContent.setBinaryContent(new ByteArrayInputStream(input)); + + cmsDataObjectImpl.setContent(cmsContent); + + MetaInfoImpl metaInfoImpl = new MetaInfoImpl(); + + metaInfoImpl.setMimeType("application/pdf"); + + cmsDataObjectImpl.setMetaInfo(metaInfoImpl); + + dataObjectInfoCMSImpl.setDataObject(cmsDataObjectImpl); + + singleSignatureInfos.setDataObjectInfo(dataObjectInfoCMSImpl); + + createCMSSignatureRequest.getSingleSignatureInfos().add(singleSignatureInfos); + + try { + CreateCMSSignatureResponse createCMSSignatureResponse = CMSSignatureCreationInvoker.getInstance() + .createCMSSignature(createCMSSignatureRequest, Collections.EMPTY_SET); + + if (createCMSSignatureResponse.getResponseElements().isEmpty()) { + Logger.error("MOA CMS Signature response is empty!"); + throw new PdfAsException("MOA CMS Signature response is empty"); + } + + CreateCMSSignatureResponseElement createCMSSignatureResponseElement = (CreateCMSSignatureResponseElement) createCMSSignatureResponse + .getResponseElements().get(0); + + if(createCMSSignatureResponseElement.getResponseType() + == CreateCMSSignatureResponseElement.ERROR_RESPONSE) { + ErrorResponse errorResponse = (ErrorResponse) createCMSSignatureResponseElement; + } else if(createCMSSignatureResponseElement.getResponseType() + == CreateCMSSignatureResponseElement.CMS_SIGNATURE ) { + CMSSignatureResponse cmsSignatureResponse = (CMSSignatureResponse) createCMSSignatureResponseElement; + return Base64Utils.decode(cmsSignatureResponse.getCMSSignature(), true); + } + } catch (MOAException e) { + Logger.error("Failed to create signature!", e); + throw new PdfAsException("Failed to create signature!", e); + } catch (IOException e) { + Logger.error("Failed to create signature!", e); + throw new PdfAsException("Failed to create signature!", e); + } + + return null; + } + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/InternalMoaVerifier.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/InternalMoaVerifier.java new file mode 100644 index 0000000..f937495 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/pdfas/InternalMoaVerifier.java @@ -0,0 +1,128 @@ +package at.gv.egovernment.moa.spss.server.pdfas; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.lib.api.Configuration; +import at.gv.egiz.pdfas.lib.api.verify.SignatureCheck; +import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.lib.impl.verify.IVerifier; +import at.gv.egiz.pdfas.lib.impl.verify.SignatureCheckImpl; +import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponseElement; +import at.gv.egovernment.moa.spss.api.common.CheckResult; +import at.gv.egovernment.moa.spss.api.impl.CMSContentExplicitImpl; +import at.gv.egovernment.moa.spss.api.impl.CMSDataObjectImpl; +import at.gv.egovernment.moa.spss.api.impl.MetaInfoImpl; +import at.gv.egovernment.moa.spss.api.impl.VerifyCMSSignatureRequestImpl; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; +import iaik.x509.X509Certificate; + +public class InternalMoaVerifier implements IVerifier { + + public static final String MOA_TRUSTPROFILE = "internal.moa.trustprofile"; + + private String trustProfile; + + private static final Logger logger = LoggerFactory.getLogger(InternalMoaVerifier.class); + + @Override + public List<VerifyResult> verify(byte[] signature, byte[] signatureContent, Date verificationTime) + throws PdfAsException { + + List<VerifyResult> verificationResultList = new ArrayList<VerifyResult>(); + + VerifyCMSSignatureRequestImpl verifyCMSSignatureRequest = new VerifyCMSSignatureRequestImpl(); + verifyCMSSignatureRequest.setDateTime(verificationTime); + verifyCMSSignatureRequest.setTrustProfileId(this.trustProfile); + verifyCMSSignatureRequest.setCMSSignature(new ByteArrayInputStream(signature)); + + CMSContentExplicitImpl cmsContentExplicitImpl = new CMSContentExplicitImpl(); + cmsContentExplicitImpl.setBinaryContent(new ByteArrayInputStream(signatureContent)); + + CMSDataObjectImpl cmsDataObjectImpl = new CMSDataObjectImpl(); + cmsDataObjectImpl.setContent(cmsContentExplicitImpl); + + MetaInfoImpl metaInfo = new MetaInfoImpl(); + metaInfo.setMimeType("application/pdf"); + metaInfo.setDescription("PDF Document"); + cmsDataObjectImpl.setMetaInfo(metaInfo); + + verifyCMSSignatureRequest.setDataObject(cmsDataObjectImpl); + + verifyCMSSignatureRequest.setSignatories(VerifyCMSSignatureRequest.ALL_SIGNATORIES); + + try { + VerifyCMSSignatureResponse verifyCMSSignatureResponse = CMSSignatureVerificationInvoker.getInstance() + .verifyCMSSignature(verifyCMSSignatureRequest); + Iterator iter; + for (iter = verifyCMSSignatureResponse.getResponseElements().iterator(); iter.hasNext();) { + VerifyCMSSignatureResponseElement responseElement = (VerifyCMSSignatureResponseElement) iter.next(); + ExtendedVerifyResult verifyResult = new ExtendedVerifyResult(); + + verifyResult.setCertificateCheck(convertCheck(responseElement.getCertificateCheck())); + verifyResult.setValueCheckCode(convertCheck(responseElement.getSignatureCheck())); + verifyResult.setManifestCheckCode(new SignatureCheckImpl(99, null)); + verifyResult.setQualifiedCertificate(responseElement.getSignerInfo().isQualifiedCertificate()); + verifyResult.setVerificationDone(true); + + if (responseElement.getSignerInfo().getSignerCertificate() instanceof X509Certificate) { + verifyResult.setSignerCertificate( + (X509Certificate) responseElement.getSignerInfo().getSignerCertificate()); + } else { + verifyResult.setSignerCertificate( + new X509Certificate(responseElement.getSignerInfo().getSignerCertificate().getEncoded())); + } + + verifyResult.setQcSource(responseElement.getSignerInfo().getQCSource()); + + verifyResult.setPublicAuthority(responseElement.getSignerInfo().isPublicAuthority()); + verifyResult.setPublicAuthorityID(responseElement.getSignerInfo().getPublicAuhtorityID()); + verifyResult.setSSCD(responseElement.getSignerInfo().isSSCD()); + verifyResult.setSscdSource(responseElement.getSignerInfo().getSSCDSource()); + verifyResult.setIssureCountryCode(responseElement.getSignerInfo().getIssuerCountryCode()); + + verificationResultList.add(verifyResult); + } + } catch (MOAException e) { + logger.error("Failed to verify CMS Signature with MOA", e); + throw new PdfAsException("Failed to verify CMS Signature with MOA", e); + } catch (CertificateEncodingException e) { + logger.error("Failed to verify CMS Signature with MOA", e); + throw new PdfAsException("Failed to verify CMS Signature with MOA", e); + } catch (CertificateException e) { + logger.error("Failed to verify CMS Signature with MOA", e); + throw new PdfAsException("Failed to verify CMS Signature with MOA", e); + } + + return verificationResultList; + } + + private SignatureCheck convertCheck(CheckResult checkResult) { + return new SignatureCheckImpl(checkResult.getCode(), null); + } + + @Override + public void setConfiguration(Configuration config) { + this.trustProfile = config.getValue(MOA_TRUSTPROFILE); + } + + @Override + public SignatureVerificationLevel getLevel() { + return SignatureVerificationLevel.FULL_VERIFICATION; + } + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java new file mode 100644 index 0000000..a18ee9f --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/AxisHandler.java @@ -0,0 +1,476 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egovernment.moa.spss.server.service; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.cert.X509Certificate; +import java.util.Iterator; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.axis.AxisFault; +import org.apache.axis.Message; +import org.apache.axis.MessageContext; +import org.apache.axis.attachments.AttachmentPart; +import org.apache.axis.handlers.BasicHandler; +import org.apache.axis.transport.http.HTTPConstants; +import org.apache.axis.utils.Messages; +import org.apache.axis.utils.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import at.gv.egovernment.moa.logging.LogMsg; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.logging.LoggingContext; +import at.gv.egovernment.moa.logging.LoggingContextManager; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; +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.transaction.TransactionIDGenerator; +import at.gv.egovernment.moa.spss.util.MessageProvider; +import at.gv.egovernment.moa.util.DOMUtils; + +/** + * An handler that is invoked on each web service request and performs some + * central message handling. + * + * Mainly sets up the <code>TransactionContext</code> for the current + * transaction (i.e. web service request). + * + * @author Patrick Peck + * @author Stefan Knirsch + * @version $Id$ + */ +public class AxisHandler extends BasicHandler { + + /** + * + */ + private static final long serialVersionUID = 2520698947819506866L; + + /** The resource names of the messages to load. */ + private static final String MOA_SPSS_WSDL_RESOURCE_ = "/resources/wsdl/MOA-SPSS-2.0.0.wsdl"; + + /** The property name for accessing the HTTP request. */ + private static final String REQUEST_PROPERTY = HTTPConstants.MC_HTTP_SERVLETREQUEST; + + /** The property name for accessing the X509 client certificate chain. */ + private static final String X509_CERTIFICATE_PROPERTY = "javax.servlet.request.X509Certificate"; + + /** The property name for accessing the SOAP action header. */ + private static final String SOAP_ACTION_HEADER = "soapaction"; + + /** URI of the SOAP XML namespace. */ + public static final String SOAP_NS_URI = "http://schemas.xmlsoap.org/soap/envelope/"; + + /** Prefix used for the SOAP XML namespace */ + public static final String SOAP_PREFIX = "soapenv"; + + /** Simple string contains the front part of the enveloping SOAP wrapping */ + private static final String SOAP_PART_PRE = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body>"; + + /** Simple string contains the post part of the enveloping SOAP wrapping */ + private static final String SOAP_PART_POST = "</soapenv:Body></soapenv:Envelope>"; + + /** + * Handle an invocation of this handler. + * + * @param msgContext + * Information about this request/response. + * @throws AxisFault + * An error occurred during processing of the request. + * @see org.apache.axis.Handler#invoke(MessageContext) + */ + public void invoke(MessageContext msgContext) throws AxisFault { + if (!msgContext.getPastPivot()) { + handleRequest(msgContext); + } else { + handleResponse(msgContext); + } + } + + /** + * This method is called by <code>invoke</code> to handle incoming requests. + * + * @param msgContext + * The context as provided to <code>invoke</code>. + * @throws AxisFault + * An error occurred during processing of the request. + */ + private void handleRequest(MessageContext msgContext) throws AxisFault { + try { + Logger.trace("---- Entering Axishandler"); + // generate a unique transaction id and build the TransactionContext + // for this request + HttpServletRequest request = (HttpServletRequest) msgContext.getProperty(REQUEST_PROPERTY); + + X509Certificate[] clientCert = (X509Certificate[]) request.getAttribute(X509_CERTIFICATE_PROPERTY); + + // Configure Axis + // AxisProperties.setProperty(AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION,"false"); + // AxisProperties.setProperty(AxisEngine.PROP_DOMULTIREFS,"false"); + // AxisProperties.setProperty(AxisEngine.PROP_SEND_XSI,"true"); + // msgContext.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION, + // Boolean.FALSE); + // msgContext.setProperty(org.apache.axis. + // AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION,"false"); + + Message soapMessage = msgContext.getCurrentMessage(); + + ConfigurationProvider configuration = ConfigurationProvider.getInstance(); + + Element xmlRequest = null; + // log.info(soapMessage.getSOAPPartAsString()); + Element soapPart = DOMUtils + .parseDocument(new ByteArrayInputStream(soapMessage.getSOAPPartAsBytes()), false, null, null) + .getDocumentElement(); + if (soapPart != null) { + // TODO: check if DOM Version is intolerant when white spaces + // are between tags (preceding normalization would be necessary) + NodeList soapBodies = soapPart.getElementsByTagNameNS(SOAP_NS_URI, "Body"); + if (soapBodies != null && soapBodies.getLength() > 0) { + xmlRequest = DOMUtils.getElementFromNodeList(soapBodies.item(0).getChildNodes()); + } + // oder TODO: Evaluierung ob XPATH schneller + /* + * HashMap nSMap = new HashMap(); nSMap.put((String)SOAP_PREFIX, + * SOAP_NS_URI); Element soapBody = (Element) + * XPathUtils.selectSingleNode(soapPart, nSMap, + * "/"+SOAP_PREFIX+":Envelope/"+SOAP_PREFIX+":Body"); if + * (soapBody!=null) { xmlRequest = + * DOMUtils.getElementFromNodeList(soapBody.getChildNodes()); } + */ + } + + TransactionContext context = new TransactionContext(TransactionIDGenerator.nextID(), clientCert, + configuration, xmlRequest, null); + + String soapAction = (String) request.getHeader(SOAP_ACTION_HEADER); + if ("\"\"".equals(soapAction)) { + // if http soap action header is empty + soapAction = msgContext.getTargetService(); + } + context.setRequestName(soapAction); + + if (soapMessage.getAttachmentsImpl() != null) { + Logger.info("Attachments is NOT null!"); + Logger.trace(">>> Get AttachmentCount"); + int attachmentCount = soapMessage.getAttachmentsImpl().getAttachmentCount(); + Logger.trace("<<< Finished Get AttachmentCount"); + if (attachmentCount > 0) { + + // add SOAP attachments to transaction context + @SuppressWarnings("rawtypes") + Iterator iterator = soapMessage.getAttachments(); + while (iterator.hasNext()) { + AttachmentPart attachment = (AttachmentPart) iterator.next(); + String id = attachment.getContentId(); + String type = attachment.getContentType(); + + // Now get the InputStream (note: we could also get the + // content with Object content = + // attachment.getContent();) + InputStream is = null; + javax.activation.DataHandler datahandler = attachment.getDataHandler(); + + int TYPE = 2; + switch (TYPE) { + case 1: { + org.apache.axis.attachments.ManagedMemoryDataSource mmds = (org.apache.axis.attachments.ManagedMemoryDataSource) datahandler + .getDataSource(); + context.addAttachment(id, type, mmds); + break; + } + case 2: { + is = datahandler.getDataSource().getInputStream(); + context.addAttachment(id, type, is, datahandler.getDataSource().getName()); + break; + } + } + debug("handler.06", new Object[] { id, type }); + } + } + } else { + Logger.info("Attachments is null!"); + } + + setUpContexts(context); + + // log some information about the request + info("handler.00", new Object[] { context.getTransactionID(), msgContext.getTargetService() }); + info("handler.01", new Object[] { request.getRemoteAddr() }); + if (clientCert != null) { + info("handler.02", new Object[] { clientCert[0].getSubjectDN(), clientCert[0].getSerialNumber(), + clientCert[0].getIssuerDN() }); + + } else { + info("handler.03", null); + } + if (Logger.isTraceEnabled()) { + // OutputFormat format = new OutputFormat((Document) + // xmlRequest.getOwnerDocument()); + // format.setLineSeparator("\n"); + // format.setIndenting(false); + // format.setPreserveSpace(true); + // format.setOmitXMLDeclaration(false); + // format.setEncoding("UTF-8"); + // ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // XMLSerializer conSerializer = new XMLSerializer(baos, + // format); + // conSerializer.serialize(xmlRequest); + // Logger.debug(new LogMsg("Request:" + baos.toString())); + + String msg = soapMessage.getSOAPPartAsString(); + Logger.trace(new LogMsg(msg)); + } + } catch (MOASystemException e) { + MOASystemException se = new MOASystemException("2900", null, e); + AxisFault fault = AxisFault.makeFault(se); + fault.setFaultDetail(new Element[] { se.toErrorResponse() }); + throw fault; + } catch (Throwable t) { + t.printStackTrace(); + Logger.info(new LogMsg(t.getStackTrace())); + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse() }); + throw fault; + } + Logger.trace("---- Leaving Axishandler"); + } + + /** + * This method is called by <code>invoke</code> to handle outgoing + * responses. + * + * @param msgContext + * The context as provided to <code>invoke</code>. + * @throws AxisFault + * An error occurred during processing of the response. + */ + private void handleResponse(MessageContext msgContext) throws AxisFault { + String xmlResponseString = null; + String soapResponseString = null; + + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + Element xmlResponse = context.getResponse(); + + if (xmlResponse != null) { + try { + xmlResponseString = DOMUtils.serializeNode(xmlResponse, true); + /* + * Soll die Antwort nur \n enthalten, so gibt es 2 + * Möglichkeiten: 1.) Xalan Version und xmlResponseString = + * DOMUtils.serializeNode(xmlResponse, true, "\n"); 2.) + * OutputFormat serializerFormat = new OutputFormat((Document) + * xmlResponse.getOwnerDocument()); + * serializerFormat.setLineSeparator("\n"); + * serializerFormat.setIndenting(false); + * serializerFormat.setPreserveSpace(true); + * serializerFormat.setOmitXMLDeclaration(true); + * serializerFormat.setEncoding("UTF-8"); ByteArrayOutputStream + * serializedBytes = new ByteArrayOutputStream(); XMLSerializer + * serializer = new XMLSerializer(serializedBytes, + * serializerFormat); serializer.serialize(xmlResponse); + * serializedBytes.close(); xmlResponseString = + * serializedBytes.toString("UTF-8"); + */ + if (Logger.isTraceEnabled()) { + Logger.trace(new LogMsg(xmlResponseString)); + } + soapResponseString = SOAP_PART_PRE + xmlResponseString + SOAP_PART_POST; + // override axis response-message + msgContext.setResponseMessage(new Message(soapResponseString)); + } catch (Throwable t) { + t.printStackTrace(); + Logger.info(new LogMsg(t.getStackTrace())); + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse() }); + throw fault; + } + + } else { + // Fallback: if functions do not set the resulting response in the + // transaction, the original one from axis will be used + soapResponseString = msgContext.getCurrentMessage().getSOAPPartAsString(); + } + + info("handler.04", null); + if (Logger.isDebugEnabled()) { + Logger.debug(new LogMsg(soapResponseString)); + } + tearDownContexts(); + } + + /** + * Called, when the processing of the web service fails. + * + * @param msgContext + * Information about the current request. + * @see org.apache.axis.Handler#onFault(org.apache.axis.MessageContext) + */ + public void onFault(MessageContext msgContext) { + info("handler.05", null); + tearDownContexts(); + } + + /** + * Set up the thread-local contexts (<code>TransactionContext</code> and + * <code>LoggingContext</code>). + * + * @param context + * The <code>TransactionContext</code> to set for the current + * request. + */ + private void setUpContexts(TransactionContext context) { + // set the transaction context in the TransactionContextManager + TransactionContextManager tcm = TransactionContextManager.getInstance(); + tcm.setTransactionContext(context); + + // set the logging context in the LoggingContextManager + LoggingContextManager lcm = LoggingContextManager.getInstance(); + LoggingContext lc = new LoggingContext(context.getTransactionID()); + lcm.setLoggingContext(lc); + } + + /** + * Tear down the thread-local contexts. + */ + private void tearDownContexts() { + TransactionContextManager tcm = TransactionContextManager.getInstance(); + + // delete temporary files + TransactionContext context = tcm.getTransactionContext(); + context.cleanAttachmentCache(); + + // unset the transaction context + tcm.setTransactionContext(null); + + // unset the logging context + LoggingContextManager lcm = LoggingContextManager.getInstance(); + lcm.setLoggingContext(null); + } + + /** + * Generate the WSDL into the <code>msgContext</code>. + * + * The code of this method is more or less copied from the + * <code>org.apache.axis.handlers.soap.SOAPService</code> class contained in + * the 1.1 release of Axis to allow for a missing <code>wsdlFile</code> (so + * that a resource by the same name is searched for in the classpath). The + * implementation of this method should be obsolete if Axis 1.1 or higher is + * used. + * + * @param msgContext + * The <code>MessageContext</code> that will contain the WSDL + * description of the current web service. + * @throws AxisFault + * An error occurred producing the WSDL. + */ + public void generateWSDL(MessageContext msgContext) throws AxisFault { + InputStream instream = null; + + try { + String filename = MOA_SPSS_WSDL_RESOURCE_; + + File file = new File(filename); + if (file.exists()) { + // if this resolves to a file, load it + instream = new FileInputStream(filename); + } else { + // else load a named resource in our classloader. + instream = this.getClass().getResourceAsStream(filename); + if (instream == null) { + String errorText = Messages.getMessage("wsdlFileMissing", filename); + throw new AxisFault(errorText); + } + } + Document doc = XMLUtils.newDocument(instream); + msgContext.setProperty("WSDL", doc); + } catch (Exception e) { + throw AxisFault.makeFault(e); + } finally { + if (instream != null) { + try { + instream.close(); + } catch (IOException e) { + // ok to do nothing here + } + } + } + } + + /** + * Utility function to issue an info message to the log. + * + * @param messageId + * The ID of the message to log. + * @param parameters + * Additional message parameters. + */ + private static void info(String messageId, Object[] parameters) { + MessageProvider msg = MessageProvider.getInstance(); + + Logger.info(new LogMsg(msg.getMessage(messageId, parameters))); + } + + /** + * Utility function to issue an debug message to the log. + * + * @param messageId + * The ID of the message to log. + * @param parameters + * Additional message parameters. + */ + private static void debug(String messageId, Object[] parameters) { + MessageProvider msg = MessageProvider.getInstance(); + + Logger.debug(new LogMsg(msg.getMessage(messageId, parameters))); + } + + // private byte[] toByteArray(AttachmentPart attachment) throws + // SOAPException, IOException + // { + // ByteArrayOutputStream outputStream = new + // ByteArrayOutputStream(attachment.getSize()); + // InputStream inputStream = (InputStream) attachment.getContent(); + // int currentByte = -1; + // while ((currentByte = inputStream.read()) != -1) + // outputStream.write(currentByte); + // + // inputStream.close(); + // outputStream.close(); + // + // return outputStream.toByteArray(); + // + // } + +}
\ No newline at end of file diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java new file mode 100644 index 0000000..c8a0f68 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java @@ -0,0 +1,178 @@ +package at.gv.egovernment.moa.spss.server.service; + +import iaik.server.modules.keys.KeyEntryID; +import iaik.server.modules.keys.KeyModule; +import iaik.server.modules.keys.KeyModuleFactory; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.server.config.ConfigurationException; +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.logging.TransactionId; +import at.gv.egovernment.moa.spss.server.transaction.TransactionIDGenerator; + +/** + * + * @author Andreas Fitzek + * @version $Id$ + */ +public class CertificateProviderServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = -6907582473072190122L; + + /** The property name for accessing the X509 client certificate chain. */ + private static final String X509_CERTIFICATE_PROPERTY = "javax.servlet.request.X509Certificate"; + + public static final String PARAM_KEYID = "id"; + + /** + * Build the set of <code>KeyEntryID</code>s available to the given + * <code>keyGroupID</code>. + * + * @param keyGroupID + * The keygroup ID for which the available keys should be + * returned. + * @return The <code>Set</code> of <code>KeyEntryID</code>s identifying the + * available keys. + * @throws ConfigurationException + */ + private Set buildKeySet(String keyGroupID, X509Certificate cert, KeyModule module) + throws ConfigurationException { + ConfigurationProvider config = ConfigurationProvider.getInstance(); + Set keyGroupEntries; + + // get the KeyGroup entries from the configuration + if (cert != null) { + 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 { + + 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; + } + } + + private X509Certificate getClientCertificate(HttpServletRequest request) { + X509Certificate[] clientCert = (X509Certificate[]) request + .getAttribute(X509_CERTIFICATE_PROPERTY); + if(clientCert != null) { + return clientCert[0]; + } + return null; + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + try { + X509Certificate cert = getClientCertificate(request); + String keyId = request.getParameter(PARAM_KEYID); + + if(keyId == null) { + Logger.warn(PARAM_KEYID + " not provided in Request. Returning: " + HttpServletResponse.SC_BAD_REQUEST); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + String transactionId = TransactionIDGenerator.nextID(); + + KeyModule module = KeyModuleFactory.getInstance(new TransactionId( + transactionId)); + + Set keySet = buildKeySet(keyId, cert, module); + + if(keySet == null || keySet.isEmpty()) { + Logger.warn("No keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + + if(keySet.size() != 1) { + Logger.warn("Too many keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_CONFLICT); + return; + } + + 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 = keySet.iterator(); iter.hasNext();) { + KeyEntryID entryID = (KeyEntryID) iter.next(); + + List certChain = module.getPrivateKeyEntry(entryID).getCertificateChain(); + + if(certChain != null && !certChain.isEmpty()) { + Logger.trace("Returning Certificate!"); + Certificate keyCert = ((Certificate)certChain.get(0)); + byte[] certData = keyCert.getEncoded(); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/pkix-cert"); + response.setHeader("Content-disposition","attachment; filename=\"" + keyId + ".cer\""); + response.getOutputStream().write(certData); + response.getOutputStream().close(); + return; + } + + break; + } + + // No Certificate could be found! + Logger.warn("Failed to find keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } catch(Throwable e) { + Logger.error("Unhandled Exception when providing certificate", e); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/ConfigurationServlet.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/ConfigurationServlet.java new file mode 100644 index 0000000..8bdfb65 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/ConfigurationServlet.java @@ -0,0 +1,148 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.server.service; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.logging.LogMsg; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.logging.LoggingContext; +import at.gv.egovernment.moa.logging.LoggingContextManager; + +import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; +import at.gv.egovernment.moa.spss.server.iaik.config.IaikConfigurator; +import at.gv.egovernment.moa.spss.server.init.*; +import at.gv.egovernment.moa.spss.util.MessageProvider; + +/** + * A servlet to initialize and update the MOA configuration. + * + * @author Fatemeh Philippi + * @author Patrick Peck + * @version $Id$ + */ +public class ConfigurationServlet extends HttpServlet { + /** + * + */ + private static final long serialVersionUID = 8372961105222028696L; +/** The document type of the HTML to generate. */ + private static final String DOC_TYPE = + "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"; + + /** + * Handle a HTTP GET request, used to indicated that the MOA + * configuration needs to be updated (reloaded). + * + * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse) + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + MessageProvider msg = MessageProvider.getInstance(); + PrintWriter out; + + // set up a logging context for logging the reconfiguration + LoggingContextManager.getInstance().setLoggingContext( + new LoggingContext("configuration update")); + + response.setContentType("text/html"); + out = response.getWriter(); + out.println(DOC_TYPE); + out.println("<head><title>MOA configuration update</title></head>"); + out.println("<body bgcolor=\"#FFFFFF\">"); + try { + // reconfigure the system + ConfigurationProvider config = ConfigurationProvider.reload(); + IaikConfigurator iaikConfigurator = new IaikConfigurator(); + + iaikConfigurator.configure(config); + + // print a status message + out.println("<p><b>" + msg.getMessage("config.06", null) + "</b></p>"); + Logger.info(new LogMsg(msg.getMessage("config.06", null))); + + if (!config.getWarnings().isEmpty()) { + // print the warnings + List allWarnings = new ArrayList(); + Iterator iter; + + allWarnings.addAll(config.getWarnings()); + allWarnings.addAll(iaikConfigurator.getWarnings()); + + out.println("<p><b>" + msg.getMessage("config.29", null) + "</b></p>"); + for (iter = allWarnings.iterator(); iter.hasNext();) { + out.println(iter.next() + "<br />"); + } + out.println("<p><b>" + msg.getMessage("config.28", null) + "</b></p>"); + } + + } catch (Throwable t) { + out.println("<p><b>" + msg.getMessage("config.20", null) + "</b></p>"); + out.println("<p><b>" + msg.getMessage("config.28", null) + "</b></p>"); + Logger.warn(new LogMsg(msg.getMessage("config.20", null)), t); + } + out.println("</body>"); + + out.flush(); + out.close(); + + // tear down the logging context + LoggingContextManager.getInstance().setLoggingContext(null); + } + + /** + * Do the same as <code>doGet</code>. + * + * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest, HttpServletResponse) + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + doGet(request, response); + } + + /** + * Perform some initial initialization tasks for the MOA web services + * application. + * + * Does an initial load of the MOA configuration to test if a working web + * service can be provided. + * + * @see javax.servlet.GenericServlet#init() + */ + public void init() throws ServletException { + SystemInitializer.init(); + } + +}
\ No newline at end of file diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/DeleteableDataSourceWrapper.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/DeleteableDataSourceWrapper.java new file mode 100644 index 0000000..1d49cd7 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/DeleteableDataSourceWrapper.java @@ -0,0 +1,43 @@ +package at.gv.egovernment.moa.spss.server.service; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import at.gv.egovernment.moa.spss.server.transaction.DeleteableDataSource; + +public class DeleteableDataSourceWrapper implements DeleteableDataSource { + + private org.apache.axis.attachments.ManagedMemoryDataSource wrapped; + + public DeleteableDataSourceWrapper(org.apache.axis.attachments.ManagedMemoryDataSource wrapped) { + this.wrapped = wrapped; + } + + @Override + public String getContentType() { + return this.wrapped.getContentType(); + } + + @Override + public InputStream getInputStream() throws IOException { + return this.wrapped.getInputStream(); + } + + @Override + public String getName() { + return this.wrapped.getName(); + } + + @Override + public OutputStream getOutputStream() throws IOException { + return this.wrapped.getOutputStream(); + } + + @Override + public void delete() { + this.wrapped.delete(); + } + + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/ServiceUtils.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/ServiceUtils.java new file mode 100644 index 0000000..d986f7a --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/ServiceUtils.java @@ -0,0 +1,104 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.server.service; + +import java.io.ByteArrayInputStream; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.util.MOASPSSEntityResolver; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.MOAErrorHandler; + +/** + * Helper methods for the Service classes. + * + * @author Patrick Peck + * @version $Id$ + */ +public class ServiceUtils { + + /** + * Schema-validate a request. + * + * @param request The request to validate. + * @throws MOAApplicationException An error occurred validating the requst. + */ + public static void validateRequest(Element[] request) + throws MOAApplicationException { + + // validate the request + try { + DOMUtils.validateElement( + request[0], + Constants.ALL_SCHEMA_LOCATIONS, + null, + new MOASPSSEntityResolver()); + } catch (Exception e) { + throw new MOAApplicationException( + "1100", + new Object[] { e.getMessage()}, + e); + } + } + + /** + * Reparse the request with schema-validation turned on so that ID references + * are resolved. + * + * @param request The request to reparse. + * @return The reparsed request. + * @throws MOAApplicationException An error occurred parsing the request. + */ + public static Element reparseRequest(Element request) + throws MOAApplicationException { + + try { + byte[] requestBytes = DOMUtils.serializeNode(request, "UTF-8"); + Document validatedRequest = DOMUtils.parseDocument(new ByteArrayInputStream(requestBytes), + true, + Constants.ALL_SCHEMA_LOCATIONS, + null, + new MOASPSSEntityResolver(), + new MOAErrorHandler()); + +// DOMUtils.parseDocument( +// new ByteArrayInputStream(requestBytes), +// true, +// Constants.ALL_SCHEMA_LOCATIONS, +// null); + return validatedRequest.getDocumentElement(); + } catch (Exception e) { + throw new MOAApplicationException( + "1100", + new Object[] { e.getMessage()}, + e); + } + } + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/SignatureCreationService.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/SignatureCreationService.java new file mode 100644 index 0000000..0c800a2 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/SignatureCreationService.java @@ -0,0 +1,314 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.server.service; + +import java.util.Collections; + +import javax.xml.namespace.QName; + +import org.apache.axis.AxisFault; +import org.apache.axis.i18n.Messages; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.cmssign.CreateCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmssign.CreateCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.xmlbind.CreateCMSSignatureRequestParser; +import at.gv.egovernment.moa.spss.api.xmlbind.CreateCMSSignatureResponseBuilder; +import at.gv.egovernment.moa.spss.api.xmlbind.CreateXMLSignatureRequestParser; +import at.gv.egovernment.moa.spss.api.xmlbind.CreateXMLSignatureResponseBuilder; +import at.gv.egovernment.moa.spss.api.xmlsign.CreateXMLSignatureRequest; +import at.gv.egovernment.moa.spss.api.xmlsign.CreateXMLSignatureResponse; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureCreationInvoker; +import at.gv.egovernment.moa.spss.server.invoke.PDFASInvoker; +import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureCreationInvoker; +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.xmlbind.CreatePDFRequest; +import at.gv.egovernment.moa.spss.server.xmlbind.CreatePDFRespone; +import at.gv.egovernment.moa.spss.server.xmlbind.CreatePDFSignatureRequestParser; +import at.gv.egovernment.moa.spss.server.xmlbind.CreatePDFSignatureResponseBuilder; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.StreamUtils; + +/** + * The service endpoint for the <code>SignatureCreation</code> web service. + * + * @author Patrick Peck + * @version $Id$ + */ +public class SignatureCreationService { + + /** + * Handle a <code>CreatePDFSignatureRequest</code>. + * + * @param request The <code>CreatePDFSignatureRequest</code> to work on + * (contained in the 0th element of the array). + * @return A <code>CreatePDFSignatureResponse</code> as the only element of + * the <code>Element</code> array. + * @throws AxisFault An error occurred during handling of the message. + */ + public Element[] CreatePDFSignatureRequest(Element[] request) + throws AxisFault { + Logger.trace("---- Entering SignatureCreationService"); + //PDFSignatureCreationInvoker invoker = + // PDFSignatureCreationInvoker.getInstance(); + Element[] response = new Element[1]; + + // check that we have a CreateXMLSignatureRequest; if not, create an + // AxisFault, just like the org.apache.axis.providers.java.MsgProvider + if (!Constants.MOA_SPSS_CREATE_PDF_REQUEST.equals(request[0].getLocalName()) || + !Constants.MOA_NS_URI.equals(request[0].getNamespaceURI())) + { + QName qname = + new QName(request[0].getNamespaceURI(), request[0].getLocalName()); + throw new AxisFault( + Messages.getMessage("noOperationForQName", qname.toString())); // TODO GK Operation name does not make it into the error repsonse + } + + // handle the request + try { + + // create a parser and builder for binding API objects to/from XML + CreatePDFSignatureRequestParser requestParser = + new CreatePDFSignatureRequestParser(); + CreatePDFSignatureResponseBuilder responseBuilder = + new CreatePDFSignatureResponseBuilder(); + Element reparsedReq; + CreatePDFRequest requestObj; + CreatePDFRespone responseObj; + + //since Axis (1.1 ff) has problem with namespaces we take the raw request stored by the Axishandler. + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + + // validate the request + reparsedReq = ServiceUtils.reparseRequest(request[0]);//context.getRequest()); + + // convert to API objects + Logger.trace(">>> preparsing Request"); + requestObj = requestParser.parse(reparsedReq); + Logger.trace("<<< preparsed Request"); + + Logger.trace(">>> creating Signature"); + // invoke the core logic + responseObj = PDFASInvoker.getInstance().createPDFSignature(requestObj, context.getTransactionID()); + Logger.trace("<<< created Signature"); + + Logger.trace(">>> building Response"); + // map back to XML + response[0] = responseBuilder.build(responseObj).getDocumentElement(); + Logger.trace("<<< built Response"); + + // save response in transaction + context.setResponse(response[0]); + Logger.trace("---- Leaving SignatureCreationService"); + + + } catch (MOAException e) { + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } catch (Throwable t) { + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } + + return response; + } + + /** + * Handle a <code>CreateXMLSignatureRequest</code>. + * + * @param request The <code>CreateXMLSignatureRequest</code> to work on + * (contained in the 0th element of the array). + * @return A <code>CreateXMLSignatureResponse</code> as the only element of + * the <code>Element</code> array. + * @throws AxisFault An error occurred during handling of the message. + */ + public Element[] CreateCMSSignatureRequest(Element[] request) + throws AxisFault { + Logger.trace("---- Entering SignatureCreationService"); + CMSSignatureCreationInvoker invoker = + CMSSignatureCreationInvoker.getInstance(); + Element[] response = new Element[1]; + + // check that we have a CreateXMLSignatureRequest; if not, create an + // AxisFault, just like the org.apache.axis.providers.java.MsgProvider + if (!Constants.MOA_SPSS_CREATE_CMS_REQUEST.equals(request[0].getLocalName()) || + !Constants.MOA_NS_URI.equals(request[0].getNamespaceURI())) + { + QName qname = + new QName(request[0].getNamespaceURI(), request[0].getLocalName()); + throw new AxisFault( + Messages.getMessage("noOperationForQName", qname.toString())); // TODO GK Operation name does not make it into the error repsonse + } + + // handle the request + try { + + // create a parser and builder for binding API objects to/from XML + CreateCMSSignatureRequestParser requestParser = + new CreateCMSSignatureRequestParser(); + CreateCMSSignatureResponseBuilder responseBuilder = + new CreateCMSSignatureResponseBuilder(); + Element reparsedReq; + CreateCMSSignatureRequest requestObj; + CreateCMSSignatureResponse responseObj; + + //since Axis (1.1 ff) has problem with namespaces we take the raw request stored by the Axishandler. + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + + // validate the request + reparsedReq = ServiceUtils.reparseRequest(request[0]);//context.getRequest()); + + // convert to API objects + Logger.trace(">>> preparsing Request"); + requestObj = requestParser.parse(reparsedReq); + Logger.trace("<<< preparsed Request"); + + Logger.trace(">>> creating Signature"); + // invoke the core logic + responseObj = invoker.createCMSSignature(requestObj, Collections.EMPTY_SET); + Logger.trace("<<< created Signature"); + + Logger.trace(">>> building Response"); + // map back to XML + response[0] = responseBuilder.build(responseObj).getDocumentElement(); + Logger.trace("<<< built Response"); + + // save response in transaction + context.setResponse(response[0]); + Logger.trace("---- Leaving SignatureCreationService"); + + + } catch (MOAException e) { + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } catch (Throwable t) { + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } + + return response; + } + + /** + * Handle a <code>CreateXMLSignatureRequest</code>. + * + * @param request The <code>CreateXMLSignatureRequest</code> to work on + * (contained in the 0th element of the array). + * @return A <code>CreateXMLSignatureResponse</code> as the only element of + * the <code>Element</code> array. + * @throws AxisFault An error occurred during handling of the message. + */ + public Element[] CreateXMLSignatureRequest(Element[] request) + throws AxisFault { + Logger.trace("---- Entering SignatureCreationService"); + XMLSignatureCreationInvoker invoker = + XMLSignatureCreationInvoker.getInstance(); + Element[] response = new Element[1]; + + // check that we have a CreateXMLSignatureRequest; if not, create an + // AxisFault, just like the org.apache.axis.providers.java.MsgProvider + if (!Constants.MOA_SPSS_CREATE_XML_REQUEST.equals(request[0].getLocalName()) || + !Constants.MOA_NS_URI.equals(request[0].getNamespaceURI())) + { + QName qname = + new QName(request[0].getNamespaceURI(), request[0].getLocalName()); + throw new AxisFault( + Messages.getMessage("noOperationForQName", qname.toString())); // TODO GK Operation name does not make it into the error repsonse + } + + // handle the request + try { + + // create a parser and builder for binding API objects to/from XML + CreateXMLSignatureRequestParser requestParser = + new CreateXMLSignatureRequestParser(); + CreateXMLSignatureResponseBuilder responseBuilder = + new CreateXMLSignatureResponseBuilder(); + Element reparsedReq; + CreateXMLSignatureRequest requestObj; + CreateXMLSignatureResponse responseObj; + + //since Axis (1.1 ff) has problem with namespaces we take the raw request stored by the Axishandler. + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + + // validate the request + reparsedReq = ServiceUtils.reparseRequest(request[0]);//context.getRequest()); + + // convert to API objects + Logger.trace(">>> preparsing Request"); + requestObj = requestParser.parse(reparsedReq); + Logger.trace("<<< preparsed Request"); + + Logger.trace(">>> creating Signature"); + // invoke the core logic + responseObj = invoker.createXMLSignature(requestObj, Collections.EMPTY_SET); + Logger.trace("<<< created Signature"); + + Logger.trace(">>> building Response"); + // map back to XML + response[0] = responseBuilder.build(responseObj).getDocumentElement(); + Logger.trace("<<< built Response"); + + // save response in transaction + context.setResponse(response[0]); + Logger.trace("---- Leaving SignatureCreationService"); + + + } catch (MOAException e) { + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } catch (Throwable t) { + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturerstellung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } + + return response; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/SignatureVerificationService.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/SignatureVerificationService.java new file mode 100644 index 0000000..40b287d --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/service/SignatureVerificationService.java @@ -0,0 +1,241 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.server.service; + +import org.apache.axis.AxisFault; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.xmlbind.VerifyCMSSignatureRequestParser; +import at.gv.egovernment.moa.spss.api.xmlbind.VerifyCMSSignatureResponseBuilder; +import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureRequestParser; +import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureResponseBuilder; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; +import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker; +import at.gv.egovernment.moa.spss.server.transaction.TransactionContext; +import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager; +import at.gv.egovernment.moa.util.StreamUtils; + +/** + * The service endpoint for the <code>SignatureVerification</code> web service. + * + * @author Patrick Peck + * @version $Id$ + */ +public class SignatureVerificationService { + + /** + * Handle a <code>VerifyPDFSignatureRequest</code>. + * + * @param request The <code>VerifyPDFSignatureRequest</code> to work on + * (contained in the 0th element of the array). + * @return A <code>VerifyPDFSignatureResponse</code> as the only element of + * the <code>Element</code> array. + * @throws AxisFault An error occurred during handling of the message. + */ + public Element[] VerifyPDFSignatureRequest(Element[] request) + throws AxisFault { + CMSSignatureVerificationInvoker invoker = + CMSSignatureVerificationInvoker.getInstance(); + Element[] response = new Element[1]; + + try { + + // create a parser and builder for binding API objects to/from XML + VerifyCMSSignatureRequestParser requestParser = + new VerifyCMSSignatureRequestParser(); + VerifyCMSSignatureResponseBuilder responseBuilder = + new VerifyCMSSignatureResponseBuilder(); + Element reparsedReq; + VerifyCMSSignatureRequest requestObj; + VerifyCMSSignatureResponse responseObj; + + //since Axis (1.1 ff) has problem with namespaces we take the raw request stored by the Axishandler. + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + // validate the request + reparsedReq = ServiceUtils.reparseRequest(request[0]);//context.getRequest()); + + // convert to API objects + requestObj = requestParser.parse(reparsedReq); + + // invoke the core logic + responseObj = invoker.verifyCMSSignature(requestObj); + + // map back to XML + response[0] = responseBuilder.build(responseObj).getDocumentElement(); + + // save response in transaction + context.setResponse(response[0]); + + + } catch (MOAException e) { + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } catch (Throwable t) { + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } + + return response; + } + + /** + * Handle a <code>VerifyCMSSignatureRequest</code>. + * + * @param request The <code>VerifyCMSSignatureRequest</code> to work on + * (contained in the 0th element of the array). + * @return A <code>VerifyCMSSignatureResponse</code> as the only element of + * the <code>Element</code> array. + * @throws AxisFault An error occurred during handling of the message. + */ + public Element[] VerifyCMSSignatureRequest(Element[] request) + throws AxisFault { + CMSSignatureVerificationInvoker invoker = + CMSSignatureVerificationInvoker.getInstance(); + Element[] response = new Element[1]; + + try { + + // create a parser and builder for binding API objects to/from XML + VerifyCMSSignatureRequestParser requestParser = + new VerifyCMSSignatureRequestParser(); + VerifyCMSSignatureResponseBuilder responseBuilder = + new VerifyCMSSignatureResponseBuilder(); + Element reparsedReq; + VerifyCMSSignatureRequest requestObj; + VerifyCMSSignatureResponse responseObj; + + //since Axis (1.1 ff) has problem with namespaces we take the raw request stored by the Axishandler. + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + // validate the request + reparsedReq = ServiceUtils.reparseRequest(request[0]);//context.getRequest()); + + // convert to API objects + requestObj = requestParser.parse(reparsedReq); + + // invoke the core logic + responseObj = invoker.verifyCMSSignature(requestObj); + + // map back to XML + response[0] = responseBuilder.build(responseObj).getDocumentElement(); + + // save response in transaction + context.setResponse(response[0]); + + + } catch (MOAException e) { + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } catch (Throwable t) { + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } + + return response; + } + + /** + * Handle a <code>VerifyXMLSignatureRequest</code>. + * + * @param request The <code>VerifyXMLSignatureRequest</code> to work on + * (contained in the 0th element of the array). + * @return A <code>VerifyXMLSignatureResponse</code> as the only element of + * the <code>Element</code> array. + * @throws AxisFault An error occurred during handling of the message. + */ + public Element[] VerifyXMLSignatureRequest(Element[] request) + throws AxisFault { + XMLSignatureVerificationInvoker invoker = + XMLSignatureVerificationInvoker.getInstance(); + Element[] response = new Element[1]; + + try { + + // create a parser and builder for binding API objects to/from XML + VerifyXMLSignatureRequestParser requestParser = + new VerifyXMLSignatureRequestParser(); + VerifyXMLSignatureResponseBuilder responseBuilder = + new VerifyXMLSignatureResponseBuilder(); + Element reparsedReq; + VerifyXMLSignatureRequest requestObj; + VerifyXMLSignatureResponse responseObj; + + //since Axis (1.1 ff) has problem with namespaces we take the raw request stored by the Axishandler. + TransactionContext context = TransactionContextManager.getInstance().getTransactionContext(); + // validate the request + reparsedReq = ServiceUtils.reparseRequest(context.getRequest()); + + // convert to API objects + requestObj = requestParser.parse(reparsedReq); + + // invoke the core logic + responseObj = invoker.verifyXMLSignature(requestObj); + + // map back to XML + response[0] = responseBuilder.build(responseObj).getDocumentElement(); + + // save response in transaction + context.setResponse(response[0]); + + + } catch (MOAException e) { + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } catch (Throwable t) { + MOASystemException e = new MOASystemException("2900", null, t); + AxisFault fault = AxisFault.makeFault(e); + fault.setFaultDetail(new Element[] { e.toErrorResponse()}); + Logger.debug("Anfrage zur Signaturpruefung wurde nicht erfolgreich beendet:" + + System.getProperty("line.separator") + StreamUtils.getStackTraceAsString(e)); + throw fault; + } + + return response; + } + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFRequest.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFRequest.java new file mode 100644 index 0000000..110665c --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFRequest.java @@ -0,0 +1,21 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.util.ArrayList; +import java.util.List; + +public class CreatePDFRequest { + private String keyIdentifier; + private List<PDFSignatureInfo> signatureInfoList = new ArrayList<PDFSignatureInfo>(); + + public CreatePDFRequest(String keyIdentifier) { + this.keyIdentifier = keyIdentifier; + } + + public synchronized String getKeyIdentifier() { + return keyIdentifier; + } + + public synchronized List<PDFSignatureInfo> getSignatureInfoList() { + return signatureInfoList; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFRespone.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFRespone.java new file mode 100644 index 0000000..ef7e832 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFRespone.java @@ -0,0 +1,15 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.util.ArrayList; +import java.util.List; + +public class CreatePDFRespone { + private List<SignedPDFInfo> signatureInfoList = new ArrayList<SignedPDFInfo>(); + + public CreatePDFRespone() { + } + + public synchronized List<SignedPDFInfo> getSignatureInfoList() { + return signatureInfoList; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFSignatureRequestParser.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFSignatureRequestParser.java new file mode 100644 index 0000000..163a7ba --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFSignatureRequestParser.java @@ -0,0 +1,142 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.io.IOException; + +import org.w3c.dom.Element; +import org.w3c.dom.traversal.NodeIterator; + +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; + +/** + * A parser to parse <code>CreateCMSSignatureRequest</code> DOM trees into + * <code>CreateCMSSignatureRequest</code> API objects. + * + * @author Patrick Peck + * @version $Id$ + */ +public class CreatePDFSignatureRequestParser { + + // + // XPath expresssions to select elements in the CreateCMSSignatureRequest + // + private static final String MOA = Constants.MOA_PREFIX + ":"; + private static final String KEY_IDENTIFIER_XPATH = "/" + MOA + "CreatePDFSignatureRequest/" + MOA + "KeyIdentifier"; + private static final String SINGLE_SIGNATURE_INFO_XPATH = "/" + MOA + "CreatePDFSignatureRequest/" + MOA + + "SingleSignatureInfo"; + private static final String SIGNATURE_PROFILE_XPATH = MOA + "SignatureProfile"; + private static final String SIGNATURE_POSITION_XPATH = MOA + "SignaturePosition"; + private static final String SIGNATURE_ID_XPATH = MOA + "SignatureID"; + + private static final String PDF_DOCUMENT_XPATH = MOA + "PDFDocument"; + + /** + * Create a new <code>CreateCMSSignatureRequestParser</code>. + */ + public CreatePDFSignatureRequestParser() { + } + + /** + * Parse a <code>CreateCMSSignatureRequest</code> DOM element, as defined by + * the MOA schema. + * + * @param requestElem + * The <code>CreateCMSSignatureRequest</code> to parse. The + * request must have been successfully parsed against the schema + * for this method to succeed. + * @return A <code>CreateCMSSignatureRequest</code> API object containing + * the data from the DOM element. + * @throws MOAApplicationException + * An error occurred parsing the request. + */ + public CreatePDFRequest parse(Element requestElem) throws MOAApplicationException { + + String keyIdentifier = XPathUtils.getElementValue(requestElem, KEY_IDENTIFIER_XPATH, null); + + CreatePDFRequest createPDFRequest = new CreatePDFRequest(keyIdentifier); + parseSingleSignatureInfos(requestElem, createPDFRequest); + + return createPDFRequest; + } + + /** + * Parse all <code>SingleSignatureInfo</code> elements of the + * <code>CreateCMSSignatureRequest</code>. + * + * @param requestElem + * The <code>CreateCMSSignatureRequest</code> to parse. + * @return A <code>List</code> of <code>SingleSignatureInfo</code> API + * objects. + * @throws MOAApplicationException + * An error occurred parsing on of the + * <code>SingleSignatureInfo</code> elements. + */ + private void parseSingleSignatureInfos(Element requestElem, CreatePDFRequest createPDFRequest) + throws MOAApplicationException { + + NodeIterator sigInfoElems = XPathUtils.selectNodeIterator(requestElem, SINGLE_SIGNATURE_INFO_XPATH); + Element sigInfoElem; + + while ((sigInfoElem = (Element) sigInfoElems.nextNode()) != null) { + createPDFRequest.getSignatureInfoList().add(parsePDFSignatureInfo(sigInfoElem)); + } + } + + /** + * Parse a <code>SingleSignatureInfo</code> DOM element. + * + * @param sigInfoElem + * The <code>SingleSignatureInfo</code> DOM element to parse. + * @return A <code>SingleSignatureInfo</code> API object containing the + * information of <code>sigInfoElem</code>. + * @throws MOAApplicationException + * An error occurred parsing the + * <code>SingleSignatureInfo</code>. + */ + private PDFSignatureInfo parsePDFSignatureInfo(Element sigInfoElem) throws MOAApplicationException { + + String signatureProfile = XPathUtils.getElementValue(sigInfoElem, SIGNATURE_PROFILE_XPATH, null); + String signaturePosition = XPathUtils.getElementValue(sigInfoElem, SIGNATURE_POSITION_XPATH, null); + String signatureID = XPathUtils.getElementValue(sigInfoElem, SIGNATURE_ID_XPATH, null); + + + Element base64ContentElem = (Element) XPathUtils.selectSingleNode(sigInfoElem, PDF_DOCUMENT_XPATH); + String base64Str = DOMUtils.getText(base64ContentElem); + try { + byte[] inputPDF = Base64Utils.decode(base64Str, true); + PDFSignatureInfo PDFSignatureInfo = new PDFSignatureInfo(inputPDF, + signatureProfile, signaturePosition, signatureID); + + return PDFSignatureInfo; + } catch (IOException e) { + throw new MOAApplicationException("2244", null, e); + } + + } +}
\ No newline at end of file diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFSignatureResponseBuilder.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFSignatureResponseBuilder.java new file mode 100644 index 0000000..78586ba --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/CreatePDFSignatureResponseBuilder.java @@ -0,0 +1,155 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.io.IOException; +import java.util.Iterator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.xmlbind.ResponseBuilderUtils; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.Constants; + +/** + * Convert a <code>CreateCMSSignatureResponse</code> API object into its XML + * representation, according to the MOA XML schema. + * + * @version $Id$ + */ +public class CreatePDFSignatureResponseBuilder { + private static final String MOA_NS_URI = Constants.MOA_NS_URI; + + private static final Logger logger = LoggerFactory.getLogger(CreatePDFSignatureResponseBuilder.class); + + /** The XML document containing the response element. */ + private Document responseDoc; + /** The response <code>CreateCMSSignatureResponse</code> DOM element. */ + private Element responseElem; + + /** + * Create a new <code>CreateCMSSignatureResponseBuilder</code>: + * + * @throws MOASystemException + * An error occurred setting up the resulting XML document. + */ + public CreatePDFSignatureResponseBuilder() throws MOASystemException { + responseDoc = ResponseBuilderUtils.createResponse("CreatePDFSignatureResponse"); + responseElem = responseDoc.getDocumentElement(); + } + + /** + * Build a document containing a <code>CreateCMSSignatureResponse</code> DOM + * element being the XML representation of the given + * <code>CreateCMSSignatureResponse</code> API object. + * + * @param response + * The <code>CreateCMSSignatureResponse</code> to convert to XML. + * @return A document containing the <code>CreateCMSSignatureResponse</code> + * DOM element. + */ + public Document build(CreatePDFRespone response) { + Iterator<SignedPDFInfo> iter = response.getSignatureInfoList().iterator(); + + while (iter.hasNext()) { + SignedPDFInfo signedPDFInfo = iter.next(); + addPDFSignature(signedPDFInfo); + } + + return responseDoc; + } + + /** + * Add a <code>CMSSignature</code> element to the response. + * + * @param cmsSignatureResponse + * The content to put under the <code>CMSSignature</code> + * element. + */ + private void addPDFSignature(SignedPDFInfo signedPDFInfo) { + Element pdfSignature = responseDoc.createElementNS(MOA_NS_URI, "PDFSignature"); + + if(signedPDFInfo.getSignatureID() != null) { + Element signatureID = responseDoc.createElementNS(MOA_NS_URI, "SignatureID"); + signatureID.setTextContent(signedPDFInfo.getSignatureID()); + pdfSignature.appendChild(signatureID); + } + + switch (signedPDFInfo.getResponseType()) { + case SignedPDFInfo.SUCCESS_SIGNATURE: + pdfSignature.appendChild(addSuccessSignature(signedPDFInfo)); + break; + + default: + pdfSignature.appendChild(addErrorResponse(signedPDFInfo)); + break; + } + + responseElem.appendChild(pdfSignature); + } + + private Element addSuccessSignature(SignedPDFInfo signedPDFInfo) { + try { + String base64Value = Base64Utils.encode(signedPDFInfo.getPdfDocument()); + Element cmsSignature = responseDoc.createElementNS(MOA_NS_URI, "PDFSignature"); + cmsSignature.setTextContent(base64Value); + + return cmsSignature; + } catch (IOException e) { + logger.error("Failed to encode pdf signature", e); + signedPDFInfo.setErrorCode(2300); + signedPDFInfo.setErrorInfo("Failed to encode the signed document"); + return addErrorResponse(signedPDFInfo); + } + + + } + + /** + * Add a <code>ErrorResponse</code> element to the response. + * + * @param errorResponse + * The API object containing the information to put into the + * <code>ErrorResponse</code> DOM element. + */ + private Element addErrorResponse(SignedPDFInfo signedPDFInfo) { + Element errorElem = responseDoc.createElementNS(MOA_NS_URI, "ErrorResponse"); + Element errorCodeElem = responseDoc.createElementNS(MOA_NS_URI, "ErrorCode"); + Element infoElem = responseDoc.createElementNS(MOA_NS_URI, "Info"); + String errorCodeStr = Integer.toString(signedPDFInfo.getErrorCode()); + + errorCodeElem.appendChild(responseDoc.createTextNode(errorCodeStr)); + errorElem.appendChild(errorCodeElem); + infoElem.appendChild(responseDoc.createTextNode(signedPDFInfo.getErrorInfo())); + errorElem.appendChild(errorCodeElem); + errorElem.appendChild(infoElem); + + return errorElem; + } + +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/PDFSignatureInfo.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/PDFSignatureInfo.java new file mode 100644 index 0000000..fd2be7c --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/PDFSignatureInfo.java @@ -0,0 +1,33 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +public class PDFSignatureInfo { + private String signatureProfile = null; + private String signaturePosition = null; + private String signatureID = null; + private byte[] pdfDocument = null; + + public PDFSignatureInfo(byte[] pdfDocument, + String signatureProfile, String signaturePosition, + String signatureID) { + this.pdfDocument = pdfDocument; + this.signatureProfile = signatureProfile; + this.signaturePosition = signaturePosition; + this.signatureID = signatureID; + } + + public synchronized String getSignatureProfile() { + return signatureProfile; + } + + public synchronized String getSignaturePosition() { + return signaturePosition; + } + + public synchronized String getSignatureID() { + return signatureID; + } + + public synchronized byte[] getPdfDocument() { + return pdfDocument; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/SignedPDFInfo.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/SignedPDFInfo.java new file mode 100644 index 0000000..a950006 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/SignedPDFInfo.java @@ -0,0 +1,53 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +public class SignedPDFInfo { + + public static final int SUCCESS_SIGNATURE = 0; + public static final int ERROR_RESPONSE = 1; + + private String signatureID = null; + private byte[] pdfDocument = null; + private int responseType = ERROR_RESPONSE; + private int errorCode = 0; + private String errorInfo = null; + + public SignedPDFInfo(String signatureID) { + this.signatureID = signatureID; + } + + public synchronized void setPdfDocument(byte[] pdfDocument) { + this.pdfDocument = pdfDocument; + } + + public synchronized String getSignatureID() { + return signatureID; + } + + public synchronized byte[] getPdfDocument() { + return pdfDocument; + } + + public synchronized void setResponseType(int responseType) { + this.responseType = responseType; + } + + public int getResponseType() { + return this.responseType; + } + + public synchronized int getErrorCode() { + return errorCode; + } + + public synchronized void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public synchronized String getErrorInfo() { + return errorInfo; + } + + public synchronized void setErrorInfo(String errorInfo) { + this.errorInfo = errorInfo; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFRequest.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFRequest.java new file mode 100644 index 0000000..c9ca89d --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFRequest.java @@ -0,0 +1,36 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.util.Date; + +public class VerifyPDFRequest { + private Date dateTime; + private byte[] signedPDF; + private String trustProfileID; + + public VerifyPDFRequest() { + } + + public synchronized Date getDateTime() { + return dateTime; + } + + public synchronized void setDateTime(Date dateTime) { + this.dateTime = dateTime; + } + + public synchronized byte[] getSignedPDF() { + return signedPDF; + } + + public synchronized void setSignedPDF(byte[] signedPDF) { + this.signedPDF = signedPDF; + } + + public synchronized String getTrustProfileID() { + return trustProfileID; + } + + public synchronized void setTrustProfileID(String trustProfileID) { + this.trustProfileID = trustProfileID; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFRequestParser.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFRequestParser.java new file mode 100644 index 0000000..7601b31 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFRequestParser.java @@ -0,0 +1,60 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.io.IOException; +import java.util.Date; + +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.api.xmlbind.RequestParserUtils; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; + +public class VerifyPDFRequestParser { + + // + // XPath expressions for selecting parts of the DOM message + // + private static final String MOA = Constants.MOA_PREFIX + ":"; + private static final String DATE_TIME_XPATH = MOA + "DateTime"; + private static final String PDF_SIGNATURE_XPATH = MOA + "PDFSignature"; + private static final String TRUST_PROFILE_ID_XPATH = MOA + "TrustProfileID"; + + public VerifyPDFRequest parse(Element requestElem) throws MOAApplicationException { + + VerifyPDFRequest verifyPDFRequest = new VerifyPDFRequest(); + + Date dateTime = RequestParserUtils.parseDateTime(requestElem, DATE_TIME_XPATH); + byte[] signedPDF = null; + try { + signedPDF = parsePDF(requestElem); + } catch (IOException e) { + throw new MOAApplicationException("Failed to extract signed pdf data", null, e); + } + String trustProfileID = XPathUtils.getElementValue(requestElem, TRUST_PROFILE_ID_XPATH, null); + verifyPDFRequest.setDateTime(dateTime); + verifyPDFRequest.setSignedPDF(signedPDF); + verifyPDFRequest.setTrustProfileID(trustProfileID); + + return verifyPDFRequest; + } + + /** + * Parse the content contained in a <code>CMSContentBaseType</code> kind of + * DOM element. + * + * @param contentElem + * The <code>CMSContentBaseType</code> kind of element to parse. + * @return A <code>CMSDataObject</code> API object containing the data from + * the given DOM element. + * @throws IOException + */ + private byte[] parsePDF(Element contentElem) throws IOException { + Element base64ContentElem = (Element) XPathUtils.selectSingleNode(contentElem, PDF_SIGNATURE_XPATH); + + String base64Str = DOMUtils.getText(base64ContentElem); + return Base64Utils.decode(base64Str, true); + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFResponse.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFResponse.java new file mode 100644 index 0000000..76746cf --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFResponse.java @@ -0,0 +1,20 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.util.List; + +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; + +public class VerifyPDFResponse { + private List<VerifyResult> verificationResults = null; + + public VerifyPDFResponse() { + } + + public synchronized List<VerifyResult> getVerificationResults() { + return verificationResults; + } + + public synchronized void setVerificationResults(List<VerifyResult> verificationResults) { + this.verificationResults = verificationResults; + } +} diff --git a/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFResponseBuilder.java b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFResponseBuilder.java new file mode 100644 index 0000000..705eff6 --- /dev/null +++ b/moaSig/moa-sig/src/main/java/at/gv/egovernment/moa/spss/server/xmlbind/VerifyPDFResponseBuilder.java @@ -0,0 +1,110 @@ +package at.gv.egovernment.moa.spss.server.xmlbind; + +import java.util.Iterator; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.xmlbind.ResponseBuilderUtils; +import at.gv.egovernment.moa.spss.server.pdfas.ExtendedVerifyResult; +import at.gv.egovernment.moa.util.Constants; + +public class VerifyPDFResponseBuilder { + private static final String MOA_NS_URI = Constants.MOA_NS_URI; + + //private static final Logger logger = LoggerFactory.getLogger(VerifyPDFResponseBuilder.class); + + /** The XML document containing the response element. */ + private Document responseDoc; + /** The response <code>CreateCMSSignatureResponse</code> DOM element. */ + private Element responseElem; + + /** + * Create a new <code>CreateCMSSignatureResponseBuilder</code>: + * + * @throws MOASystemException + * An error occurred setting up the resulting XML document. + */ + public VerifyPDFResponseBuilder() throws MOASystemException { + responseDoc = ResponseBuilderUtils.createResponse("VerifyPDFSignatureResponse"); + responseElem = responseDoc.getDocumentElement(); + } + + /** + * Build a document containing a <code>CreateCMSSignatureResponse</code> DOM + * element being the XML representation of the given + * <code>CreateCMSSignatureResponse</code> API object. + * + * @param response + * The <code>CreateCMSSignatureResponse</code> to convert to XML. + * @return A document containing the <code>CreateCMSSignatureResponse</code> + * DOM element. + */ + public Document build(VerifyPDFResponse response) throws MOAException { + if(response.getVerificationResults() == null) { + throw new MOAApplicationException("No verification results available", null); + } + Iterator<VerifyResult> iter = response.getVerificationResults().iterator(); + + while (iter.hasNext()) { + VerifyResult verifyResult = iter.next(); + addVerifyResult(verifyResult); + } + + return responseDoc; + } + + private void addVerifyResult(VerifyResult verifyResult) throws MOAApplicationException { + Element pdfSignature = responseDoc.createElementNS(MOA_NS_URI, "SignatureResult"); + + + String qcSource = null; + String publicAuthorityID = null; + String sscdSource = null; + boolean isPublicAuthority = false; + boolean isSSCD = false; + String issureCountryCode = null; + + if(verifyResult instanceof ExtendedVerifyResult) { + ExtendedVerifyResult extendedVerifyResult = (ExtendedVerifyResult)verifyResult; + + qcSource = extendedVerifyResult.getQcSource(); + publicAuthorityID = extendedVerifyResult.getPublicAuthorityID(); + sscdSource = extendedVerifyResult.getQcSource(); + issureCountryCode = extendedVerifyResult.getIssureCountryCode(); + + isPublicAuthority = extendedVerifyResult.isPublicAuthority(); + isSSCD = extendedVerifyResult.isSSCD(); + } + + ResponseBuilderUtils.addSignerInfo(responseDoc, pdfSignature, + verifyResult.getSignerCertificate(), + verifyResult.isQualifiedCertificate(), + qcSource, + isPublicAuthority, + publicAuthorityID, + isSSCD, + sscdSource, + issureCountryCode); + + ResponseBuilderUtils.addCodeInfoElement( + responseDoc, + pdfSignature, + "SignatureCheck", + verifyResult.getValueCheckCode().getCode(), + (String)null); + + ResponseBuilderUtils.addCodeInfoElement( + responseDoc, + pdfSignature, + "CertificateCheck", + verifyResult.getCertificateCheck().getCode(), + (String)null); + + responseElem.appendChild(pdfSignature); + } +} |