diff options
author | Thomas <> | 2023-01-11 23:23:30 +0100 |
---|---|---|
committer | Thomas <> | 2023-01-11 23:23:30 +0100 |
commit | 42e68c8f3e53b34663d2fe9c434b0b034ff9ddf0 (patch) | |
tree | de9aceb59655ff02fcbc4100f07fe33d035f34f1 | |
parent | 989f7685e730255a08c32e7a10c090f2ffc22d26 (diff) | |
download | pdf-as-4-42e68c8f3e53b34663d2fe9c434b0b034ff9ddf0.tar.gz pdf-as-4-42e68c8f3e53b34663d2fe9c434b0b034ff9ddf0.tar.bz2 pdf-as-4-42e68c8f3e53b34663d2fe9c434b0b034ff9ddf0.zip |
feat(web): add bulk-light functionality into PDF-AS-Web
30 files changed, 2149 insertions, 1259 deletions
diff --git a/build.gradle b/build.gradle index fab5e81a..e990df14 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,9 @@ subprojects { } dependencies { - testImplementation 'junit:junit:4.13.2' + compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24' + testImplementation 'junit:junit:4.13.2' } task sourcesJar(type: Jar, dependsOn: classes) { @@ -70,7 +72,7 @@ subprojects { archives sourcesJar } - sourceCompatibility = 1.7 + sourceCompatibility = 1.8 compileJava.options.encoding = "UTF-8" compileTestJava.options.encoding = "UTF-8" project.ext{ diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/CoreSignParams.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/CoreSignParams.java new file mode 100644 index 00000000..f86e93b6 --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/CoreSignParams.java @@ -0,0 +1,32 @@ +package at.gv.egiz.pdfas.api.processing; + +import java.io.Serializable; +import java.util.Map; + +import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; +import lombok.Data; + +@Data +public class CoreSignParams implements Serializable { + + private static final long serialVersionUID = 947480605651880556L; + + String transactionId; + + Connector connector; + + String invokeUrl; + + String invokeTarget; + + String invokeErrorUrl; + + String keyIdentifier; + + Map<String,String> preprocessor; + + Map<String,String> overrides; + + Map<String,String> signatureBlockParameters; + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/DocumentToSign.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/DocumentToSign.java new file mode 100644 index 00000000..6cc3a933 --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/DocumentToSign.java @@ -0,0 +1,22 @@ +package at.gv.egiz.pdfas.api.processing; + +import java.io.Serializable; + +import lombok.Data; + +@Data +public class DocumentToSign implements Serializable { + + private static final long serialVersionUID = 551977730667465367L; + + byte[] inputData; + + String fileName; + + String position; + + String qrCodeContent; + + String profile; + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/PdfasSignRequest.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/PdfasSignRequest.java new file mode 100644 index 00000000..b36b5a4c --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/PdfasSignRequest.java @@ -0,0 +1,62 @@ +package at.gv.egiz.pdfas.api.processing; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import at.gv.egiz.pdfas.api.ws.VerificationLevel; +import lombok.Getter; +import lombok.Setter; + +@Getter +public class PdfasSignRequest implements Serializable, Iterator<DocumentToSign> { + + private static final long serialVersionUID = -7245405996920651806L; + + @Setter + String requestID; + + @Setter + CoreSignParams coreParams; + + @Setter + VerificationLevel verificationLevel; + + List<DocumentToSign> input; + + /** + * Add single PDF for signing. + * + * @param pdf PDF to sign + */ + public void addDocumentToSign(DocumentToSign pdf) { + if (input == null) { + input = new ArrayList<>(); + + } + input.add(pdf); + + } + + + /** + * <code>true</code> if there is one or more {@link DocumentToSign}, otherwise <code>false</code>. + */ + @Override + public boolean hasNext() { + return input != null && !input.isEmpty(); + + } + + /** + * Get next {@link DocumentToSign}. + */ + @Override + public synchronized DocumentToSign next() { + return input.remove(0); + + } + + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/PdfasSignResponse.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/PdfasSignResponse.java new file mode 100644 index 00000000..3618715f --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/PdfasSignResponse.java @@ -0,0 +1,23 @@ +package at.gv.egiz.pdfas.api.processing; + +import java.io.Serializable; +import java.util.List; + +import lombok.Builder; +import lombok.Data; +import lombok.Singular; + +@Data +@Builder(toBuilder = true) +public class PdfasSignResponse implements Serializable { + + private static final long serialVersionUID = -3235466827933651452L; + + String requestId; + + String transactionId; + + @Singular + List<SignedDocument> signedPdfs; + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/SignedDocument.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/SignedDocument.java new file mode 100644 index 00000000..348746df --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/processing/SignedDocument.java @@ -0,0 +1,25 @@ +package at.gv.egiz.pdfas.api.processing; + +import java.io.Serializable; + +import at.gv.egiz.pdfas.api.ws.PDFASVerificationResponse; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class SignedDocument implements Serializable { + + private static final long serialVersionUID = 5409915106152807937L; + + Long signingTimestamp; + + byte[] outputData; + + String fileName; + + String signerCertificate; + + PDFASVerificationResponse verificationResponse; + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSignParameters.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSignParameters.java index 94906112..a70b8f56 100644 --- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSignParameters.java +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSignParameters.java @@ -23,11 +23,8 @@ ******************************************************************************/ package at.gv.egiz.pdfas.api.ws; -import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.Serializable; +import java.util.Arrays; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlEnumValue; @@ -71,6 +68,15 @@ public class PDFASSignParameters implements Serializable { public String toString(){ return name; } + + public static Connector fromString(String value) { + return Arrays.asList(Connector.values()).stream() + .filter(el -> el.toString().equalsIgnoreCase(value)) + .findFirst() + .get(); + + } + } diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSigning.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSigning.java index 667080fa..beeff937 100644 --- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSigning.java +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PDFASSigning.java @@ -44,4 +44,14 @@ public interface PDFASSigning { @WebMethod(operationName = "signBulk") @WebResult(name="bulkResponse") public PDFASBulkSignResponse signPDFDokument(@WebParam(name = "signBulkRequest") PDFASBulkSignRequest request); + + @WebMethod(operationName = "signMultiple") + @WebResult(name="signMultipleResponse") + public PdfasSignMultipleResponse signPDFDokument(@WebParam(name = "signMultipleRequest") PdfasSignMultipleRequest request); + + @WebMethod(operationName = "getMultiple") + @WebResult(name="getMultipleResponse") + public PdfasSignMultipleResponse getSignedDokument(@WebParam(name = "getMultipleRequest") PdfasGetMultipleRequest request); + + } diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasGetMultipleRequest.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasGetMultipleRequest.java new file mode 100644 index 00000000..5f4f3a27 --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasGetMultipleRequest.java @@ -0,0 +1,24 @@ +package at.gv.egiz.pdfas.api.ws; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@XmlType(name="getMultipleRequest") +@XmlAccessorType(XmlAccessType.FIELD) +public class PdfasGetMultipleRequest implements Serializable { + + private static final long serialVersionUID = -7105371679206044280L; + + @XmlElement(required = true, nillable = false, name="token") + String token; + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignDocument.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignDocument.java new file mode 100644 index 00000000..e065ef5e --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignDocument.java @@ -0,0 +1,37 @@ +package at.gv.egiz.pdfas.api.ws; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@XmlType(name="signMultipleFile") +@XmlAccessorType(XmlAccessType.FIELD) +public class PdfasSignDocument implements Serializable { + + private static final long serialVersionUID = -2422995343468207094L; + + @XmlElement(required = true, nillable = false, name="inputData") + byte[] inputData; + + @XmlElement(required = true, nillable = false, name="fileName") + String fileName; + + @XmlElement(required = false, nillable = true, name="position") + String position; + + @XmlElement(required = false, nillable = true, name="qrCodeContent") + String qrCodeContent; + + @XmlElement(required = false, nillable = true, name="profile") + String profile; + +} + diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignMultipleRequest.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignMultipleRequest.java new file mode 100644 index 00000000..8d172bfb --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignMultipleRequest.java @@ -0,0 +1,60 @@ +package at.gv.egiz.pdfas.api.ws; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@XmlType(name="signMultipleRequest") +@XmlAccessorType(XmlAccessType.FIELD) +public class PdfasSignMultipleRequest implements Serializable { + + private static final long serialVersionUID = 4338536417988335976L; + + @XmlElement(required = true, nillable = false, name="requestID") + String requestID; + + @XmlElement(required = false, nillable = true, name="transactionId") + String transactionId; + + @XmlElement(required = true, nillable = false, name="connector") + Connector connector; + + @XmlElement(required = false, nillable = true, name="invoke-url") + String invokeUrl; + + @XmlElement(required = false, nillable = true, name="invoke-target") + String invokeTarget; + + @XmlElement(required = false, nillable = true, name="invoke-error-url") + String invokeErrorUrl; + + @XmlElement(required = false, nillable = true, name="keyIdentifier") + String keyIdentifier; + + @XmlElement(required = false, nillable = true, name="preprocessorArguments") + PDFASPropertyMap preprocessor; + + @XmlElement(required = false, nillable = true, name="configurationOverrides") + PDFASPropertyMap overrides; + + @XmlElement(required = false, nillable = true, name="signatureBlockParameter") + Map<String,String> signatureBlockParameters; + + @XmlElement(required = false, nillable = true, name="verificationLevel") + VerificationLevel verificationLevel; + + @XmlElement(required = true, nillable = false, name="documents") + List<PdfasSignDocument> input; + +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignMultipleResponse.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignMultipleResponse.java new file mode 100644 index 00000000..a2391d11 --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignMultipleResponse.java @@ -0,0 +1,35 @@ +package at.gv.egiz.pdfas.api.ws; + +import java.io.Serializable; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@XmlType(name="signMultipleResponse") +@XmlAccessorType(XmlAccessType.FIELD) +public class PdfasSignMultipleResponse implements Serializable { + private static final long serialVersionUID = 2544165926674778203L; + + @XmlElement(required = true, nillable = false, name="requestID") + String requestID; + + @XmlElement(required = false, nillable = true, name="transactionId") + String transactionId; + + @XmlElement(required = false, name="error") + String error; + + @XmlElement(required = false, name="redirectUrl") + String redirectUrl; + + @XmlElement(required = true, nillable = false, name="documents") + List<PdfasSignedDocument> output; +} diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignedDocument.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignedDocument.java new file mode 100644 index 00000000..7ac13e1d --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/api/ws/PdfasSignedDocument.java @@ -0,0 +1,30 @@ +package at.gv.egiz.pdfas.api.ws; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@XmlType(name="signedMultipleFile") +@XmlAccessorType(XmlAccessType.FIELD) +public class PdfasSignedDocument implements Serializable { + + private static final long serialVersionUID = -2621030544869357960L; + + @XmlElement(required = true, nillable = false, name="outputData") + byte[] outputData; + + @XmlElement(required = false, nillable = true, name="fileName") + String fileName; + + @XmlElement(required = false, nillable = false, name="verificationResponse") + PDFASVerificationResponse verificationResponse; + +} diff --git a/pdf-as-web-client/src/main/java/at/gv/egiz/pdfas/web/client/RemotePDFSigner.java b/pdf-as-web-client/src/main/java/at/gv/egiz/pdfas/web/client/RemotePDFSigner.java index c4a55521..c8a89541 100644 --- a/pdf-as-web-client/src/main/java/at/gv/egiz/pdfas/web/client/RemotePDFSigner.java +++ b/pdf-as-web-client/src/main/java/at/gv/egiz/pdfas/web/client/RemotePDFSigner.java @@ -35,6 +35,9 @@ import at.gv.egiz.pdfas.api.ws.PDFASBulkSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; import at.gv.egiz.pdfas.api.ws.PDFASSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSigning; +import at.gv.egiz.pdfas.api.ws.PdfasGetMultipleRequest; +import at.gv.egiz.pdfas.api.ws.PdfasSignMultipleRequest; +import at.gv.egiz.pdfas.api.ws.PdfasSignMultipleResponse; public class RemotePDFSigner implements PDFASSigning { @@ -61,4 +64,15 @@ public class RemotePDFSigner implements PDFASSigning { return proxy.signPDFDokument(request); } + @Override + public PdfasSignMultipleResponse signPDFDokument(PdfasSignMultipleRequest request) { + return proxy.signPDFDokument(request); + } + + @Override + public PdfasSignMultipleResponse getSignedDokument(PdfasGetMultipleRequest request) { + return proxy.getSignedDokument(request); + + } + } diff --git a/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/DBRequestStore.java b/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/DBRequestStore.java index 1499b8ba..5afb28e4 100644 --- a/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/DBRequestStore.java +++ b/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/DBRequestStore.java @@ -14,172 +14,237 @@ import org.hibernate.service.ServiceRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.stats.StatisticEvent; -import at.gv.egiz.pdfas.web.store.IRequestStore; import at.gv.egiz.pdfas.web.store.db.Request; +import at.gv.egiz.pdfas.web.store.db.Response; import at.gv.egiz.pdfas.web.store.db.StatisticRequest; public class DBRequestStore implements IRequestStore { - private static final Logger logger = LoggerFactory - .getLogger(DBRequestStore.class); - - private SessionFactory sessions; - private ServiceRegistry serviceRegistry; - - public DBRequestStore() { - Configuration cfg = new Configuration(); - cfg.addAnnotatedClass(Request.class); - cfg.setProperties(WebConfiguration.getHibernateProps()); - - serviceRegistry = new StandardServiceRegistryBuilder().applySettings( - cfg.getProperties()).build(); - - sessions = cfg.buildSessionFactory(serviceRegistry); - } - - private void cleanOldRequests() { - int seconds = WebConfiguration.getDBTimeout(); - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.SECOND, (-1) * seconds); - Date date = calendar.getTime(); - SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); - logger.info("Clearing Entries before: " + dt.format(date)); - Session session = null; - Transaction tx = null; - try { - session = sessions.openSession(); - tx = session.beginTransaction(); - Query query = session.createQuery("delete from Request as req" - + " where req.created < :date"); - query.setCalendar("date", calendar); - query.executeUpdate(); - } catch (Throwable e) { - logger.error("Failed to save Request", e); - tx.rollback(); - } finally { - if (session != null) { - session.close(); - } - } - } - - public void cleanOldRequestException() { - int seconds = WebConfiguration.getDBTimeout(); - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.SECOND, (-1) * seconds); - Date date = calendar.getTime(); - SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); - logger.info("Clearing Entries before: " + dt.format(date)); - Session session = null; - try { - session = sessions.openSession(); - Query query = session.createQuery("delete from Request as req" - + " where req.created < :date"); - query.setCalendar("date", calendar); - query.executeUpdate(); - - Query queryStat = session.createQuery("delete from StatisticRequest as req" - + " where req.created < :date"); - queryStat.setCalendar("date", calendar); - queryStat.executeUpdate(); - } finally { - if (session != null) { - session.close(); - } - } - } - - public String createNewStoreEntry(PDFASSignRequest request, - StatisticEvent event) { - // Clean Old Requests - this.cleanOldRequests(); - Session session = null; - Transaction tx = null; - try { - session = sessions.openSession(); - tx = session.beginTransaction(); - Request dbRequest = new Request(); - dbRequest.setSignRequest(request); - dbRequest.setCreated(Calendar.getInstance().getTime()); - session.save(dbRequest); - - StatisticRequest statisticRequest = new StatisticRequest(); - statisticRequest.setStatisticEvent(event); - statisticRequest.setCreated(Calendar.getInstance().getTime()); - session.save(statisticRequest); - - tx.commit(); - return dbRequest.getId(); - } catch (Throwable e) { - logger.error("Failed to save Request", e); - tx.rollback(); - return null; - } finally { - if (session != null) { - session.close(); - } - } - } - - public PDFASSignRequest fetchStoreEntry(String id) { - // Clean Old Requests - this.cleanOldRequests(); - - Session session = null; - Transaction tx = null; - try { - session = sessions.openSession(); - tx = session.beginTransaction(); - Request dbRequest = (Request) session.get(Request.class, id); - - PDFASSignRequest request = dbRequest.getSignRequest(); - - session.delete(dbRequest); - - tx.commit(); - return request; - } catch (Throwable e) { - logger.error("Failed to fetch Request", e); - tx.rollback(); - return null; - } finally { - if (session != null) { - session.close(); - } - } - - } - - @Override - public StatisticEvent fetchStatisticEntry(String id) { - // Clean Old Requests - this.cleanOldRequests(); - - Session session = null; - Transaction tx = null; - try { - session = sessions.openSession(); - tx = session.beginTransaction(); - StatisticRequest dbRequest = (StatisticRequest) session.get( - StatisticRequest.class, id); - - StatisticEvent request = dbRequest.getStatisticEvent(); - - session.delete(dbRequest); - - tx.commit(); - return request; - } catch (Throwable e) { - logger.error("Failed to fetch Request", e); - tx.rollback(); - return null; - } finally { - if (session != null) { - session.close(); - } - } - } + private static final Logger logger = LoggerFactory + .getLogger(DBRequestStore.class); + + private final SessionFactory sessions; + private final ServiceRegistry serviceRegistry; + + public DBRequestStore() { + final Configuration cfg = new Configuration(); + cfg.addAnnotatedClass(Request.class); + cfg.setProperties(WebConfiguration.getHibernateProps()); + + serviceRegistry = new StandardServiceRegistryBuilder().applySettings( + cfg.getProperties()).build(); + + sessions = cfg.buildSessionFactory(serviceRegistry); + } + + private void cleanOldRequests() { + final int seconds = WebConfiguration.getDBTimeout(); + final Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, -1 * seconds); + final Date date = calendar.getTime(); + final SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); + logger.info("Clearing Entries before: " + dt.format(date)); + Session session = null; + Transaction tx = null; + try { + session = sessions.openSession(); + tx = session.beginTransaction(); + final Query query = session.createQuery("delete from Request as req" + + " where req.created < :date"); + query.setCalendar("date", calendar); + query.executeUpdate(); + } catch (final Throwable e) { + logger.error("Failed to save Request", e); + tx.rollback(); + } finally { + if (session != null) { + session.close(); + } + } + } + + public void cleanOldRequestException() { + final int seconds = WebConfiguration.getDBTimeout(); + final Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, -1 * seconds); + final Date date = calendar.getTime(); + final SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); + logger.info("Clearing Entries before: " + dt.format(date)); + Session session = null; + try { + session = sessions.openSession(); + final Query query = session.createQuery("delete from Request as req" + + " where req.created < :date"); + query.setCalendar("date", calendar); + query.executeUpdate(); + + final Query queryStat = session.createQuery("delete from StatisticRequest as req" + + " where req.created < :date"); + queryStat.setCalendar("date", calendar); + queryStat.executeUpdate(); + + final Query queryResponse = session.createQuery("delete from Response as req" + + " where req.created < :date"); + queryResponse.setCalendar("date", calendar); + queryResponse.executeUpdate(); + + } finally { + if (session != null) { + session.close(); + } + } + } + + @Override + public String createNewStoreEntry(PdfasSignRequest request, + StatisticEvent event) { + // Clean Old Requests + this.cleanOldRequests(); + Session session = null; + Transaction tx = null; + try { + session = sessions.openSession(); + tx = session.beginTransaction(); + final Request dbRequest = new Request(); + dbRequest.setSignRequest(request); + dbRequest.setCreated(Calendar.getInstance().getTime()); + session.save(dbRequest); + + final StatisticRequest statisticRequest = new StatisticRequest(); + statisticRequest.setStatisticEvent(event); + statisticRequest.setCreated(Calendar.getInstance().getTime()); + session.save(statisticRequest); + + tx.commit(); + return dbRequest.getId(); + } catch (final Throwable e) { + logger.error("Failed to save Request", e); + tx.rollback(); + return null; + } finally { + if (session != null) { + session.close(); + } + } + } + + @Override + public PdfasSignRequest fetchStoreEntry(String id) { + // Clean Old Requests + this.cleanOldRequests(); + + Session session = null; + Transaction tx = null; + try { + session = sessions.openSession(); + tx = session.beginTransaction(); + final Request dbRequest = session.get(Request.class, id); + + final PdfasSignRequest request = dbRequest.getSignRequest(); + + session.delete(dbRequest); + + tx.commit(); + return request; + } catch (final Throwable e) { + logger.error("Failed to fetch Request", e); + tx.rollback(); + return null; + } finally { + if (session != null) { + session.close(); + } + } + + } + + @Override + public StatisticEvent fetchStatisticEntry(String id) { + // Clean Old Requests + this.cleanOldRequests(); + + Session session = null; + Transaction tx = null; + try { + session = sessions.openSession(); + tx = session.beginTransaction(); + final StatisticRequest dbRequest = session.get( + StatisticRequest.class, id); + + final StatisticEvent request = dbRequest.getStatisticEvent(); + + session.delete(dbRequest); + + tx.commit(); + return request; + } catch (final Throwable e) { + logger.error("Failed to fetch Request", e); + tx.rollback(); + return null; + } finally { + if (session != null) { + session.close(); + } + } + } + + @Override + public String createNewResponseEntry(PdfasSignResponse response) { + // Clean Old Requests + this.cleanOldRequests(); + Session session = null; + Transaction tx = null; + try { + session = sessions.openSession(); + tx = session.beginTransaction(); + final Response dbRequest = new Response(); + dbRequest.setSignedResponse(response); + dbRequest.setCreated(Calendar.getInstance().getTime()); + session.save(dbRequest); + + tx.commit(); + return dbRequest.getId(); + } catch (final Throwable e) { + logger.error("Failed to save Request", e); + tx.rollback(); + return null; + } finally { + if (session != null) { + session.close(); + } + } + } + + @Override + public PdfasSignResponse fetchStoreResponse(String id) { + // Clean Old Requests + this.cleanOldRequests(); + + Session session = null; + Transaction tx = null; + try { + session = sessions.openSession(); + tx = session.beginTransaction(); + final Response dbResponse = session.get(Response.class, id); + + final PdfasSignResponse request = dbResponse.getSignedResponse(); + + session.delete(dbResponse); + + tx.commit(); + return request; + } catch (final Throwable e) { + logger.error("Failed to fetch Response", e); + tx.rollback(); + return null; + } finally { + if (session != null) { + session.close(); + } + } + } } diff --git a/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Request.java b/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Request.java index 54870365..f8a169c3 100644 --- a/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Request.java +++ b/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Request.java @@ -10,8 +10,7 @@ import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; -import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; -import at.gv.egiz.pdfas.web.stats.StatisticEvent; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; @Entity @Table(name = "requests") @@ -19,7 +18,7 @@ public class Request { private String uuid; private Date created; - private PDFASSignRequest signRequest; + private PdfasSignRequest signRequest; @Id @GeneratedValue(generator = "uuid") @@ -43,11 +42,11 @@ public class Request { } @Column(name = "signRequest", nullable = false, length = 52428800) - public PDFASSignRequest getSignRequest() { + public PdfasSignRequest getSignRequest() { return this.signRequest; } - public void setSignRequest(PDFASSignRequest signRequest) { + public void setSignRequest(PdfasSignRequest signRequest) { this.signRequest = signRequest; } diff --git a/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Response.java b/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Response.java new file mode 100644 index 00000000..a47f532c --- /dev/null +++ b/pdf-as-web-db/src/main/java/at/gv/egiz/pdfas/web/store/db/Response.java @@ -0,0 +1,54 @@ +package at.gv.egiz.pdfas.web.store.db; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.annotations.GenericGenerator; + +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; + +@Entity +@Table(name = "response") +public class Response { + + private String uuid; + private Date created; + private PdfasSignResponse signResponse; + + @Id + @GeneratedValue(generator = "uuid") + @GenericGenerator(name = "uuid", strategy = "uuid2") + @Column(name = "id", unique = true) + public String getId() { + return this.uuid; + } + + public void setId(String uuid) { + this.uuid = uuid; + } + + @Column(name = "created", nullable = false) + public Date getCreated() { + return this.created; + } + + public void setCreated(Date created) { + this.created = created; + } + + @Column(name = "signedResponse", nullable = false, length = 52428800) + public PdfasSignResponse getSignedResponse() { + return this.signResponse; + } + + public void setSignedResponse(PdfasSignResponse signResponse) { + this.signResponse = signResponse; + } + + +} diff --git a/pdf-as-web-statistic-api/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticEvent.java b/pdf-as-web-statistic-api/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticEvent.java index aafbb99b..a043be3f 100644 --- a/pdf-as-web-statistic-api/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticEvent.java +++ b/pdf-as-web-statistic-api/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticEvent.java @@ -23,6 +23,7 @@ public class StatisticEvent { public enum Operation { SIGN("sign"), + SIGNBULK("signBulk"), VERIFY("verify"); private String name; diff --git a/pdf-as-web/build.gradle b/pdf-as-web/build.gradle index 17ca596b..ad434bcf 100644 --- a/pdf-as-web/build.gradle +++ b/pdf-as-web/build.gradle @@ -48,6 +48,7 @@ sourceSets.test.runtimeClasspath += configurations.providedCompile dependencies { + api project (':pdf-as-common') api project (':pdf-as-lib') api project (':pdf-as-moa') api project (':signature-standards:sigs-pkcs7detached') @@ -64,6 +65,7 @@ dependencies { api group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.3' api "commons-codec:commons-codec:1.15" api 'org.apache.commons:commons-lang3:3.12.0' + api group: 'org.apache.commons', name: 'commons-collections4', version: '4.4' api 'org.apache.cxf:cxf-rt-transports-http:3.4.5' api 'org.apache.cxf:cxf-rt-frontend-jaxws:3.4.5' api 'com.thetransactioncompany:cors-filter:2.10' @@ -71,7 +73,9 @@ dependencies { api 'ch.qos.logback:logback-core:1.2.10' api 'org.json:json:20210307' api group: 'javax.jws', name: 'javax.jws-api', version: '1.1' - compileOnly 'javax.servlet:javax.servlet-api:3.0.1' + compileOnly 'javax.servlet:javax.servlet-api:3.0.1' + compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24' testImplementation group: 'junit', name: 'junit', version: '4.+' testRuntime 'org.springframework:spring-test:5.2.22.RELEASE' diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java index 2f7c9323..35b5a7ce 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java @@ -23,19 +23,68 @@ ******************************************************************************/ package at.gv.egiz.pdfas.web.helper; -import at.gv.egiz.pdfas.api.ws.PDFASSignParameters; +import java.awt.Image; +import java.awt.image.RenderedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLEncoder; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.imageio.ImageIO; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.xml.bind.JAXBElement; +import javax.xml.ws.WebServiceException; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.zxing.WriterException; + +import at.gv.egiz.pdfas.api.processing.CoreSignParams; +import at.gv.egiz.pdfas.api.processing.DocumentToSign; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse.PdfasSignResponseBuilder; +import at.gv.egiz.pdfas.api.processing.SignedDocument; import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; -import at.gv.egiz.pdfas.api.ws.PDFASSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASVerificationResponse; import at.gv.egiz.pdfas.common.exceptions.PDFASError; +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.common.utils.PDFUtils; -import at.gv.egiz.pdfas.lib.api.*; +import at.gv.egiz.pdfas.lib.api.ByteArrayDataSource; +import at.gv.egiz.pdfas.lib.api.Configuration; +import at.gv.egiz.pdfas.lib.api.IConfigurationConstants; +import at.gv.egiz.pdfas.lib.api.PdfAs; +import at.gv.egiz.pdfas.lib.api.PdfAsFactory; +import at.gv.egiz.pdfas.lib.api.StatusRequest; 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.sign.SignResult; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter; 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.StatusRequestImpl; import at.gv.egiz.pdfas.moa.MOAConnector; import at.gv.egiz.pdfas.sigs.pades.PAdESSigner; import at.gv.egiz.pdfas.sigs.pades.PAdESSignerKeystore; @@ -50,7 +99,7 @@ import at.gv.egiz.sl.schema.InfoboxReadRequestType; import at.gv.egiz.sl.schema.InfoboxReadResponseType; import at.gv.egiz.sl.schema.ObjectFactory; import at.gv.egiz.sl.util.BKUSLConnector; -import at.gv.egiz.sl.util.BaseSLConnector; +import at.gv.egiz.sl.util.ISLConnector; import at.gv.egiz.sl.util.RequestPackage; import at.gv.egiz.sl.util.SLMarschaller; import at.gv.egiz.sl20.SL20Connector; @@ -60,48 +109,21 @@ import at.gv.egiz.sl20.exceptions.SLCommandoParserException; import at.gv.egiz.sl20.utils.SL20Constants; import at.gv.egiz.sl20.utils.SL20JSONBuilderUtils; import at.gv.egiz.sl20.utils.SL20JSONExtractorUtils; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import iaik.x509.X509Certificate; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.entity.ContentType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.imageio.ImageIO; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.xml.bind.JAXBElement; -import javax.xml.ws.WebServiceException; -import java.awt.*; -import java.awt.image.RenderedImage; -import java.io.*; -import java.net.URL; -import java.net.URLEncoder; -import java.security.cert.CertificateException; -import java.util.*; -import java.util.List; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class PdfAsHelper { private static final String PDF_CONFIG = "PDF_CONFIG"; + + private static final String PDF_PROCESSING_REQUEST = "PDF_PROCESSING_REQUEST"; private static final String PDF_STATUS = "PDF_STATUS"; private static final String PDF_OUTPUT = "PDF_OUTPUT"; private static final String PDF_SL_CONNECTOR = "PDF_SL_CONNECTOR"; private static final String PDF_STATISTICS = "PDF_STATISTICS"; private static final String PDF_SIGNER = "PDF_SIGNER"; private static final String PDF_SL_INTERACTIVE = "PDF_SL_INTERACTIVE"; - private static final String PDF_SIGNED_DATA = "PDF_SIGNED_DATA"; - private static final String PDF_SIGNED_DATA_CREATED = "PDF_SIGNED_DATA_CREATED"; private static final String PDF_LOCALE = "PDF_LOCALE"; private static final String PDF_ERR_MESSAGE = "PDF_ERR_MESSAGE"; private static final String PDF_ERR_THROWABLE = "PDF_ERR_THROWABLE"; @@ -114,9 +136,7 @@ public class PdfAsHelper { private static final String PDF_USERENTRY_PAGE = "/userentry"; private static final String PDF_ERR_URL = "PDF_ERR_URL"; private static final String PDF_FILE_NAME = "PDF_FILE_NAME"; - private static final String PDF_SIGNER_CERT = "PDF_SIGNER_CERT"; private static final String PDF_VER_LEVEL = "PDF_VER_LEVEL"; - private static final String PDF_VER_RESP = "PDF_VER_RESP"; private static final String PDF_INVOKE_URL = "PDF_INVOKE_URL"; private static final String PDF_INVOKE_TARGET = "PDF_INVOKE_TARGET"; private static final String PDF_RESPONSE_MODE = "PDF_RESPONSE_MODE"; @@ -124,14 +144,14 @@ public class PdfAsHelper { private static final String SIGNATURE_DATA_HASH = "SIGNATURE_DATA_HASH"; private static final String SIGNATURE_ACTIVE = "SIGNATURE_ACTIVE"; private static final String VERIFICATION_RESULT = "VERIFICATION_RESULT"; + private static final String PDF_SIGNING_RESPONSE = "PDF_SIGNING_RESULT"; private static final String QRCODE_CONTENT = "QR_CONT"; public static final String PDF_SESSION_PREFIX = "PDF_SESSION_"; - + + public static final String DEFAULT_RESULT_FILENAME = "document.pdf"; - public enum PDF_RESPONSE_MODES {htmlform, direct}; - private static final Logger logger = LoggerFactory - .getLogger(PdfAsHelper.class); + public enum PDF_RESPONSE_MODES {htmlform, direct}; private static PdfAs pdfAs; private static ObjectFactory of = new ObjectFactory(); @@ -142,15 +162,15 @@ public class PdfAsHelper { } public static void init() { - logger.info("PDF-AS Helper initialized"); + log.info("PDF-AS Helper initialized"); } public static synchronized void reloadConfig() { - logger.info("Creating PDF-AS"); + log.info("Creating PDF-AS"); pdfAs = PdfAsFactory.createPdfAs(new File(WebConfiguration .getPdfASDir())); pdfAsConfig = pdfAs.getConfiguration(); - logger.info("Creating PDF-AS done"); + log.info("Creating PDF-AS done"); } public static Configuration getPdfAsConfig() { @@ -310,11 +330,11 @@ public class PdfAsHelper { try { signIdx = Integer.parseInt(signidxString); } catch (Throwable e) { - logger.warn("Failed to parse Signature Index: " + signidxString); + log.warn("Failed to parse Signature Index: " + signidxString); } } - logger.debug("Verifing Signature index: " + signIdx); + log.debug("Verifing Signature index: " + signIdx); Configuration config = pdfAs.getConfiguration(); @@ -335,7 +355,7 @@ public class PdfAsHelper { public static List<VerifyResult> synchronousVerify(byte[] pdfData, int signIdx, SignatureVerificationLevel lvl, Map<String, String> preProcessor) throws Exception { - logger.debug("Verifing Signature index: " + signIdx); + log.debug("Verifing Signature index: " + signIdx); Configuration config = pdfAs.getConfiguration(); @@ -354,198 +374,53 @@ public class PdfAsHelper { return results; } - - /** - * Create synchronous PDF Signature - * - * @param request - * The Web request - * @param response - * The Web response - * @param pdfData - * The pdf data - * @param dynamicSignatureBlockArguments - * @return The signed pdf data - * @throws Exception - */ - public static byte[] synchronousSignature(HttpServletRequest request, - HttpServletResponse response, byte[] pdfData, - Map<String, String> dynamicSignatureBlockArguments) throws Exception { - validatePdfSize(request, response, pdfData); - - Configuration config = pdfAs.getConfiguration(); - - - Map<String,String> configOverwrite = PdfAsParameterExtractor.getOverwriteMap(request); - ConfigurationOverwrite.overwriteConfiguration(configOverwrite, config); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - // Generate Sign Parameter - SignParameter signParameter = PdfAsFactory.createSignParameter(config, - new ByteArrayDataSource(pdfData), baos); - - // Get Connector - String connector = PdfAsParameterExtractor.getConnector(request); - - if (!connector.equals("moa") && !connector.equals("jks")) { - throw new PdfAsWebException("Invalid connector (moa | jks)"); - } - - IPlainSigner signer; - if (connector.equals("moa")) { - - String keyIdentifier = PdfAsParameterExtractor - .getKeyIdentifier(request); - - if (keyIdentifier != null) { - if (!WebConfiguration.isMoaEnabled(keyIdentifier)) { - throw new PdfAsWebException("MOA connector [" - + keyIdentifier + "] disabled or not existing."); - } - - String url = WebConfiguration.getMoaURL(keyIdentifier); - String keyId = WebConfiguration.getMoaKeyID(keyIdentifier); - String certificate = WebConfiguration - .getMoaCertificate(keyIdentifier); - - config.setValue(IConfigurationConstants.MOA_SIGN_URL, url); - config.setValue(IConfigurationConstants.MOA_SIGN_KEY_ID, keyId); - config.setValue(IConfigurationConstants.MOA_SIGN_CERTIFICATE, - certificate); - } else { - if (!WebConfiguration.getMOASSEnabled()) { - throw new PdfAsWebException("MOA connector disabled."); - } - } - - signer = new PAdESSigner(new MOAConnector(config)); - } else if (connector.equals("jks")) { - - String keyIdentifier = PdfAsParameterExtractor - .getKeyIdentifier(request); - - boolean ksEnabled = false; - String ksFile = null; - String ksAlias = null; - String ksPass = null; - String ksKeyPass = null; - String ksType = null; - - if (keyIdentifier != null) { - ksEnabled = WebConfiguration.getKeystoreEnabled(keyIdentifier); - ksFile = WebConfiguration.getKeystoreFile(keyIdentifier); - ksAlias = WebConfiguration.getKeystoreAlias(keyIdentifier); - ksPass = WebConfiguration.getKeystorePass(keyIdentifier); - ksKeyPass = WebConfiguration.getKeystoreKeyPass(keyIdentifier); - ksType = WebConfiguration.getKeystoreType(keyIdentifier); - } else { - ksEnabled = WebConfiguration.getKeystoreDefaultEnabled(); - ksFile = WebConfiguration.getKeystoreDefaultFile(); - ksAlias = WebConfiguration.getKeystoreDefaultAlias(); - ksPass = WebConfiguration.getKeystoreDefaultPass(); - ksKeyPass = WebConfiguration.getKeystoreDefaultKeyPass(); - ksType = WebConfiguration.getKeystoreDefaultType(); - } - - if (!ksEnabled) { - if (keyIdentifier != null) { - throw new PdfAsWebException("JKS connector [" - + keyIdentifier + "] disabled or not existing."); - } else { - throw new PdfAsWebException( - "DEFAULT JKS connector disabled."); - } - } - - if (ksFile == null || ksAlias == null || ksPass == null - || ksKeyPass == null || ksType == null) { - if (keyIdentifier != null) { - throw new PdfAsWebException("JKS connector [" - + keyIdentifier + "] not correctly configured."); - } else { - throw new PdfAsWebException( - "DEFAULT JKS connector not correctly configured."); - } - } - - signer = new PAdESSignerKeystore(ksFile, ksAlias, ksPass, - ksKeyPass, ksType); - } else { - throw new PdfAsWebException("Invalid connector (moa | jks)"); - } - - signParameter.setPlainSigner(signer); - - String profileId = PdfAsParameterExtractor.getSigType(request); - String qrCodeContent = PdfAsHelper.getQRCodeContent(request); - - if (qrCodeContent != null) { - if (profileId == null) { - // get default Profile - profileId = config.getValue("sig_obj.type.default"); - } - - if (profileId == null) { - logger.warn("Failed to determine default profile! Using hard coded!"); - profileId = "SIGNATURBLOCK_SMALL_DE"; - } - - ByteArrayOutputStream qrbaos = new ByteArrayOutputStream(); - try { - String key = "sig_obj." + profileId + ".value.SIG_LABEL"; - QRCodeGenerator.generateQRCode(qrCodeContent, qrbaos, 200); - String value = Base64.encodeBase64String(qrbaos.toByteArray()); - config.setValue(key, value); - } finally { - IOUtils.closeQuietly(qrbaos); - } - } - - // set Signature Profile (null use default ...) - signParameter.setSignatureProfileId(profileId); - - // set Signature Position - signParameter.setSignaturePosition(buildPosString(request, response)); - - //set signature block parameters - signParameter.setDynamicSignatureBlockArguments(dynamicSignatureBlockArguments); - @SuppressWarnings("unused") - SignResult result = pdfAs.sign(signParameter); - - return baos.toByteArray(); - } - - /** - * Create synchronous PDF Signature - * - * @param params - * The Web request - * @param pdfData - * The pdf data - * @return The signed pdf data - * @throws Exception - */ - public static PDFASSignResponse synchronousServerSignature(byte[] pdfData, - PDFASSignParameters params, Map<String, String> dynamicSignatureBlockArguments) throws Exception { - + + public static PdfasSignResponse synchronousServerSignature(PdfasSignRequest internalReq) throws Exception { + log.debug("Find #{} files to sign synchronized. Starting signing process ... ", internalReq.getInput().size()); + PdfasSignResponseBuilder respBuilder = PdfasSignResponse.builder(); + respBuilder.requestId(internalReq.getRequestID()); + respBuilder.transactionId(internalReq.getCoreParams().getTransactionId()); + + // sign each document + Iterator<DocumentToSign> docsToSign = internalReq.getInput().iterator(); + while(docsToSign.hasNext()) { + respBuilder.signedPdf(synchronousServerSignature(docsToSign.next(), internalReq.getCoreParams())); + + } + + log.debug("Signing process finished."); + return respBuilder.build(); + + } + + /** + * Create synchronous signed PDF's + * + * @param documentToSign Document to sign with parameters + * @param coreParams generic signing parameters + * @return Signing result + * @throws Exception In case of an error + */ + private static SignedDocument synchronousServerSignature(DocumentToSign documentToSign, CoreSignParams coreParams) throws Exception { + log.debug("Signing file with transactionId:{}", coreParams.getTransactionId()); + Configuration config = pdfAs.getConfiguration(); - if (WebConfiguration.isAllowExtOverwrite() && params.getOverrides() != null) { - ConfigurationOverwrite.overwriteConfiguration(params.getOverrides().getMap(), config); + if (WebConfiguration.isAllowExtOverwrite() && coreParams.getOverrides() != null) { + ConfigurationOverwrite.overwriteConfiguration(coreParams.getOverrides(), config); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Generate Sign Parameter SignParameter signParameter = PdfAsFactory.createSignParameter(config, - new ByteArrayDataSource(pdfData), baos); + new ByteArrayDataSource(documentToSign.getInputData()), baos); // Get Connector IPlainSigner signer; - if (params.getConnector().equals(Connector.MOA)) { - String keyIdentifier = params.getKeyIdentifier(); + if (coreParams.getConnector().equals(Connector.MOA)) { + String keyIdentifier = coreParams.getKeyIdentifier(); if (keyIdentifier != null) { if (!WebConfiguration.isMoaEnabled(keyIdentifier)) { @@ -569,8 +444,10 @@ public class PdfAsHelper { } signer = new PAdESSigner(new MOAConnector(config)); - } else if (params.getConnector().equals(Connector.JKS)) { - String keyIdentifier = params.getKeyIdentifier(); + + + } else if (coreParams.getConnector().equals(Connector.JKS)) { + String keyIdentifier = coreParams.getKeyIdentifier(); boolean ksEnabled = false; String ksFile = null; @@ -618,17 +495,19 @@ public class PdfAsHelper { signer = new PAdESSignerKeystore(ksFile, ksAlias, ksPass, ksKeyPass, ksType); + } else { throw new PdfAsWebException("Invalid connector (moa | jks)"); + } signParameter.setPlainSigner(signer); - String profile = params.getProfile(); + String profile = documentToSign.getProfile(); // PdfAsHelper.getQRCodeContent(request); // Get QR Code Content form param - String qrCodeContent = params.getQRCodeContent(); + String qrCodeContent = documentToSign.getQrCodeContent(); if (qrCodeContent != null) { if (profile == null) { @@ -637,7 +516,7 @@ public class PdfAsHelper { } if (profile == null) { - logger.warn("Failed to determine default profile! Using hard coded!"); + log.warn("Failed to determine default profile! Using hard coded!"); profile = "SIGNATURBLOCK_SMALL_DE"; } @@ -656,220 +535,157 @@ public class PdfAsHelper { signParameter.setSignatureProfileId(profile); // set Signature Position - signParameter.setSignaturePosition(params.getPosition()); + signParameter.setSignaturePosition(documentToSign.getPosition()); // Set Preprocessor - if (params.getPreprocessor() != null) { - signParameter.setPreprocessorArguments(params.getPreprocessor() - .getMap()); - } - //TODO alex - signParameter.setDynamicSignatureBlockArguments(dynamicSignatureBlockArguments); - - SignResult signResult = pdfAs.sign(signParameter); - - PDFASSignResponse signResponse = new PDFASSignResponse(); - signResponse.setSignedPDF(baos.toByteArray()); - - PDFASVerificationResponse verResponse = new PDFASVerificationResponse(); - - verResponse.setSignerCertificate(signResult.getSignerCertificate() - .getEncoded()); - - signResponse.setVerificationResponse(verResponse); - - return signResponse; - } - - public static void startSignatureJson(HttpServletRequest request, - HttpServletResponse response, ServletContext context, - byte[] pdfData, String connector, String position, - String transactionId, String profile, - Map<String, String> preProcessor, Map<String, String> overwrite) throws Exception { - - // TODO: Protect session so that only one PDF can be signed during one - // session - /* - * if(PdfAsHelper.isSignatureActive(request)) { throw new - * PdfAsException("Signature is active in this session"); } - * - * PdfAsHelper.setSignatureActive(request, true); - */ - - validatePdfSize(request, response, pdfData); - - HttpSession session = request.getSession(); - - logger.info("Starting signature in session: " + session.getId()); - - Configuration config = pdfAs.getConfiguration(); - session.setAttribute(PDF_CONFIG, config); - - ConfigurationOverwrite.overwriteConfiguration(overwrite, config); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - session.setAttribute(PDF_OUTPUT, baos); - - // Generate Sign Parameter - SignParameter signParameter = PdfAsFactory.createSignParameter(config, - new ByteArrayDataSource(pdfData), baos); - - logger.info("Setting TransactionID: " + transactionId); - - signParameter.setTransactionId(transactionId); - - IPlainSigner signer; - if (connector.equals("bku") || connector.equals("onlinebku") - || connector.equals("mobilebku")) { - BKUSLConnector conn = new BKUSLConnector(config); - // conn.setBase64(true); - signer = new PAdESSigner(conn); - session.setAttribute(PDF_SL_CONNECTOR, conn); - - } else if (connector.equals("sl20")) { - SL20Connector conn = new SL20Connector(config); - signer = new PAdESSigner(conn); - session.setAttribute(PDF_SL_CONNECTOR, conn); + if (coreParams.getPreprocessor() != null) { + signParameter.setPreprocessorArguments(coreParams.getPreprocessor()); - } else { - throw new PdfAsWebException( - "Invalid connector (bku | onlinebku | mobilebku | moa | jks)"); - } - signParameter.setPreprocessorArguments(preProcessor); - signParameter.setPlainSigner(signer); - session.setAttribute(PDF_SIGNER, signer); - session.setAttribute(PDF_SL_INTERACTIVE, connector); - - String qrCodeContent = PdfAsHelper.getQRCodeContent(request); - - if (qrCodeContent != null) { - if (profile == null) { - // get default Profile - profile = config.getValue("sig_obj.type.default"); - } - - if (profile == null) { - logger.warn("Failed to determine default profile! Using hard coded!"); - profile = "SIGNATURBLOCK_SMALL_DE"; - } - - ByteArrayOutputStream qrbaos = new ByteArrayOutputStream(); - try { - String key = "sig_obj." + profile + ".value.SIG_LABEL"; - QRCodeGenerator.generateQRCode(qrCodeContent, qrbaos, 200); - String value = Base64.encodeBase64String(qrbaos.toByteArray()); - config.setValue(key, value); - } finally { - IOUtils.closeQuietly(qrbaos); - } } - // set Signature Profile (null use default ...) - signParameter.setSignatureProfileId(profile); + signParameter.setDynamicSignatureBlockArguments(coreParams.getSignatureBlockParameters()); - // set Signature Position - signParameter.setSignaturePosition(position); - - StatusRequest statusRequest = pdfAs.startSign(signParameter); - session.setAttribute(PDF_STATUS, statusRequest); - } - - public static void startSignature(HttpServletRequest request, - HttpServletResponse response, ServletContext context, - byte[] pdfData, String connector, String position, - String transactionId, String profile, - Map<String, String> preProcessor, Map<String, String> overwrite, Map<String, String> dynamicSignatureBlockArguments) throws Exception { - - // TODO: Protect session so that only one PDF can be signed during one - // session - /* - * if(PdfAsHelper.isSignatureActive(request)) { throw new - * PdfAsException("Signature is active in this session"); } - * - * PdfAsHelper.setSignatureActive(request, true); - */ - - validatePdfSize(request, response, pdfData); - - HttpSession session = request.getSession(); - - logger.info("Starting signature in session: " + session.getId()); - - Configuration config = pdfAs.getConfiguration(); - session.setAttribute(PDF_CONFIG, config); + SignResult signResult = pdfAs.sign(signParameter); - ConfigurationOverwrite.overwriteConfiguration(overwrite, config); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - session.setAttribute(PDF_OUTPUT, baos); - - // Generate Sign Parameter - SignParameter signParameter = PdfAsFactory.createSignParameter(config, - new ByteArrayDataSource(pdfData), baos); - - logger.info("Setting TransactionID: " + transactionId); + PDFASVerificationResponse verResponse = new PDFASVerificationResponse(); + verResponse.setSignerCertificate(signResult.getSignerCertificate() + .getEncoded()); - signParameter.setTransactionId(transactionId); - - IPlainSigner signer; - if (connector.equals("bku") || connector.equals("onlinebku") - || connector.equals("mobilebku")) { - BKUSLConnector conn = new BKUSLConnector(config); - // conn.setBase64(true); - signer = new PAdESSigner(conn); - session.setAttribute(PDF_SL_CONNECTOR, conn); - - } else if (connector.equals("sl20")) { - SL20Connector conn = new SL20Connector(config); - signer = new PAdESSigner(conn); - session.setAttribute(PDF_SL_CONNECTOR, conn); - - } else { - throw new PdfAsWebException( - "Invalid connector (bku | onlinebku | mobilebku | moa | jks | sl20)"); - } - signParameter.setPreprocessorArguments(preProcessor); - signParameter.setPlainSigner(signer); - session.setAttribute(PDF_SIGNER, signer); - session.setAttribute(PDF_SL_INTERACTIVE, connector); - - String qrCodeContent = PdfAsHelper.getQRCodeContent(request); - - if (qrCodeContent != null) { - if (profile == null) { - // get default Profile - profile = config.getValue("sig_obj.type.default"); - } - - if (profile == null) { - logger.warn("Failed to determine default profile! Using hard coded!"); - profile = "SIGNATURBLOCK_SMALL_DE"; - } - - ByteArrayOutputStream qrbaos = new ByteArrayOutputStream(); - try { - String key = "sig_obj." + profile + ".value.SIG_LABEL"; - QRCodeGenerator.generateQRCode(qrCodeContent, qrbaos, 200); - String value = Base64.encodeBase64String(qrbaos.toByteArray()); - config.setValue(key, value); - } finally { - IOUtils.closeQuietly(qrbaos); - } - } - - // set Signature Profile (null use default ...) - signParameter.setSignatureProfileId(profile); - - // set Signature Position - signParameter.setSignaturePosition(position); - - signParameter.setDynamicSignatureBlockArguments(dynamicSignatureBlockArguments); - StatusRequest statusRequest = pdfAs.startSign(signParameter); - session.setAttribute(PDF_STATUS, statusRequest); - - PdfAsHelper.process(request, response, context); + + SignedDocument signPdfDoc = SignedDocument.builder() + .signingTimestamp(Long.valueOf(System.currentTimeMillis())) + .outputData(baos.toByteArray()) + .fileName(documentToSign.getFileName()) + .verificationResponse(verResponse) + .signerCertificate(Base64.encodeBase64String(signResult.getSignerCertificate().getEncoded())) + .build(); + + return signPdfDoc; + } + public static void startSignatureJson(HttpServletRequest request, HttpServletResponse response, + ServletContext context, String connector, PdfasSignRequest pdfAsRequest) throws Exception { + HttpSession session = request.getSession(); + + log.info("Starting signature in session: " + session.getId()); + session.setAttribute(PDF_PROCESSING_REQUEST, pdfAsRequest); + + StatusRequest statusRequest = initializeSigningContextForNewDocument(request, connector, pdfAsRequest); + session.setAttribute(PDF_STATUS, statusRequest); + + } + + public static void startSignature(HttpServletRequest request, HttpServletResponse response, + ServletContext context, String connector, PdfasSignRequest pdfAsRequest) throws Exception { + HttpSession session = request.getSession(); + log.info("Starting signature in session: " + session.getId()); + session.setAttribute(PDF_PROCESSING_REQUEST, pdfAsRequest); + + StatusRequest statusRequest = initializeSigningContextForNewDocument(request, connector, pdfAsRequest); + session.setAttribute(PDF_STATUS, statusRequest); + + // start processing of first document + PdfAsHelper.process(request, response, context); + + } + + private static StatusRequest initializeSigningContextForNewDocument(HttpServletRequest request, String connector, PdfasSignRequest pdfAsRequest) + throws PdfAsWebException, WriterException, IOException, PdfAsException, PDFASError { + HttpSession session = request.getSession(); + + Configuration config = pdfAs.getConfiguration(); + session.setAttribute(PDF_CONFIG, config); + + ConfigurationOverwrite.overwriteConfiguration(pdfAsRequest.getCoreParams().getOverrides(), config); + + session.setAttribute(PDF_SL_INTERACTIVE, connector); + + // prepare first document + IPlainSigner signer = getSignerFromConnector(connector, config, session); + session.setAttribute(PDF_SIGNER, signer); + + String qrCodeContent = PdfAsHelper.getQRCodeContent(request); + + DocumentToSign documentToSign = pdfAsRequest.next(); + PdfAsHelper.setPDFFileName(request, documentToSign.getFileName()); + + return buildPdfasStatusRequestToSignSingleDocument(documentToSign, + session, signer, pdfAsRequest.getCoreParams(), qrCodeContent, config); + + } + + private static StatusRequest buildPdfasStatusRequestToSignSingleDocument(DocumentToSign pdfToSign, HttpSession session, IPlainSigner signer, + CoreSignParams coreSignParams, String qrCodeContent, Configuration config) throws WriterException, IOException, PdfAsException, PDFASError { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + session.setAttribute(PDF_OUTPUT, baos); + + // Generate Sign Parameter + SignParameter signParameter = PdfAsFactory.createSignParameter(config, new ByteArrayDataSource(pdfToSign.getInputData()), baos); + log.info("Setting TransactionID: " + coreSignParams.getTransactionId()); + signParameter.setTransactionId(coreSignParams.getTransactionId()); + + signParameter.setPlainSigner(signer); + + + signParameter.setPreprocessorArguments(coreSignParams.getPreprocessor()); + + + String profile = pdfToSign.getProfile(); + if (qrCodeContent != null) { + if (profile == null) { + // get default Profile + profile = config.getValue("sig_obj.type.default"); + } + + if (profile == null) { + log.warn("Failed to determine default profile! Using hard coded!"); + profile = "SIGNATURBLOCK_SMALL_DE"; + } + + ByteArrayOutputStream qrbaos = new ByteArrayOutputStream(); + try { + String key = "sig_obj." + profile + ".value.SIG_LABEL"; + QRCodeGenerator.generateQRCode(qrCodeContent, qrbaos, 200); + String value = Base64.encodeBase64String(qrbaos.toByteArray()); + config.setValue(key, value); + } finally { + IOUtils.closeQuietly(qrbaos); + } + } + + // set Signature Profile (null use default ...) + signParameter.setSignatureProfileId(profile); + + // set Signature Position + signParameter.setSignaturePosition(pdfToSign.getPosition()); + + signParameter.setDynamicSignatureBlockArguments(coreSignParams.getSignatureBlockParameters()); + + return pdfAs.startSign(signParameter); + + } + + private static IPlainSigner getSignerFromConnector(String connector, Configuration config, HttpSession session) throws PdfAsWebException { + if (connector.equals("bku") || connector.equals("onlinebku") + || connector.equals("mobilebku")) { + BKUSLConnector conn = new BKUSLConnector(config); + session.setAttribute(PDF_SL_CONNECTOR, conn); + return new PAdESSigner(conn); + + + } else if (connector.equals("sl20")) { + SL20Connector conn = new SL20Connector(config); + session.setAttribute(PDF_SL_CONNECTOR, conn); + return new PAdESSigner(conn); + + } else { + throw new PdfAsWebException( + "Invalid connector (bku | onlinebku | mobilebku | moa | jks | sl20)"); + } + } + public static byte[] getCertificate( InfoboxReadResponseType infoboxReadResponseType) { byte[] data = null; @@ -953,7 +769,7 @@ public class PdfAsHelper { byte[] cmsSginature, ServletContext context) throws Exception { - logger.debug("Got CMS Signature Response"); + log.debug("Got CMS Signature Response"); HttpSession session = request.getSession(); StatusRequest statusRequest = (StatusRequest) session @@ -973,7 +789,7 @@ public class PdfAsHelper { public static void logAccess(HttpServletRequest request) { HttpSession session = request.getSession(); - logger.info("Access to " + request.getServletPath() + " in Session: " + log.info("Access to " + request.getServletPath() + " in Session: " + session.getId()); } @@ -994,7 +810,7 @@ public class PdfAsHelper { .getAttribute(PDF_SL_CONNECTOR); if (statusRequest.needCertificate()) { - logger.debug("Needing Certificate from BKU"); + log.debug("Needing Certificate from BKU"); // build SL Request to read certificate InfoboxReadRequestType readCertificateRequest = bkuSLConnector .createInfoboxReadRequest(statusRequest @@ -1014,42 +830,32 @@ public class PdfAsHelper { return null; } - public static void process(HttpServletRequest request, + protected static void process(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws Exception { HttpSession session = request.getSession(); - StatusRequest statusRequest = (StatusRequest) session - .getAttribute(PDF_STATUS); + StatusRequest statusRequest = (StatusRequest) session.getAttribute(PDF_STATUS); + PdfasSignRequest pdfAsRequest = (PdfasSignRequest) session.getAttribute(PDF_PROCESSING_REQUEST); + + // IPlainSigner plainSigner = (IPlainSigner) session // .getAttribute(PDF_SIGNER); String connector = (String) session.getAttribute(PDF_SL_INTERACTIVE); //load connector - BaseSLConnector slConnector = null; - if (connector.equals("bku") || connector.equals("onlinebku") - || connector.equals("mobilebku")) - slConnector = (BKUSLConnector) session - .getAttribute(PDF_SL_CONNECTOR); - - else if (connector.equals("sl20")) - slConnector = (SL20Connector) session - .getAttribute(PDF_SL_CONNECTOR); - - else - throw new PdfAsWebException("Invalid connector: " + connector); + ISLConnector slConnector = (ISLConnector) session.getAttribute(PDF_SL_CONNECTOR); JsonSecurityUtils joseTools = JsonSecurityUtils.getInstance(); if (!joseTools.isInitialized()) joseTools = null; if (statusRequest.needCertificate()) { - logger.debug("Needing Certificate from BKU"); + log.debug("Needing Certificate from BKU"); // build SL Request to read certificate InfoboxReadRequestType readCertificateRequest = slConnector - .createInfoboxReadRequest(statusRequest - .getSignParameter()); + .createInfoboxReadRequest(statusRequest.getSignParameter()); if (slConnector instanceof BKUSLConnector) { JAXBElement<InfoboxReadRequestType> readRequest = of @@ -1114,7 +920,7 @@ public class PdfAsHelper { //send SL20 request via Backend connection JsonObject sl20Resp = sl20Connector.sendSL20Request(sl20Req, null, generateBKUURL(connector)); if (sl20Resp == null) { - logger.info("Receive NO responce from SL2.0 connection. Process stops ... "); + log.info("Receive NO responce from SL2.0 connection. Process stops ... "); throw new SLCommandoParserException(); } @@ -1124,12 +930,12 @@ public class PdfAsHelper { sl20Resp, joseTools, false); if (respPayloadContainer.isValidSigned() == null) - logger.debug("Receive unsigned payLoad from VDA"); + log.debug("Receive unsigned payLoad from VDA"); JsonObject respPayload = respPayloadContainer.getPayload(); if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString() .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) { - logger.debug("Find 'redirect' command in VDA response ... "); + log.debug("Find 'redirect' command in VDA response ... "); JsonObject params = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true); String redirectURL = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true); JsonObject command = SL20JSONExtractorUtils.getJSONObjectValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false); @@ -1156,11 +962,11 @@ public class PdfAsHelper { String errorCode = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); String errorMsg = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true); - logger.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); + log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); throw new SL20Exception("sl20.08"); } else { - logger.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()); + log.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()); throw new SLCommandoParserException(); } @@ -1169,7 +975,7 @@ public class PdfAsHelper { throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName()); } else if (statusRequest.needSignature()) { - logger.debug("Needing Signature from BKU"); + log.debug("Needing Signature from BKU"); // build SL Request for cms signature RequestPackage pack = slConnector.createCMSRequest( statusRequest.getSignatureData(), @@ -1182,7 +988,7 @@ public class PdfAsHelper { .createCreateCMSSignatureRequest(pack .getRequestType())); - logger.trace("SL Request: " + slRequest); + log.trace("SL Request: " + slRequest); response.setContentType("text/xml"); response.getWriter().write(slRequest); @@ -1192,11 +998,11 @@ public class PdfAsHelper { //convert byte range int[] exclude_range = PDFUtils.buildExcludeRange(statusRequest.getSignatureDataByteRange()); - logger.info("Exclude Byte Range: " + exclude_range[0] + " " + exclude_range[1]); + log.info("Exclude Byte Range: " + exclude_range[0] + " " + exclude_range[1]); List<JsonElement> byteRanges = new ArrayList<JsonElement>(); if (statusRequest.getSignatureDataByteRange().length % 2 != 0) { - logger.warn("ByteRange is not a set of pairs. Something is maybe suspect"); + log.warn("ByteRange is not a set of pairs. Something is maybe suspect"); } @@ -1266,7 +1072,7 @@ public class PdfAsHelper { request.getSession(false).setAttribute(PDF_SESSION_PREFIX + SL20Constants.SL20_REQID, reqId); //forward SL2.0 command - logger.trace("Write 'createCAdES' command to VDA: " + sl20CreateCAdES.toString()); + log.trace("Write 'createCAdES' command to VDA: " + sl20CreateCAdES.toString()); StringWriter writer = new StringWriter(); writer.write(sl20CreateCAdES.toString()); final byte[] content = writer.toString().getBytes("UTF-8"); @@ -1275,19 +1081,16 @@ public class PdfAsHelper { response.setContentType(ContentType.APPLICATION_JSON.toString()); response.getOutputStream().write(content); - } else + } else { throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName()); - - + } + } else if (statusRequest.isReady()) { - // TODO: store pdf document redirect to Finish URL - logger.debug("Document ready!"); - + log.debug("Single document is ready. Perform post-processing ... "); SignResult result = pdfAs.finishSign(statusRequest); - ByteArrayOutputStream baos = (ByteArrayOutputStream) session - .getAttribute(PDF_OUTPUT); + ByteArrayOutputStream baos = (ByteArrayOutputStream) session.getAttribute(PDF_OUTPUT); baos.close(); PDFASVerificationResponse verResponse = new PDFASVerificationResponse(); @@ -1305,35 +1108,55 @@ public class PdfAsHelper { .getCertificateCheck().getCode()); verResponse.setValueCode(verifyResult.getValueCheckCode() .getCode()); - - PdfAsHelper.setPDFASVerificationResponse(request, verResponse); - PdfAsHelper.setSignedPdf(request, response, baos.toByteArray()); - - String signerCert = Base64.encodeBase64String(result - .getSignerCertificate().getEncoded()); - - PdfAsHelper.setSignerCertificate(request, signerCert); + + SignedDocument signPdfDoc = SignedDocument.builder() + .signingTimestamp(Long.valueOf(System.currentTimeMillis())) + .outputData(baos.toByteArray()) + .fileName(PdfAsHelper.getPDFFileName(request)) + .verificationResponse(verResponse) + .signerCertificate(Base64.encodeBase64String(result.getSignerCertificate().getEncoded())) + .build(); + + addSignedDocumentToResult(request, signPdfDoc, pdfAsRequest.getRequestID(), + pdfAsRequest.getCoreParams().getTransactionId()); - if (slConnector instanceof BKUSLConnector) { - PdfAsHelper.gotoProvidePdf(context, request, response); - - } else if (slConnector instanceof SL20Connector) { - //TODO: add code to send SL20 redirect command to redirect the user from DataURL connection to App Front-End connection - String callUrl = generateProvideURL(request, response); - String transactionId = (String) request.getAttribute(PdfAsHelper.PDF_SESSION_PREFIX + SL20Constants.SL20_TRANSACTIONID); - buildSL20RedirectResponse(request, response, transactionId, callUrl); - - } else - throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName()); + // check if more files are available + if (pdfAsRequest.hasNext()) { + log.debug("Find additional file, restarting signing process again ... "); + StatusRequestImpl nextStatusRequest = (StatusRequestImpl)initializeSigningContextForNewDocument(request, connector, pdfAsRequest); + nextStatusRequest.setCertificate(((StatusRequestImpl)statusRequest).getCertificate().getEncoded()); + nextStatusRequest.setNeedCertificate(true); + + statusRequest = pdfAs.process(nextStatusRequest); + session.setAttribute(PDF_STATUS, nextStatusRequest); + + PdfAsHelper.process(request, response, context); + session.setAttribute(PDF_STATUS, nextStatusRequest); + + } else { + if (slConnector instanceof BKUSLConnector) { + PdfAsHelper.gotoProvidePdf(context, request, response); + + } else if (slConnector instanceof SL20Connector) { + //TODO: add code to send SL20 redirect command to redirect the user from DataURL connection to App Front-End connection + String callUrl = generateProvideURL(request, response); + String transactionId = (String) request.getAttribute(PdfAsHelper.PDF_SESSION_PREFIX + SL20Constants.SL20_TRANSACTIONID); + buildSL20RedirectResponse(request, response, transactionId, callUrl); + + } else + throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName()); + + } - } else { - throw new PdfAsWebException("Invalid state!"); - } + } else { + throw new PdfAsWebException("Invalid state!"); + + } } - private static String getTemplateSL() throws IOException { - String xml = FileUtils.readFileToString(FileUtils - .toFile(PdfAsHelper.class.getResource("/template_sl.html"))); + private static String getTemplateSL() throws IOException { + String xml = FileUtils.readFileToString( + FileUtils.toFile(PdfAsHelper.class.getResource("/template_sl.html"))); return xml; } @@ -1371,52 +1194,13 @@ public class PdfAsHelper { return xml; } - public static boolean isSignedDataExpired(HttpServletRequest request, - HttpServletResponse response) { - HttpSession session = request.getSession(); - Object signedData = session.getAttribute(PDF_SIGNED_DATA_CREATED); - if (signedData == null) { - logger.warn("Cannot find signed data created timestamp in session."); - return true; - } - - if (signedData instanceof Long) { - long created = ((Long)signedData).longValue(); - long now = System.currentTimeMillis(); - - long validUntil = created + 300000; - - logger.debug("Checking signed data valid until {} now is {}", - validUntil, now); - - return validUntil < now; - } - logger.warn("PDF_SIGNED_DATA_CREATED in session is not a long type!"); - return true; - } - - public static byte[] getSignedPdf(HttpServletRequest request, - HttpServletResponse response) { - HttpSession session = request.getSession(); - Object signedData = session.getAttribute(PDF_SIGNED_DATA); - if (signedData == null) { - return null; - } - - if (signedData instanceof byte[]) { - return (byte[]) signedData; - } - logger.warn("PDF_SIGNED_DATA in session is not a byte[] type!"); - return null; - } - - public static void setSignedPdf(HttpServletRequest request, - HttpServletResponse response, byte[] signedData) { - HttpSession session = request.getSession(); - session.setAttribute(PDF_SIGNED_DATA, signedData); - session.setAttribute(PDF_SIGNED_DATA_CREATED, Long.valueOf(System.currentTimeMillis())); - } - + public static String getInvokeRedirectTemplateMoreFiles() throws IOException { + String xml = FileUtils.readFileToString(FileUtils + .toFile(PdfAsHelper.class + .getResource("/template_invoke_redirect_more_files.html"))); + return xml; + } + public static void setStatisticEvent(HttpServletRequest request, HttpServletResponse response, StatisticEvent event) { HttpSession session = request.getSession(); @@ -1467,7 +1251,7 @@ public class PdfAsHelper { if (obj instanceof Throwable) { return (Throwable) obj; } - logger.warn("PDF_ERR_THROWABLE in session is not a throwable type!"); + log.warn("PDF_ERR_THROWABLE in session is not a throwable type!"); return null; } @@ -1498,7 +1282,7 @@ public class PdfAsHelper { public static void setErrorURL(HttpServletRequest request, HttpServletResponse response, String url) { HttpSession session = request.getSession(); - logger.debug("[" + session.getId() + "]: Setting Error URL to: " + url); + log.debug("[" + session.getId() + "]: Setting Error URL to: " + url); session.setAttribute(PDF_ERR_URL, url); } @@ -1512,7 +1296,7 @@ public class PdfAsHelper { public static void setInvokeURL(HttpServletRequest request, HttpServletResponse response, String url) { HttpSession session = request.getSession(); - logger.debug("[" + session.getId() + "]: Setting Invoke URL to: " + url); + log.debug("[" + session.getId() + "]: Setting Invoke URL to: " + url); session.setAttribute(PDF_INVOKE_URL, url); } @@ -1528,7 +1312,7 @@ public class PdfAsHelper { HttpSession session = request.getSession(); session.setAttribute(PDF_INVOKE_TARGET, url); - logger.debug("External Invoke TARGET: " + url); + log.debug("External Invoke TARGET: " + url); } public static String getInvokeTarget(HttpServletRequest request, @@ -1547,7 +1331,7 @@ public class PdfAsHelper { mode = PDF_RESPONSE_MODES.valueOf(responseMode); } catch (Exception e) { - logger.warn("HTTP parameter 'responsemode' has an unsupported value: " + responseMode + log.warn("HTTP parameter 'responsemode' has an unsupported value: " + responseMode + ". Use default value: " + mode.toString()); } @@ -1555,7 +1339,7 @@ public class PdfAsHelper { HttpSession session = request.getSession(); session.setAttribute(PDF_RESPONSE_MODE , mode); - logger.debug("External ResponseMode: " + mode.toString()); + log.debug("External ResponseMode: " + mode.toString()); } @@ -1565,11 +1349,11 @@ public class PdfAsHelper { Object obj = session.getAttribute(PDF_RESPONSE_MODE); if (obj == null) { - logger.debug("'responseMode' parameter is 'null'. Use defaultvalue: " + PDF_RESPONSE_MODES.htmlform.toString()); + log.debug("'responseMode' parameter is 'null'. Use defaultvalue: " + PDF_RESPONSE_MODES.htmlform.toString()); return PDF_RESPONSE_MODES.htmlform; } else { - logger.debug("'responseMode' parameter is " + ((PDF_RESPONSE_MODES) obj).toString()); + log.debug("'responseMode' parameter is " + ((PDF_RESPONSE_MODES) obj).toString()); return (PDF_RESPONSE_MODES) obj; } @@ -1596,7 +1380,7 @@ public class PdfAsHelper { + session.getId(); } } - logger.debug("Generated URL: " + dataURL); + log.debug("Generated URL: " + dataURL); return dataURL; } @@ -1639,7 +1423,7 @@ public class PdfAsHelper { public static String generateUserEntryURL(String storeId) { String publicURL = WebConfiguration.getPublicURL(); if (publicURL == null) { - logger.error("To use this functionality " + log.error("To use this functionality " + WebConfiguration.PUBLIC_URL + " has to be configured in the web configuration"); return null; @@ -1650,7 +1434,7 @@ public class PdfAsHelper { return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "=" + URLEncoder.encode(storeId, "UTF-8"); } catch (UnsupportedEncodingException e) { - logger.warn("Encoding not supported for URL encoding", e); + log.warn("Encoding not supported for URL encoding", e); } return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "=" + storeId; @@ -1723,24 +1507,45 @@ public class PdfAsHelper { if (obj != null) { return obj.toString(); } - return "document.pdf"; + return DEFAULT_RESULT_FILENAME; + } + + public static void addSignedDocumentToResult(HttpServletRequest request, SignedDocument signPdfDoc, + String requestId, String transactionId) { + PdfasSignResponse fullResponse = getPdfSigningResponse(request); + + if (fullResponse == null) { + setPdfSigningResponse(request, + PdfasSignResponse.builder() + .requestId(requestId) + .transactionId(transactionId) + .signedPdf(signPdfDoc).build()); + + } else { + setPdfSigningResponse(request, + fullResponse.toBuilder().signedPdf(signPdfDoc).build()); + + } } - - public static void setSignerCertificate(HttpServletRequest request, - String value) { - HttpSession session = request.getSession(); - session.setAttribute(PDF_SIGNER_CERT, value); + + public static void setPdfSigningResponse(HttpServletRequest request, PdfasSignResponse response) { + HttpSession session = request.getSession(); + session.setAttribute(PDF_SIGNING_RESPONSE, response); + } - - public static String getSignerCertificate(HttpServletRequest request) { - HttpSession session = request.getSession(); - Object obj = session.getAttribute(PDF_SIGNER_CERT); - if (obj != null) { - return obj.toString(); - } - return null; + + public static PdfasSignResponse getPdfSigningResponse(HttpServletRequest request) { + HttpSession session = request.getSession(); + Object obj = session.getAttribute(PDF_SIGNING_RESPONSE); + if (obj != null && obj instanceof PdfasSignResponse) { + return (PdfasSignResponse) obj; + + } + + return null; + } - + public static void setVerificationLevel(HttpServletRequest request, SignatureVerificationLevel lvl) { HttpSession session = request.getSession(); @@ -1757,22 +1562,6 @@ public class PdfAsHelper { return SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION; } - public static void setPDFASVerificationResponse(HttpServletRequest request, - PDFASVerificationResponse resp) { - HttpSession session = request.getSession(); - session.setAttribute(PDF_VER_RESP, resp); - } - - public static PDFASVerificationResponse getPDFASVerificationResponse( - HttpServletRequest request) { - HttpSession session = request.getSession(); - Object obj = session.getAttribute(PDF_VER_RESP); - if (obj != null && obj instanceof PDFASVerificationResponse) { - return (PDFASVerificationResponse) obj; - } - return null; - } - public static void setVerificationResult(HttpServletRequest request, List<VerifyResult> value) { HttpSession session = request.getSession(); @@ -1787,12 +1576,12 @@ public class PdfAsHelper { if (obj != null) { try { if (!(obj instanceof List<?>)) { - logger.warn("Invalid object type"); + log.warn("Invalid object type"); return null; } return (List<VerifyResult>) obj; } catch (Throwable e) { - logger.warn("Invalid object type"); + log.warn("Invalid object type"); } } return null; @@ -1861,14 +1650,14 @@ public class PdfAsHelper { redirectTwoCommand, null); - logger.trace("SL2.0 command: " + respContainer.toString()); + log.trace("SL2.0 command: " + respContainer.toString()); //workaround for A-Trust if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE) || true) { - logger.debug("Client request containts 'native client' header ... "); - logger.trace("SL20 response to VDA: " + respContainer); + log.debug("Client request containts 'native client' header ... "); + log.trace("SL20 response to VDA: " + respContainer); StringWriter writer = new StringWriter(); writer.write(respContainer.toString()); final byte[] content = writer.toString().getBytes("UTF-8"); @@ -1879,11 +1668,10 @@ public class PdfAsHelper { } else { - logger.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); + log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); throw new SL20Exception("sl20.06"); } } - } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java index 674d3351..898e44e2 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java @@ -23,6 +23,25 @@ ******************************************************************************/ package at.gv.egiz.pdfas.web.servlets; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +import at.gv.egiz.pdfas.api.processing.CoreSignParams; +import at.gv.egiz.pdfas.api.processing.DocumentToSign; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; +import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsValidationException; @@ -43,24 +62,12 @@ import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; import at.gv.egiz.pdfas.web.stats.StatisticFrontend; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; +import lombok.extern.slf4j.Slf4j; /** * Servlet implementation class Sign */ +@Slf4j public class ExternSignServlet extends HttpServlet { private static final long serialVersionUID = 1L; @@ -69,9 +76,6 @@ public class ExternSignServlet extends HttpServlet { private static final String UPLOAD_PDF_DATA = "pdf-file"; private static final String UPLOAD_DIRECTORY = "upload"; - - private static final Logger logger = LoggerFactory - .getLogger(ExternSignServlet.class); /** * Default constructor. @@ -81,7 +85,7 @@ public class ExternSignServlet extends HttpServlet { String webconfig = System.getProperty(PDF_AS_WEB_CONF); if(webconfig == null) { - logger.error("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF); + log.error("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF); throw new RuntimeException("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF); } @@ -92,7 +96,7 @@ public class ExternSignServlet extends HttpServlet { PdfAsFactory.validateConfiguration((ISettings)PdfAsHelper.getPdfAsConfig()); } catch (PdfAsSettingsValidationException e) { // TODO Auto-generated catch block - logger.error(e.getLocalizedMessage(),e.getCause()); + log.error(e.getLocalizedMessage(),e.getCause()); //e.printStackTrace(); } } @@ -100,9 +104,10 @@ public class ExternSignServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - //PdfAsHelper.regenerateSession(request); + // invalidate existing http sessions at first + request.getSession().invalidate(); - logger.debug("Get signing request"); + log.debug("Get signing request"); String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); PdfAsHelper.setErrorURL(request, response, errorUrl); @@ -131,7 +136,7 @@ public class ExternSignServlet extends HttpServlet { byte[] pdfData = RemotePDFFetcher.fetchPdfFile(pdfUrl); doSignature(request, response, pdfData, statisticEvent); } catch (Exception e) { - logger.error("Signature failed", e); + log.error("Signature failed", e); statisticEvent.setStatus(Status.ERROR); statisticEvent.setException(e); if(e instanceof PDFASError) { @@ -154,10 +159,11 @@ public class ExternSignServlet extends HttpServlet { */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - - //PdfAsHelper.regenerateSession(request); - - logger.debug("Post signing request"); + + // invalidate existing http sessions at first + request.getSession().invalidate(); + + log.debug("Post signing request"); String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); PdfAsHelper.setErrorURL(request, response, errorUrl); @@ -202,7 +208,7 @@ public class ExternSignServlet extends HttpServlet { } List<?> formItems = upload.parseRequest(request); - logger.debug(formItems.size() + " Items in form data"); + log.debug(formItems.size() + " Items in form data"); if (formItems.size() < 1) { // No Uploaded data! // Try do get @@ -224,30 +230,30 @@ public class ExternSignServlet extends HttpServlet { try { File f = new File(item.getName()); String name = f.getName(); - logger.debug("Got upload: " + item.getName()); + log.debug("Got upload: " + item.getName()); if(name != null) { if(!(name.endsWith(".pdf") || name.endsWith(".PDF"))) { name += ".pdf"; } - logger.debug("Setting Filename in session: " + name); + log.debug("Setting Filename in session: " + name); PdfAsHelper.setPDFFileName(request, name); } } catch(Throwable e) { - logger.warn("In resolving filename", e); + log.warn("In resolving filename", e); } if(filecontent.length < 10) { filecontent = null; } else { - logger.debug("Found pdf Data! Size: " + filecontent.length); + log.debug("Found pdf Data! Size: " + filecontent.length); } } else { request.setAttribute(item.getFieldName(), item.getString()); - logger.debug("Setting " + item.getFieldName() + " = " + item.getString()); + log.debug("Setting " + item.getFieldName() + " = " + item.getString()); } } else { - logger.debug(obj.getClass().getName() + " - " + obj.toString()); + log.debug(obj.getClass().getName() + " - " + obj.toString()); } } } @@ -282,7 +288,7 @@ public class ExternSignServlet extends HttpServlet { doSignature(request, response, filecontent, statisticEvent); } catch (Exception e) { - logger.error("Signature failed", e); + log.error("Signature failed", e); statisticEvent.setStatus(Status.ERROR); statisticEvent.setException(e); if(e instanceof PDFASError) { @@ -351,24 +357,48 @@ public class ExternSignServlet extends HttpServlet { } } catch(Exception e) { - logger.error(e.getLocalizedMessage()); + log.error(e.getLocalizedMessage()); } String filename = PdfAsParameterExtractor.getFilename(request); if(filename != null) { - logger.debug("Setting Filename in session: " + filename); + log.debug("Setting Filename in session: " + filename); PdfAsHelper.setPDFFileName(request, filename); } String pdfDataHash = DigestHelper.getHexEncodedHash(pdfData); PdfAsHelper.setSignatureDataHash(request, pdfDataHash); - logger.debug("Storing signatures data hash: " + pdfDataHash); + log.debug("Storing signatures data hash: " + pdfDataHash); Map<String, String> dynamicSignatureBlockArguments = PdfAsParameterExtractor.getDynamicSignatureBlockParameters(request); - logger.debug("Starting signature creation with: " + connector); + log.debug("Starting signature creation with: " + connector); + + // prepare internal process data-structure + PdfasSignRequest data = new PdfasSignRequest(); + + CoreSignParams coreParams = new CoreSignParams(); + coreParams.setSignatureBlockParameters(dynamicSignatureBlockArguments); + coreParams.setConnector(Connector.fromString(connector)); + coreParams.setKeyIdentifier(PdfAsParameterExtractor.getKeyIdentifier(request)); + coreParams.setOverrides(PdfAsParameterExtractor.getOverwriteMap(request)); + coreParams.setPreprocessor(PdfAsParameterExtractor.getPreProcessorMap(request)); + coreParams.setInvokeErrorUrl(errorUrl); + coreParams.setInvokeTarget(invokeTarget); + coreParams.setInvokeUrl(invokeUrl); + coreParams.setTransactionId(transactionId); + data.setCoreParams(coreParams); + + DocumentToSign document = new DocumentToSign(); + document.setInputData(pdfData); + document.setPosition(PdfAsHelper.buildPosString(request, response)); + document.setProfile(PdfAsParameterExtractor.getSigType(request)); + document.setQrCodeContent(qrcodeContent); + document.setFileName(PdfAsHelper.getPDFFileName(request)); + data.addDocumentToSign(document); + //IPlainSigner signer; if (connector.equals("bku") || connector.equals("onlinebku") || connector.equals("mobilebku") @@ -397,13 +427,12 @@ public class ExternSignServlet extends HttpServlet { } PdfAsHelper.setStatisticEvent(request, response, statisticEvent); + + // sign document + PdfAsHelper.startSignature(request, response, getServletContext(), connector, data); - - PdfAsHelper.startSignature(request, response, getServletContext(), pdfData, connector, - PdfAsHelper.buildPosString(request, response), transactionId, PdfAsParameterExtractor - .getSigType(request), PdfAsParameterExtractor.getPreProcessorMap(request), - PdfAsParameterExtractor.getOverwriteMap(request), dynamicSignatureBlockArguments); return; + } else if (connector.equals("jks") || connector.equals("moa")) { // start synchronous siganture creation @@ -434,10 +463,13 @@ public class ExternSignServlet extends HttpServlet { } } - byte[] pdfSignedData = PdfAsHelper.synchronousSignature(request, - response, pdfData, dynamicSignatureBlockArguments); - PdfAsHelper.setSignedPdf(request, response, pdfSignedData); + // sign document + PdfasSignResponse pdfSignedData = PdfAsHelper.synchronousServerSignature(data); + // inject response + PdfAsHelper.setPdfSigningResponse(request, pdfSignedData); + + // set statistic entry statisticEvent.setStatus(Status.OK); statisticEvent.setEndNow(); statisticEvent.setTimestampNow(); @@ -446,8 +478,10 @@ public class ExternSignServlet extends HttpServlet { PdfAsHelper.gotoProvidePdf(getServletContext(), request, response); return; + } else { throw new PdfAsWebException("Invalid connector (bku | moa | jks)"); + } } } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java index 641c09e7..d5ef2079 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java @@ -1,7 +1,28 @@ package at.gv.egiz.pdfas.web.servlets; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.api.processing.CoreSignParams; +import at.gv.egiz.pdfas.api.processing.DocumentToSign; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSignParameters; -import at.gv.egiz.pdfas.api.ws.PDFASSignResponse; +import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter; import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; @@ -13,27 +34,13 @@ import at.gv.egiz.pdfas.web.helper.JSONStartResponse; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.stats.StatisticEvent; import at.gv.egiz.pdfas.web.stats.StatisticFrontend; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.IOUtils; -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; /** * Created by Andreas Fitzek on 6/23/16. */ public class JSONAPIServlet extends HttpServlet { + private static final long serialVersionUID = -2319338922500393376L; private static final String JSON_PROFILE = "profile"; private static final String JSON_POSITION = "position"; private static final String JSON_CONNECTOR = "connector"; @@ -151,17 +158,39 @@ public class JSONAPIServlet extends HttpServlet { }catch(Exception e){ e.printStackTrace(); } + + + PdfasSignRequest data = new PdfasSignRequest(); + + data.setRequestID(requestID); + + CoreSignParams coreParams = new CoreSignParams(); + coreParams.setSignatureBlockParameters(signatureBlockParametersMap); + coreParams.setConnector(Connector.fromString(connector)); + data.setCoreParams(coreParams); + + DocumentToSign document = new DocumentToSign(); + document.setInputData(inputDocument); + document.setPosition(position); + document.setProfile(profile); + data.addDocumentToSign(document); + + + if (PDFASSignParameters.Connector.MOA.equals(connectorEnum) || PDFASSignParameters.Connector.JKS.equals(connectorEnum)) { // Plain server based signatures!! - PDFASSignResponse pdfasSignResponse = PdfAsHelper.synchronousServerSignature( - inputDocument, parameters, signatureBlockParametersMap); - + + + //TODO: update implementation to support more than one file!!!! + + PdfasSignResponse pdfasSignResponse = PdfAsHelper.synchronousServerSignature(data); + VerifyResult verifyResult = null; List<VerifyResult> verResults = PdfAsHelper .synchronousVerify( - pdfasSignResponse.getSignedPDF(), + pdfasSignResponse.getSignedPdfs().get(0).getOutputData(), -1, VerifyParameter.SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION, null); @@ -187,7 +216,7 @@ public class JSONAPIServlet extends HttpServlet { statisticEvent.setLogged(true); } - jsonResponse.put(JSON_OUTPUT, Base64.encodeBase64String(pdfasSignResponse.getSignedPDF())); + jsonResponse.put(JSON_OUTPUT, Base64.encodeBase64String(pdfasSignResponse.getSignedPdfs().get(0).getOutputData())); jsonResponse.put(JSON_OUTPUT_SIG, verifyResult.getValueCheckCode().getCode()); jsonResponse.put(JSON_OUTPUT_CER, verifyResult.getCertificateCheck().getCode()); @@ -234,13 +263,8 @@ public class JSONAPIServlet extends HttpServlet { } } - PdfAsHelper.startSignatureJson(request, response, getServletContext(), - inputDocument, connectorEnum.toString(), - position, - null, - profile, null, - null); + connectorEnum.toString(), data); JSONStartResponse jsonStartResponse = PdfAsHelper.startJsonProcess(request, response, getServletContext()); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java index 401d3e68..bf45745d 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java @@ -3,19 +3,19 @@ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria 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 @@ -23,147 +23,262 @@ ******************************************************************************/ package at.gv.egiz.pdfas.web.servlets; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egiz.pdfas.web.config.WebConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import at.gv.egiz.pdfas.api.processing.SignedDocument; import at.gv.egiz.pdfas.api.ws.PDFASVerificationResponse; +import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; import at.gv.egiz.pdfas.web.stats.StatisticEvent; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; import at.gv.egiz.pdfas.web.stats.StatisticFrontend; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; +import lombok.extern.slf4j.Slf4j; /** * Servlet implementation class PDFData */ +@Slf4j public class PDFData extends HttpServlet { - private static final long serialVersionUID = 1L; - - private static final Logger logger = LoggerFactory.getLogger(PDFData.class); - - /** - * @see HttpServlet#HttpServlet() - */ - public PDFData() { - super(); - } - - /** - * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse - * response) - */ - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - this.process(request, response); - } - - /** - * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse - * response) - */ - protected void doPost(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - this.process(request, response); - } - - protected void process(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - byte[] signedData = PdfAsHelper.getSignedPdf(request, response); - - StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request, - response); - - String plainPDFDigest = PdfAsParameterExtractor.getOrigDigest(request); - - if (signedData != null) { - - if(WebConfiguration.isKeepSignedDocument()) { - if(PdfAsHelper.isSignedDataExpired(request, response)) { - logger.info("Destroying expired signed data in session"); - request.getSession().invalidate(); - PdfAsHelper.setSessionException(request, response, - "No signed pdf document available.", null); - PdfAsHelper.gotoError(getServletContext(), request, response); - return; - } - } - - if (plainPDFDigest != null) { - String signatureDataHash = PdfAsHelper - .getSignatureDataHash(request); - if (!plainPDFDigest.equalsIgnoreCase(signatureDataHash)) { - logger.warn("Digest Hash mismatch!"); - logger.warn("Requested digest: " + plainPDFDigest); - logger.warn("Saved digest: " + signatureDataHash); - - PdfAsHelper.setSessionException(request, response, - "Signature Data digest do not match!", null); - PdfAsHelper.gotoError(getServletContext(), request, - response); - return; - } - } - response.setHeader("Content-Disposition", "inline;filename=" - + PdfAsHelper.getPDFFileName(request)); - String pdfCert = PdfAsHelper.getSignerCertificate(request); - if (pdfCert != null) { - response.setHeader("Signer-Certificate", pdfCert); - } - - if (statisticEvent != null) { - if (!statisticEvent.isLogged()) { - statisticEvent.setStatus(Status.OK); - - statisticEvent.setEndNow(); - statisticEvent.setTimestampNow(); - StatisticFrontend.getInstance().storeEvent(statisticEvent); - statisticEvent.setLogged(true); - } - } - - PDFASVerificationResponse resp = PdfAsHelper - .getPDFASVerificationResponse(request); - if (resp != null) { - response.setHeader("CertificateCheckCode", - String.valueOf(resp.getCertificateCode())); - response.setHeader("ValueCheckCode", - String.valueOf(resp.getValueCode())); - } - response.setContentType("application/pdf"); - OutputStream os = response.getOutputStream(); - os.write(signedData); - os.close(); - - // When data is collected destroy session! - if(!WebConfiguration.isKeepSignedDocument()) { - logger.debug("Destroying signed data in session : {}", request.getSession().getId()); - request.getSession().invalidate(); - } else { - logger.debug("Keeping signed data in session : {}", request.getSession().getId()); - } - } else { - logger.info("No signed pdf document available."); - PdfAsHelper.setSessionException(request, response, - "No signed pdf document available.", null); - PdfAsHelper.gotoError(getServletContext(), request, response); - } - } + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public PDFData() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + this.process(request, response); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + this.process(request, response); + } + + protected void process(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + if (PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().isEmpty()) { + log.info("No signed pdf document available."); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + + } else if (PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().size() == 1) { + buildSingleFileResult(request, response, + PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().get(0)); + + } else { + buildMultipleFileResult(request, response, PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs()); + + } + + } + + private void buildMultipleFileResult(HttpServletRequest request, HttpServletResponse response, + List<SignedDocument> signedPdfs) throws IOException, ServletException { + + final StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request,response); + + // check if some files are expired + if (WebConfiguration.isKeepSignedDocument()) { + if (signedPdfs.stream() + .filter(el -> isSignedDataExpired(el)) + .findFirst().isPresent()) { + log.info("Destroying expired signed data in session"); + request.getSession().invalidate(); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + return; + } + } + + // package files into ZIP + byte[] zippedFiles = packageSignedPdfsIntoZip(signedPdfs); + + // write static log + if (statisticEvent != null) { + if (!statisticEvent.isLogged()) { + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + } + + // build response + response.setHeader("Content-Disposition", "inline;filename=multiple_documents.zip"); + response.setContentType("application/zip"); + final OutputStream os = response.getOutputStream(); + + os.write(zippedFiles); + os.close(); + + // When data is collected destroy session! + if (!WebConfiguration.isKeepSignedDocument()) { + log.debug("Destroying signed data in session : {}", request.getSession().getId()); + request.getSession().invalidate(); + } else { + log.debug("Keeping signed data in session : {}", request.getSession().getId()); + } + + } + + private byte[] packageSignedPdfsIntoZip(List<SignedDocument> signedPdfs) throws IOException { + ByteArrayOutputStream baOut = new ByteArrayOutputStream(); + + try { + ZipOutputStream zos = new ZipOutputStream(baOut); + zos.setLevel(Deflater.BEST_COMPRESSION); + zos.setMethod(Deflater.DEFLATED); + + Iterator<SignedDocument> it = signedPdfs.iterator(); + while (it.hasNext()) { + SignedDocument entry = it.next(); + if (entry.getOutputData() != null) { + log.debug("Compressing file {}.", entry.getFileName()); + ZipEntry oze = new ZipEntry(entry.getFileName()); + zos.putNextEntry(oze); + zos.write(entry.getOutputData()); + zos.closeEntry(); + + } else { + log.warn("Ignore entry with name: {} because it's empty", entry.getFileName()); + + } + } + zos.closeEntry(); + zos.finish(); + zos.close(); + + return baOut.toByteArray(); + + } finally { + baOut.close(); + + } + + } + + private void buildSingleFileResult(HttpServletRequest request, HttpServletResponse response, SignedDocument signedFile) throws ServletException, IOException { + final byte[] signedData = signedFile.getOutputData(); + + final StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request, + response); + + final String plainPDFDigest = PdfAsParameterExtractor.getOrigDigest(request); + + if (signedData != null) { + + if (WebConfiguration.isKeepSignedDocument()) { + if (isSignedDataExpired(signedFile)) { + log.info("Destroying expired signed data in session"); + request.getSession().invalidate(); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + return; + } + } + + if (plainPDFDigest != null) { + final String signatureDataHash = PdfAsHelper + .getSignatureDataHash(request); + if (!plainPDFDigest.equalsIgnoreCase(signatureDataHash)) { + log.warn("Digest Hash mismatch!"); + log.warn("Requested digest: " + plainPDFDigest); + log.warn("Saved digest: " + signatureDataHash); + + PdfAsHelper.setSessionException(request, response, + "Signature Data digest do not match!", null); + PdfAsHelper.gotoError(getServletContext(), request, + response); + return; + } + } + response.setHeader("Content-Disposition", "inline;filename=" + + PdfAsHelper.getPDFFileName(request)); + final String pdfCert = signedFile.getSignerCertificate(); + if (pdfCert != null) { + response.setHeader("Signer-Certificate", pdfCert); + } + + if (statisticEvent != null) { + if (!statisticEvent.isLogged()) { + statisticEvent.setStatus(Status.OK); + + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + } + + final PDFASVerificationResponse resp = signedFile.getVerificationResponse(); + if (resp != null) { + response.setHeader("CertificateCheckCode", + String.valueOf(resp.getCertificateCode())); + response.setHeader("ValueCheckCode", + String.valueOf(resp.getValueCode())); + } + response.setContentType("application/pdf"); + final OutputStream os = response.getOutputStream(); + os.write(signedData); + os.close(); + + // When data is collected destroy session! + if (!WebConfiguration.isKeepSignedDocument()) { + log.debug("Destroying signed data in session : {}", request.getSession().getId()); + request.getSession().invalidate(); + } else { + log.debug("Keeping signed data in session : {}", request.getSession().getId()); + } + } else { + log.info("No signed pdf document available."); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + + } + + } + + private static boolean isSignedDataExpired(SignedDocument signedFile) { + final long now = System.currentTimeMillis(); + final long validUntil = signedFile.getSigningTimestamp() + 300000; + + log.debug("Checking signed data valid until {} now is {}", validUntil, now); + return validUntil < now; + + } + } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java index 7262586d..47469eb2 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java @@ -26,32 +26,31 @@ package at.gv.egiz.pdfas.web.servlets; import java.io.IOException; import java.net.URL; import java.net.URLEncoder; +import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.swing.text.html.HTML; import org.apache.commons.lang3.StringEscapeUtils; -import org.codehaus.stax2.io.EscapingWriterFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.api.processing.SignedDocument; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.web.config.WebConfiguration; +import at.gv.egiz.pdfas.web.exception.PdfAsStoreException; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.UrlParameterExtractor; +import at.gv.egiz.pdfas.web.store.RequestStore; +import lombok.extern.slf4j.Slf4j; /** * Servlet implementation class ProvidePDF */ +@Slf4j public class ProvidePDFServlet extends HttpServlet { private static final long serialVersionUID = 1L; - - private static final Logger logger = LoggerFactory - .getLogger(ProvidePDFServlet.class); private static final String PDF_DATA_URL = "##PDFDATAURL##"; @@ -88,7 +87,7 @@ public class ProvidePDFServlet extends HttpServlet { if (invokeURL == null || !WebConfiguration.isProvidePdfURLinWhitelist(invokeURL)) { if(invokeURL != null) { - logger.warn(invokeURL + " is not allowed by whitelist"); + log.warn(invokeURL + " is not allowed by whitelist"); } if (PdfAsHelper.getResponseMode(request, response).equals(PdfAsHelper.PDF_RESPONSE_MODES.htmlform)) { @@ -100,60 +99,126 @@ public class ProvidePDFServlet extends HttpServlet { response.getWriter().close(); } else { - logger.debug("PDFResult directMode: Forward to PDFData Servlet directly"); + log.debug("PDFResult directMode: Forward to PDFData Servlet directly"); RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/PDFData"); dispatcher.forward(request, response); } - } else { - // Redirect Browser - String template = PdfAsHelper.getInvokeRedirectTemplateSL(); - - URL url = new URL(invokeURL); - int p=url.getPort(); - //no port, but http or https --> use default port - if((url.getProtocol().equalsIgnoreCase("https") || url.getProtocol().equalsIgnoreCase("http")) && p == -1){ - p=url.getDefaultPort(); - } - String invokeUrlProcessed = url.getProtocol() + "://" + // "http" + ":// - url.getHost() + // "myhost" - ":" + // ":" - p + // "8080" - url.getPath(); - - template = template.replace("##INVOKE_URL##", invokeUrlProcessed); - - String extraParams = UrlParameterExtractor.buildParameterFormString(url); - template = template.replace("##ADD_PARAMS##", extraParams); - - byte[] signedData = PdfAsHelper.getSignedPdf(request, response); - if (signedData != null) { - template = template.replace("##PDFLENGTH##", - String.valueOf(signedData.length)); - } else { - throw new PdfAsException("No Signature data available"); - } - - String target = PdfAsHelper.getInvokeTarget(request, response); - - if(target == null) { - target = "_self"; - } - - template = template.replace("##TARGET##", StringEscapeUtils.escapeHtml4(target)); - - template = template.replace("##PDFURL##", - URLEncoder.encode(PdfAsHelper.generatePdfURL(request, response), - "UTF-8")); - response.setContentType("text/html"); - response.getWriter().write(template); - response.getWriter().close(); + } else { + List<SignedDocument> signedPdfs = PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs(); + + if (signedPdfs.isEmpty()) { + log.info("No signed pdf document available."); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + + } else if (signedPdfs.size() == 1) { + provideSingleFile(request, response, signedPdfs.get(0), invokeURL); + + + } else { + provideTokenToGetMultipleFiles(request, response, invokeURL); + + } } + } catch (Exception e) { - PdfAsHelper.setSessionException(request, response, e.getMessage(), - e); + PdfAsHelper.setSessionException(request, response, e.getMessage(), e); PdfAsHelper.gotoError(getServletContext(), request, response); + } } + + private void provideTokenToGetMultipleFiles(HttpServletRequest request, HttpServletResponse response, + String invokeURL) throws IOException, PdfAsStoreException { + + String template = PdfAsHelper.getInvokeRedirectTemplateMoreFiles(); + + URL url = new URL(invokeURL); + int p=url.getPort(); + //no port, but http or https --> use default port + if((url.getProtocol().equalsIgnoreCase("https") || url.getProtocol().equalsIgnoreCase("http")) && p == -1){ + p=url.getDefaultPort(); + } + String invokeUrlProcessed = url.getProtocol() + "://" + // "http" + ":// + url.getHost() + // "myhost" + ":" + // ":" + p + // "8080" + url.getPath(); + + template = template.replace("##INVOKE_URL##", invokeUrlProcessed); + + String extraParams = UrlParameterExtractor.buildParameterFormString(url); + template = template.replace("##ADD_PARAMS##", extraParams); + + + String target = PdfAsHelper.getInvokeTarget(request, response); + if(target == null) { + target = "_self"; + + } + template = template.replace("##TARGET##", StringEscapeUtils.escapeHtml4(target)); + + String accessToken = RequestStore.getInstance().createNewResponseEntry(PdfAsHelper.getPdfSigningResponse(request)); + template = template.replace("##RESPONSETOKEN##", accessToken); + + response.setContentType("text/html"); + response.getWriter().write(template); + response.getWriter().close(); + + + + + + } + + private void provideSingleFile(HttpServletRequest request, HttpServletResponse response, SignedDocument signedDocument, String invokeURL) throws IOException, PdfAsException { + // Redirect Browser + String template = PdfAsHelper.getInvokeRedirectTemplateSL(); + + URL url = new URL(invokeURL); + int p=url.getPort(); + //no port, but http or https --> use default port + if((url.getProtocol().equalsIgnoreCase("https") || url.getProtocol().equalsIgnoreCase("http")) && p == -1){ + p=url.getDefaultPort(); + } + String invokeUrlProcessed = url.getProtocol() + "://" + // "http" + ":// + url.getHost() + // "myhost" + ":" + // ":" + p + // "8080" + url.getPath(); + + template = template.replace("##INVOKE_URL##", invokeUrlProcessed); + + String extraParams = UrlParameterExtractor.buildParameterFormString(url); + template = template.replace("##ADD_PARAMS##", extraParams); + + + //TODO: implement use-case if result contains more than one file + byte[] signedData = PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().get(0).getOutputData(); + if (signedData != null) { + template = template.replace("##PDFLENGTH##", + String.valueOf(signedData.length)); + } else { + throw new PdfAsException("No Signature data available"); + } + + String target = PdfAsHelper.getInvokeTarget(request, response); + + if(target == null) { + target = "_self"; + } + + template = template.replace("##TARGET##", StringEscapeUtils.escapeHtml4(target)); + + template = template.replace("##PDFURL##", + URLEncoder.encode(PdfAsHelper.generatePdfURL(request, response), + "UTF-8")); + response.setContentType("text/html"); + response.getWriter().write(template); + response.getWriter().close(); + + } } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java index 664dd9b3..d7a3d3c6 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java @@ -24,18 +24,14 @@ package at.gv.egiz.pdfas.web.servlets; import java.io.IOException; -import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; -import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; import at.gv.egiz.pdfas.web.config.WebConfiguration; @@ -45,15 +41,14 @@ import at.gv.egiz.pdfas.web.helper.DigestHelper; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.stats.StatisticEvent; import at.gv.egiz.pdfas.web.store.RequestStore; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class UIEntryPointServlet extends HttpServlet { private static final long serialVersionUID = 1L; public static final String REQUEST_ID_PARAM = "reqId"; - private static final Logger logger = LoggerFactory - .getLogger(UIEntryPointServlet.class); - public UIEntryPointServlet() { } @@ -72,13 +67,16 @@ public class UIEntryPointServlet extends HttpServlet { protected void doProcess(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { + // invalidate existing http sessions at first + req.getSession().invalidate(); + String storeId = req.getParameter(REQUEST_ID_PARAM); if (storeId == null) { throw new PdfAsStoreException("Wrong Parameters"); } - PDFASSignRequest pdfAsRequest = RequestStore.getInstance() + PdfasSignRequest pdfAsRequest = RequestStore.getInstance() .fetchStoreEntry(storeId); if (pdfAsRequest == null) { @@ -91,16 +89,15 @@ public class UIEntryPointServlet extends HttpServlet { PdfAsHelper.setStatisticEvent(req, resp, statisticEvent); - Connector connector = pdfAsRequest.getParameters().getConnector(); + Connector connector = pdfAsRequest.getCoreParams().getConnector(); - String invokeUrl = pdfAsRequest.getParameters().getInvokeURL(); + String invokeUrl = pdfAsRequest.getCoreParams().getInvokeUrl(); PdfAsHelper.setInvokeURL(req, resp, invokeUrl); - String invokeTarget = pdfAsRequest.getParameters() - .getInvokeTarget(); + String invokeTarget = pdfAsRequest.getCoreParams().getInvokeTarget(); PdfAsHelper.setInvokeTarget(req, resp, invokeTarget); - String errorUrl = pdfAsRequest.getParameters().getInvokeErrorURL(); + String errorUrl = pdfAsRequest.getCoreParams().getInvokeErrorUrl(); PdfAsHelper.setErrorURL(req, resp, errorUrl); SignatureVerificationLevel lvl = SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION; @@ -116,17 +113,16 @@ public class UIEntryPointServlet extends HttpServlet { } PdfAsHelper.setVerificationLevel(req, lvl); - if (pdfAsRequest.getInputData() == null) { + if (pdfAsRequest.hasNext() && pdfAsRequest.getInput().get(0).getInputData() == null) { throw new PdfAsException("No Signature data available"); } - String pdfDataHash = DigestHelper.getHexEncodedHash(pdfAsRequest - .getInputData()); + String pdfDataHash = DigestHelper.getHexEncodedHash(pdfAsRequest.getInput().get(0).getInputData()); PdfAsHelper.setSignatureDataHash(req, pdfDataHash); - logger.debug("Storing signatures data hash: " + pdfDataHash); + log.debug("Storing signatures data hash: " + pdfDataHash); - logger.debug("Starting signature creation with: " + connector); + log.debug("Starting signature creation with: " + connector); // IPlainSigner signer; if (connector.equals(Connector.BKU) @@ -163,26 +159,8 @@ public class UIEntryPointServlet extends HttpServlet { } } - Map<String, String> map = null; - if (pdfAsRequest.getParameters().getPreprocessor() != null) { - map = pdfAsRequest.getParameters().getPreprocessor() - .getMap(); - } + PdfAsHelper.startSignature(req, resp, getServletContext(), connector.toString(), pdfAsRequest); - Map<String, String> overwrite = null; - if (pdfAsRequest.getParameters().getOverrides() != null) { - overwrite = pdfAsRequest.getParameters().getOverrides() - .getMap(); - } - //TODO alex - Map<String, String> dynamicSignatureBlockArguments = pdfAsRequest.getSignatureBlockParameters(); - - PdfAsHelper.startSignature(req, resp, getServletContext(), - pdfAsRequest.getInputData(), connector.toString(), - pdfAsRequest.getParameters().getPosition(), - pdfAsRequest.getParameters().getTransactionId(), - pdfAsRequest.getParameters().getProfile(), map, - overwrite, dynamicSignatureBlockArguments); } else { throw new PdfAsWebException("Invalid connector (" + Connector.BKU + " | " + Connector.ONLINEBKU + " | " @@ -190,7 +168,7 @@ public class UIEntryPointServlet extends HttpServlet { } } catch (Throwable e) { - logger.warn("Failed to process Request: ", e); + log.warn("Failed to process Request: ", e); PdfAsHelper.setSessionException(req, resp, e.getMessage(), e); PdfAsHelper.gotoError(getServletContext(), req, resp); } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java index bc5f2e2d..003a4a73 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java @@ -50,10 +50,10 @@ import at.gv.egiz.pdfas.web.helper.RemotePDFFetcher; import at.gv.egiz.pdfas.web.helper.VerifyEncoder; import at.gv.egiz.pdfas.web.helper.VerifyResultEncoder; import at.gv.egiz.pdfas.web.stats.StatisticEvent; -import at.gv.egiz.pdfas.web.stats.StatisticFrontend; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; /** * Servlet implementation class VerifyServlet @@ -84,6 +84,9 @@ public class VerifyServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // invalidate existing http sessions at first + request.getSession().invalidate(); + logger.info("Get verify request"); String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); @@ -138,6 +141,9 @@ public class VerifyServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // invalidate existing http sessions at first + request.getSession().invalidate(); + logger.info("Post verify request"); String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java index f07a36ce..643d3ea0 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java @@ -23,11 +23,16 @@ ******************************************************************************/ package at.gv.egiz.pdfas.web.store; -import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; import at.gv.egiz.pdfas.web.stats.StatisticEvent; public interface IRequestStore { public StatisticEvent fetchStatisticEntry(String id); - public String createNewStoreEntry(PDFASSignRequest request, StatisticEvent event); - public PDFASSignRequest fetchStoreEntry(String id); + public String createNewStoreEntry(PdfasSignRequest request, StatisticEvent event); + public PdfasSignRequest fetchStoreEntry(String id); + + public String createNewResponseEntry(PdfasSignResponse response); + public PdfasSignResponse fetchStoreResponse(String id); + } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java index f712a894..6ab58ce0 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java @@ -23,26 +23,35 @@ ******************************************************************************/ package at.gv.egiz.pdfas.web.store; -import java.util.HashMap; +import java.util.Map; import java.util.UUID; -import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; +import org.apache.commons.collections4.map.PassiveExpiringMap; + +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; import at.gv.egiz.pdfas.web.stats.StatisticEvent; public class InMemoryRequestStore implements IRequestStore { + // expires after 10 minutes + private static final long DEFAULT_EXPIRATION = 10 * 60 * 1000; + + private Map<String, PdfasSignRequest> reqStore = new PassiveExpiringMap<>(DEFAULT_EXPIRATION); + private Map<String, PdfasSignResponse> respStore = new PassiveExpiringMap<>(DEFAULT_EXPIRATION); + private Map<String, StatisticEvent> statEvents = new PassiveExpiringMap<>(DEFAULT_EXPIRATION); + public InMemoryRequestStore() { + } - private HashMap<String, PDFASSignRequest> store = new HashMap<String, PDFASSignRequest>(); - private HashMap<String, StatisticEvent> statEvents = new HashMap<String, StatisticEvent>(); - - public String createNewStoreEntry(PDFASSignRequest request, StatisticEvent event) { + public String createNewStoreEntry(PdfasSignRequest request, StatisticEvent event) { UUID id = UUID.randomUUID(); String sid = id.toString(); - this.store.put(sid, request); + this.reqStore.put(sid, request); this.statEvents.put(sid, event); return sid; + } public StatisticEvent fetchStatisticEntry(String id) { @@ -50,17 +59,41 @@ public class InMemoryRequestStore implements IRequestStore { StatisticEvent event = statEvents.get(id); statEvents.remove(id); return event; + } + return null; } - public PDFASSignRequest fetchStoreEntry(String id) { - if(store.containsKey(id)) { - PDFASSignRequest request = store.get(id); - store.remove(id); + public PdfasSignRequest fetchStoreEntry(String id) { + if(reqStore.containsKey(id)) { + PdfasSignRequest request = reqStore.get(id); + reqStore.remove(id); return request; + } + return null; } + @Override + public String createNewResponseEntry(PdfasSignResponse response) { + String sid = UUID.randomUUID().toString(); + this.respStore.put(sid, response); + return sid; + + } + + @Override + public PdfasSignResponse fetchStoreResponse(String id) { + if (respStore.containsKey(id)) { + PdfasSignResponse response = respStore.get(id); + respStore.remove(id); + return response; + + } + + return null; + } + } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java index 531abdf1..2c248059 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java @@ -3,19 +3,19 @@ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria 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 @@ -26,20 +26,29 @@ package at.gv.egiz.pdfas.web.ws; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.jws.WebService; import javax.xml.ws.WebServiceException; import javax.xml.ws.soap.MTOM; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.commons.lang3.StringUtils; +import at.gv.egiz.pdfas.api.processing.CoreSignParams; +import at.gv.egiz.pdfas.api.processing.DocumentToSign; +import at.gv.egiz.pdfas.api.processing.PdfasSignRequest; +import at.gv.egiz.pdfas.api.processing.PdfasSignResponse; +import at.gv.egiz.pdfas.api.processing.SignedDocument; import at.gv.egiz.pdfas.api.ws.PDFASBulkSignRequest; import at.gv.egiz.pdfas.api.ws.PDFASBulkSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector; import at.gv.egiz.pdfas.api.ws.PDFASSignRequest; import at.gv.egiz.pdfas.api.ws.PDFASSignResponse; import at.gv.egiz.pdfas.api.ws.PDFASSigning; +import at.gv.egiz.pdfas.api.ws.PdfasGetMultipleRequest; +import at.gv.egiz.pdfas.api.ws.PdfasSignMultipleRequest; +import at.gv.egiz.pdfas.api.ws.PdfasSignMultipleResponse; +import at.gv.egiz.pdfas.api.ws.PdfasSignedDocument; import at.gv.egiz.pdfas.api.ws.VerificationLevel; import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; @@ -53,188 +62,460 @@ import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; import at.gv.egiz.pdfas.web.stats.StatisticFrontend; import at.gv.egiz.pdfas.web.store.RequestStore; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +@Slf4j @MTOM @WebService(endpointInterface = "at.gv.egiz.pdfas.api.ws.PDFASSigning") public class PDFASSigningImpl implements PDFASSigning { - private static final Logger logger = LoggerFactory - .getLogger(PDFASSigningImpl.class); - - /* - * public byte[] signPDFDokument(byte[] inputDocument, PDFASSignParameters - * parameters) { checkSoapSignEnabled(); try { return - * PdfAsHelper.synchornousServerSignature(inputDocument, parameters); } - * catch (Throwable e) { logger.error("Server Signature failed.", e); if - * (WebConfiguration.isShowErrorDetails()) { throw new - * WebServiceException("Server Signature failed.", e); } else { throw new - * WebServiceException("Server Signature failed."); } } } - */ - - public PDFASSignResponse signPDFDokument(PDFASSignRequest request) { - logger.debug("Starting SOAP Sign Request"); - checkSoapSignEnabled(); - if (request == null) { - logger.warn("SOAP Sign Request is null!"); - return null; - } - - StatisticEvent statisticEvent = new StatisticEvent(); - statisticEvent.setSource(Source.SOAP); - statisticEvent.setOperation(Operation.SIGN); - statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); - statisticEvent.setStartNow(); - PDFASSignResponse response = new PDFASSignResponse(); - try { - if(request.getParameters().getConnector() == null) { - throw new WebServiceException( - "Invalid connector value!"); - } - - statisticEvent.setFilesize(request.getInputData().length); - statisticEvent.setProfileId(request.getParameters().getProfile()); - statisticEvent.setDevice(request.getParameters().getConnector().toString()); - - Map<String, String> preProcessor = null; - if(request.getParameters().getPreprocessor() != null) { - preProcessor = request.getParameters().getPreprocessor().getMap(); - } - - if (request.getParameters().getConnector().equals(Connector.MOA) - || request.getParameters().getConnector() - .equals(Connector.JKS)) { - // Plain server based signatures!! - response = PdfAsHelper.synchronousServerSignature( - request.getInputData(), request.getParameters(), request.getSignatureBlockParameters()); - - - VerifyResult verifyResult = null; - if (request.getVerificationLevel() != null && - request.getVerificationLevel().equals( - VerificationLevel.FULL_CERT_PATH)) { - List<VerifyResult> verResults = PdfAsHelper - .synchronousVerify( - response.getSignedPDF(), - -1, - SignatureVerificationLevel.FULL_VERIFICATION, - preProcessor); - - if (verResults.size() < 1) { - throw new WebServiceException( - "Document verification failed! " + verResults.size()); - } - verifyResult = verResults.get(verResults.size() - 1); - } else { - List<VerifyResult> verResults = PdfAsHelper - .synchronousVerify( - response.getSignedPDF(), - -1, - SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION, - preProcessor); - - if (verResults.size() < 1) { - throw new WebServiceException( - "Document verification failed! " + verResults.size()); - } - verifyResult = verResults.get(verResults.size() - 1); - } - - if(verifyResult.getValueCheckCode().getCode() == 0) { - statisticEvent.setStatus(Status.OK); - statisticEvent.setEndNow(); - statisticEvent.setTimestampNow(); - StatisticFrontend.getInstance().storeEvent(statisticEvent); - statisticEvent.setLogged(true); - } else { - statisticEvent.setStatus(Status.ERROR); - statisticEvent.setErrorCode(verifyResult.getValueCheckCode().getCode()); - statisticEvent.setEndNow(); - statisticEvent.setTimestampNow(); - StatisticFrontend.getInstance().storeEvent(statisticEvent); - statisticEvent.setLogged(true); - } - - response.getVerificationResponse().setCertificateCode( - verifyResult.getCertificateCheck().getCode()); - response.getVerificationResponse().setValueCode( - verifyResult.getValueCheckCode().getCode()); - - } else { - // Signatures with user interaction!! - String id = RequestStore.getInstance().createNewStoreEntry( - request, statisticEvent); - - if (id == null) { - throw new WebServiceException("Failed to store request"); - } - - String userEntryURL = PdfAsHelper.generateUserEntryURL(id); - - logger.debug("Generated request store: " + id); - logger.debug("Generated UI URL: " + userEntryURL); - - if (userEntryURL == null) { - throw new WebServiceException( - "Failed to generate User Entry URL"); - } - - response.setRedirectUrl(userEntryURL); - } - } catch (Throwable e) { - - statisticEvent.setStatus(Status.ERROR); - statisticEvent.setException(e); - if(e instanceof PDFASError) { - statisticEvent.setErrorCode(((PDFASError)e).getCode()); - } - statisticEvent.setEndNow(); - statisticEvent.setTimestampNow(); - StatisticFrontend.getInstance().storeEvent(statisticEvent); - statisticEvent.setLogged(true); - - logger.warn("Error in Soap Service", e); - if (e.getCause() != null) { - response.setError(e.getCause().getMessage()); - } else { - response.setError(e.getMessage()); - } - } finally { - logger.debug("Done SOAP Sign Request"); - } - response.setRequestID(request.getRequestID()); - return response; - } - - public PDFASBulkSignResponse signPDFDokument(PDFASBulkSignRequest request) { - logger.debug("Starting SOAP BulkSign Request"); - checkSoapSignEnabled(); - List<PDFASSignResponse> responses = new ArrayList<PDFASSignResponse>(); - if (request.getSignRequests() != null) { - for (int i = 0; i < request.getSignRequests().size(); i++) { - PDFASSignResponse response = signPDFDokument(request - .getSignRequests().get(i)); - if (response != null) { - responses.add(response); - } - } - PDFASBulkSignResponse response = new PDFASBulkSignResponse(); - response.setSignResponses(responses); - logger.debug("Done SOAP Sign Request"); - return response; - } - logger.warn("Server Signature failed. [PDFASBulkSignRequest is NULL]"); - - if (WebConfiguration.isShowErrorDetails()) { - throw new WebServiceException("PDFASBulkSignRequest is NULL"); - } else { - throw new WebServiceException("Server Signature failed."); - } - } - - private void checkSoapSignEnabled() { - if (!WebConfiguration.getSoapSignEnabled()) { - throw new WebServiceException("Service disabled!"); - } - } + /* + * public byte[] signPDFDokument(byte[] inputDocument, PDFASSignParameters + * parameters) { checkSoapSignEnabled(); try { return + * PdfAsHelper.synchornousServerSignature(inputDocument, parameters); } catch + * (Throwable e) { logger.error("Server Signature failed.", e); if + * (WebConfiguration.isShowErrorDetails()) { throw new + * WebServiceException("Server Signature failed.", e); } else { throw new + * WebServiceException("Server Signature failed."); } } } + */ + @Override + public PDFASSignResponse signPDFDokument(PDFASSignRequest request) { + log.debug("Starting SOAP Sign Request"); + checkSoapSignEnabled(); + if (request == null) { + log.warn("SOAP Sign Request is null!"); + return null; + } + + // map request into internal data-structure + final PdfasSignRequest internalReq = buildOperationRequest(request); + + final StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setSource(Source.SOAP); + statisticEvent.setOperation(Operation.SIGN); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + statisticEvent.setProfileId(request.getParameters().getProfile()); + statisticEvent.setDevice(request.getParameters().getConnector().toString()); + statisticEvent.setStartNow(); + + PDFASSignResponse response = new PDFASSignResponse(); + try { + if (request.getParameters().getConnector() == null) { + throw new WebServiceException( + "Invalid connector value!"); + } + + if (request.getParameters().getConnector().equals(Connector.MOA) + || request.getParameters().getConnector() + .equals(Connector.JKS)) { + + // perform technical signing process + final PdfasSignResponse internalResp = PdfAsHelper.synchronousServerSignature(internalReq); + + // validate signatures + internalResp.getSignedPdfs().forEach(el -> validatePdfSignature(el, internalReq, statisticEvent)); + + // must be done later, because we should verify signed documents before + response = buildResponseFromInternalResult(internalResp, internalReq.getRequestID()); + + } else { + // Signatures with user interaction!! + final String id = RequestStore.getInstance().createNewStoreEntry(internalReq, statisticEvent); + + if (id == null) { + throw new WebServiceException("Failed to store request"); + } + + final String userEntryURL = PdfAsHelper.generateUserEntryURL(id); + + log.debug("Generated request store: " + id); + log.debug("Generated UI URL: " + userEntryURL); + + if (userEntryURL == null) { + throw new WebServiceException( + "Failed to generate User Entry URL"); + } + + response.setRedirectUrl(userEntryURL); + } + } catch (final Throwable e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if (e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError) e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + + log.warn("Error in Soap Service", e); + if (e.getCause() != null) { + response.setError(e.getCause().getMessage()); + + } else { + response.setError(e.getMessage()); + + } + + } finally { + log.debug("Done SOAP Sign Request"); + + } + + response.setRequestID(request.getRequestID()); + return response; + + } + + @Override + public PDFASBulkSignResponse signPDFDokument(PDFASBulkSignRequest request) { + log.debug("Starting SOAP BulkSign Request"); + checkSoapSignEnabled(); + final List<PDFASSignResponse> responses = new ArrayList<>(); + if (request.getSignRequests() != null) { + for (int i = 0; i < request.getSignRequests().size(); i++) { + final PDFASSignResponse response = signPDFDokument(request + .getSignRequests().get(i)); + if (response != null) { + responses.add(response); + } + } + final PDFASBulkSignResponse response = new PDFASBulkSignResponse(); + response.setSignResponses(responses); + log.debug("Done SOAP Sign Request"); + return response; + } + log.warn("Server Signature failed. [PDFASBulkSignRequest is NULL]"); + + if (WebConfiguration.isShowErrorDetails()) { + throw new WebServiceException("PDFASBulkSignRequest is NULL"); + } else { + throw new WebServiceException("Server Signature failed."); + } + } + + @Override + public PdfasSignMultipleResponse signPDFDokument(PdfasSignMultipleRequest request) { + + log.debug("Starting SOAP Bulk-Sign Request"); + checkSoapSignEnabled(); + if (request == null) { + log.warn("SOAP Sign Request is null!"); + return null; + } + + // map request into internal data-structure + final PdfasSignRequest internalReq = buildOperationRequest(request); + + final StatisticEvent statisticEvent = new StatisticEvent(); + statisticEvent.setSource(Source.SOAP); + statisticEvent.setOperation(Operation.SIGNBULK); + statisticEvent.setUserAgent(UserAgentFilter.getUserAgent()); + statisticEvent.setDevice(internalReq.getCoreParams().getConnector().toString()); + statisticEvent.setStartNow(); + + PdfasSignMultipleResponse response = new PdfasSignMultipleResponse(); + try { + if (internalReq.getCoreParams().getConnector() == null) { + throw new WebServiceException( + "Invalid connector value!"); + } + + if (internalReq.getCoreParams().getConnector().equals(Connector.MOA) + || internalReq.getCoreParams().getConnector() + .equals(Connector.JKS)) { + + // perform technical signing process + final PdfasSignResponse internalResp = PdfAsHelper.synchronousServerSignature(internalReq); + + // validate signatures + internalResp.getSignedPdfs().forEach(el -> validatePdfSignature(el, internalReq, statisticEvent)); + + // must be done later, because we should verify signed documents before + response = buildMultiResponseFromInternalResult(internalResp, internalReq.getRequestID(), internalReq + .getCoreParams().getTransactionId()); + + } else { + // Signatures with user interaction!! + final String id = RequestStore.getInstance().createNewStoreEntry(internalReq, statisticEvent); + + if (id == null) { + throw new WebServiceException("Failed to store request"); + } + + final String userEntryURL = PdfAsHelper.generateUserEntryURL(id); + + log.debug("Generated request store: " + id); + log.debug("Generated UI URL: " + userEntryURL); + + if (userEntryURL == null) { + throw new WebServiceException( + "Failed to generate User Entry URL"); + } + + response.setRedirectUrl(userEntryURL); + response.setRequestID(request.getRequestID()); + + } + } catch (final Throwable e) { + + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setException(e); + if (e instanceof PDFASError) { + statisticEvent.setErrorCode(((PDFASError) e).getCode()); + } + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + + log.warn("Error in Soap Service", e); + if (e.getCause() != null) { + response.setError(e.getCause().getMessage()); + + } else { + response.setError(e.getMessage()); + + } + + } finally { + log.debug("Done SOAP Sign Request"); + + } + + return response; + + } + + @Override + public PdfasSignMultipleResponse getSignedDokument(PdfasGetMultipleRequest request) { + log.debug("Starting SOAP Get-Signed Request"); + checkSoapSignEnabled(); + if (request == null) { + log.warn("SOAP Get-Signed Request is null!"); + return null; + + } + + final PdfasSignMultipleResponse response = new PdfasSignMultipleResponse(); + + try { + if (StringUtils.isEmpty(request.getToken())) { + log.warn("SOAP Get-Signed Request contains NO token"); + throw new WebServiceException("SOAP Get-Signed Request contains NO token"); + + } + + final PdfasSignResponse result = RequestStore.getInstance().fetchStoreResponse(request.getToken()); + if (result != null) { + response.setRequestID(result.getRequestId()); + response.setTransactionId(result.getTransactionId()); + response.setOutput(result.getSignedPdfs().stream() + .map(el -> { + PdfasSignedDocument out = new PdfasSignedDocument(); + out.setFileName(el.getFileName()); + out.setOutputData(el.getOutputData()); + out.setVerificationResponse(el.getVerificationResponse()); + return out; + + }) + .collect(Collectors.toList())); + + } else { + log.warn("SOAP Get-Signed Request token is unknown or expired"); + throw new WebServiceException("SOAP Get-Signed Request token is unknown or expired"); + + } + + } catch (final Throwable e) { + + log.warn("Error in Soap Service", e); + if (e.getCause() != null) { + response.setError(e.getCause().getMessage()); + + } else { + response.setError(e.getMessage()); + + } + + } finally { + log.debug("Done SOAP Sign Request"); + + } + + return response; + + } + + private PdfasSignRequest buildOperationRequest(PdfasSignMultipleRequest request) { + final PdfasSignRequest data = new PdfasSignRequest(); + data.setRequestID(request.getRequestID()); + data.setVerificationLevel(request.getVerificationLevel()); + + final CoreSignParams coreParams = new CoreSignParams(); + coreParams.setSignatureBlockParameters(request.getSignatureBlockParameters()); + coreParams.setConnector(request.getConnector()); + coreParams.setKeyIdentifier(request.getKeyIdentifier()); + coreParams.setOverrides( + request.getOverrides() != null ? request.getOverrides().getMap() : null); + coreParams.setPreprocessor( + request.getPreprocessor() != null ? request.getPreprocessor().getMap() : null); + coreParams.setInvokeErrorUrl(request.getInvokeErrorUrl()); + coreParams.setInvokeTarget(request.getInvokeTarget()); + coreParams.setInvokeUrl(request.getInvokeUrl()); + coreParams.setTransactionId(request.getTransactionId()); + data.setCoreParams(coreParams); + + request.getInput().forEach(el -> { + final DocumentToSign document = new DocumentToSign(); + document.setInputData(el.getInputData()); + document.setPosition(el.getPosition()); + document.setProfile(el.getProfile()); + document.setQrCodeContent(el.getQrCodeContent()); + document.setFileName(el.getFileName()); + data.addDocumentToSign(document); + + }); + + return data; + + } + + private PdfasSignMultipleResponse buildMultiResponseFromInternalResult(PdfasSignResponse internalResp, + String reqId, String transactionId) { + final PdfasSignMultipleResponse resp = new PdfasSignMultipleResponse(); + resp.setRequestID(reqId); + resp.setTransactionId(transactionId); + resp.setOutput( + internalResp.getSignedPdfs().stream() + .map(el -> { + final PdfasSignedDocument out = new PdfasSignedDocument(); + out.setFileName(el.getFileName()); + out.setOutputData(el.getOutputData()); + out.setVerificationResponse(el.getVerificationResponse()); + return out; + }) + .collect(Collectors.toList())); + + return resp; + + } + + private void checkSoapSignEnabled() { + if (!WebConfiguration.getSoapSignEnabled()) { + throw new WebServiceException("Service disabled!"); + } + } + + private PdfasSignRequest buildOperationRequest(PDFASSignRequest request) { + final PdfasSignRequest data = new PdfasSignRequest(); + data.setRequestID(request.getRequestID()); + data.setVerificationLevel(request.getVerificationLevel()); + + final CoreSignParams coreParams = new CoreSignParams(); + coreParams.setSignatureBlockParameters(request.getSignatureBlockParameters()); + coreParams.setConnector(request.getParameters().getConnector()); + coreParams.setKeyIdentifier(request.getParameters().getKeyIdentifier()); + coreParams.setOverrides( + request.getParameters().getOverrides() != null ? request.getParameters().getOverrides().getMap() + : null); + coreParams.setPreprocessor( + request.getParameters().getPreprocessor() != null ? request.getParameters().getPreprocessor().getMap() + : null); + coreParams.setInvokeErrorUrl(request.getParameters().getInvokeErrorURL()); + coreParams.setInvokeTarget(request.getParameters().getInvokeTarget()); + coreParams.setInvokeUrl(request.getParameters().getInvokeURL()); + coreParams.setTransactionId(request.getParameters().getTransactionId()); + data.setCoreParams(coreParams); + + final DocumentToSign document = new DocumentToSign(); + document.setInputData(request.getInputData()); + document.setPosition(request.getParameters().getPosition()); + document.setProfile(request.getParameters().getProfile()); + document.setQrCodeContent(request.getParameters().getQRCodeContent()); + data.addDocumentToSign(document); + + return data; + + } + + private PDFASSignResponse buildResponseFromInternalResult(PdfasSignResponse internalResp, String reqId) { + final PDFASSignResponse resp = new PDFASSignResponse(); + resp.setRequestID(reqId); + resp.setSignedPDF(internalResp.getSignedPdfs().get(0).getOutputData()); + resp.setVerificationResponse(internalResp.getSignedPdfs().get(0).getVerificationResponse()); + return resp; + + } + + @SneakyThrows + private void validatePdfSignature(SignedDocument el, PdfasSignRequest request, + StatisticEvent statisticEvent) { + + Map<String, String> preProcessor = null; + if (request.getCoreParams().getPreprocessor() != null) { + preProcessor = request.getCoreParams().getPreprocessor(); + + } + + VerifyResult verifyResult = null; + if (request.getVerificationLevel() != null && + request.getVerificationLevel().equals( + VerificationLevel.FULL_CERT_PATH)) { + final List<VerifyResult> verResults = PdfAsHelper + .synchronousVerify( + el.getOutputData(), + -1, + SignatureVerificationLevel.FULL_VERIFICATION, + preProcessor); + + if (verResults.size() < 1) { + throw new WebServiceException( + "Document verification failed! " + verResults.size()); + } + verifyResult = verResults.get(verResults.size() - 1); + } else { + final List<VerifyResult> verResults = PdfAsHelper + .synchronousVerify( + el.getOutputData(), + -1, + SignatureVerificationLevel.INTEGRITY_ONLY_VERIFICATION, + preProcessor); + + if (verResults.size() < 1) { + throw new WebServiceException( + "Document verification failed! " + verResults.size()); + } + + verifyResult = verResults.get(verResults.size() - 1); + + } + + if (verifyResult.getValueCheckCode().getCode() == 0) { + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + statisticEvent.setFilesize(el.getOutputData().length); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } else { + statisticEvent.setStatus(Status.ERROR); + statisticEvent.setErrorCode(verifyResult.getValueCheckCode().getCode()); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + statisticEvent.setFilesize(el.getOutputData().length); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + + el.getVerificationResponse().setCertificateCode( + verifyResult.getCertificateCheck().getCode()); + el.getVerificationResponse().setValueCode( + verifyResult.getValueCheckCode().getCode()); + + } } diff --git a/pdf-as-web/src/main/resources/template_invoke_redirect_more_files.html b/pdf-as-web/src/main/resources/template_invoke_redirect_more_files.html new file mode 100644 index 00000000..9ad17ea2 --- /dev/null +++ b/pdf-as-web/src/main/resources/template_invoke_redirect_more_files.html @@ -0,0 +1,56 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="de"> +<head> +<title></title> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<style type="text/css"> +div.frameT { + width: 100%; + padding: 0; + display: table; + height: 100%; + position: absolute; + top: 0; + left: 0; + margin: 0; +} + +div.frameTC { + padding: 0; + vertical-align: middle; + display: table-cell; + margin: 0; +} + +div.content { + width: 600px; + background-color: #fff; + margin: 0 auto; + text-align: left; + padding: 10px; +} +</style> +<script language="javascript" type="text/javascript"> + function onAnmeldeSubmit() { + document.CustomizedForm.submit(); + document.CustomizedForm.Senden.disabled=true; + document.CustomizedForm.Senden.hidden = "hidden"; + } + </script> +</head> +<body onload="onAnmeldeSubmit()"> + <div class="frameT"> + <div class="frameTC"> + <div class="content"> + <form name="CustomizedForm" action="##INVOKE_URL##" method="GET" target="##TARGET##"> + <input type="submit" value="Weiter" + name="Senden"> + ##ADD_PARAMS## + <input type="hidden" name="token" value="##RESPONSETOKEN##"> + </form> + </div> + </div> + </div> + +</body> +</html> |