From 3400771c9f6c2d558e6f2478630856738a5f1e12 Mon Sep 17 00:00:00 2001 From: basketmc Date: Thu, 22 Jun 2023 11:22:37 +0200 Subject: [PATCH] 0.14.1: - Bugfixing: Pipeline-Operationen --- CHANGELOG.md | 15 + pom.xml | 2 +- .../openkim/fachdienst/FachdienstService.java | 2 + .../cmdhandler/Pop3GatewayAuthCmdHandler.java | 17 +- .../cmdhandler/Pop3GatewayPassCmdHandler.java | 1 + .../cmdhandler/Pop3GatewayRetrCmdHandler.java | 350 +-------------- .../cmdhandler/SmtpGatewayAuthCmdHandler.java | 1 + .../smtp/hook/SmtpGatewayMailHook.java | 228 +--------- .../openkim/konnektor/KonnektorService.java | 11 +- .../openkim/pipeline/PipelineService.java | 4 +- .../operation/IPipelineOperation.java | 3 + .../GetDecryptCardHandleOperation.java | 47 +- .../konnektor/GetSignCardHandleOperation.java | 6 +- ...nnektorConnectionInformationOperation.java | 6 +- ...nektorLoadAllCardInformationOperation.java | 21 +- .../webservice/SignMailOperation.java | 6 +- .../CheckEncryptedMailFormatOperation.java | 6 +- .../mail/DecryptVerifyMailOperation.java | 425 ++++++++++++++++++ .../mail/SignEncryptMailOperation.java | 314 +++++++++++++ .../mail/part/AddMailAttachmentOperation.java | 6 +- .../mail/part/AddMailTextOperation.java | 6 +- 21 files changed, 852 insertions(+), 625 deletions(-) create mode 100644 src/main/java/net/sberg/openkim/pipeline/operation/mail/DecryptVerifyMailOperation.java create mode 100644 src/main/java/net/sberg/openkim/pipeline/operation/mail/SignEncryptMailOperation.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 3894ccd..f185153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ``` ``` +## [0.14.1] + +### Added +``` +``` + +### Changed +``` +``` + +### Fixed +``` +- Pipeline-Operationen +``` + ## [0.14.0] ### Added diff --git a/pom.xml b/pom.xml index b7a069f..77708e7 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ net.sberg openkim - 0.14.0 + 0.14.1 openkim Open KIM Client Modul diff --git a/src/main/java/net/sberg/openkim/fachdienst/FachdienstService.java b/src/main/java/net/sberg/openkim/fachdienst/FachdienstService.java index cdb4c88..1b847f8 100644 --- a/src/main/java/net/sberg/openkim/fachdienst/FachdienstService.java +++ b/src/main/java/net/sberg/openkim/fachdienst/FachdienstService.java @@ -138,6 +138,7 @@ private String aRequest(DefaultLogger logger, Konnektor konnektor, String domain DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_DOMAIN, domain); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_RECORD_TYPE, Type.string(Type.A)); + dnsRequestOperation.execute( defaultPipelineOperationContext, context -> { @@ -177,6 +178,7 @@ private Fachdienst fqdnRequest(DefaultLogger logger, Konnektor konnektor, Fachdi DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); defaultPipelineOperationContext.setEnvironmentValue(DnsFqdnRequestOperation.NAME, DnsFqdnRequestOperation.ENV_DOMAIN, domain); defaultPipelineOperationContext.setEnvironmentValue(DnsFqdnRequestOperation.NAME, DnsFqdnRequestOperation.ENV_PTR_DOMAIN_SUFFIX, fachdienst.getTyp().getDomainSuffix()); + dnsFqdnRequestOperation.execute( defaultPipelineOperationContext, context -> { diff --git a/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayAuthCmdHandler.java b/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayAuthCmdHandler.java index d1e6026..f718e94 100644 --- a/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayAuthCmdHandler.java +++ b/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayAuthCmdHandler.java @@ -373,15 +373,16 @@ protected Response doAuthTest(POP3Session session, Username username, String pas DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(((Pop3GatewaySession) session).getLogger()); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_DOMAIN, ((Pop3GatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost()); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_RECORD_TYPE, Type.string(Type.A)); + dnsRequestOperation.execute( - defaultPipelineOperationContext, - context -> { - ((Pop3GatewaySession) session).log("dns request finished for: " + ((Pop3GatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost()); - }, - (context, e) -> { - log.error("dns request failed for: " + ((Pop3GatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost(), e); - failedCounter.incrementAndGet(); - } + defaultPipelineOperationContext, + context -> { + ((Pop3GatewaySession) session).log("dns request finished for: " + ((Pop3GatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost()); + }, + (context, e) -> { + log.error("dns request failed for: " + ((Pop3GatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost(), e); + failedCounter.incrementAndGet(); + } ); DnsResultContainer dnsResultContainer = (DnsResultContainer) defaultPipelineOperationContext.getEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_DNS_RESULT); if (failedCounter.get() > 0 || dnsResultContainer == null || dnsResultContainer.isError()) { diff --git a/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayPassCmdHandler.java b/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayPassCmdHandler.java index 4936d64..87abf02 100644 --- a/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayPassCmdHandler.java +++ b/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayPassCmdHandler.java @@ -99,6 +99,7 @@ protected final Response doAuth(POP3Session session, Username user, String pass) DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(((Pop3GatewaySession) session).getLogger()); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_DOMAIN, ((Pop3GatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost()); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_RECORD_TYPE, Type.string(Type.A)); + dnsRequestOperation.execute( defaultPipelineOperationContext, context -> { diff --git a/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayRetrCmdHandler.java b/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayRetrCmdHandler.java index 7a6661e..d641469 100644 --- a/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayRetrCmdHandler.java +++ b/src/main/java/net/sberg/openkim/gateway/pop3/cmdhandler/Pop3GatewayRetrCmdHandler.java @@ -17,34 +17,18 @@ package net.sberg.openkim.gateway.pop3.cmdhandler; import com.google.common.collect.ImmutableSet; -import de.gematik.ws.conn.connectorcommon.DocumentType; -import de.gematik.ws.conn.encryptionservice.v6_1_1.DecryptDocumentResponse; -import de.gematik.ws.conn.signatureservice.v7_5_5.VerifyDocumentResponse; -import net.sberg.openkim.common.StringUtils; import net.sberg.openkim.common.metrics.DefaultMetricFactory; -import net.sberg.openkim.common.x509.CMSUtils; import net.sberg.openkim.gateway.pop3.EnumPop3GatewayState; import net.sberg.openkim.gateway.pop3.Pop3GatewaySession; import net.sberg.openkim.gateway.pop3.signreport.SignReportService; import net.sberg.openkim.konfiguration.EnumGatewayTIMode; import net.sberg.openkim.konnektor.Konnektor; import net.sberg.openkim.log.DefaultLogger; -import net.sberg.openkim.log.error.EnumErrorCode; import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; -import net.sberg.openkim.pipeline.operation.konnektor.GetDecryptCardHandleOperation; -import net.sberg.openkim.pipeline.operation.konnektor.KonnektorLoadAllCardInformationOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.DecryptDocumentOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.ReadCardCertificateOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.VerifySignedDocumentOperation; -import net.sberg.openkim.pipeline.operation.mail.CheckEncryptedMailFormatOperation; import net.sberg.openkim.pipeline.operation.mail.CreateDsnOperation; import net.sberg.openkim.pipeline.operation.mail.CreateEmbeddedMessageRfc822Operation; -import net.sberg.openkim.pipeline.operation.mail.MailUtils; -import net.sberg.openkim.pipeline.operation.mail.part.AddMailAttachmentOperation; -import net.sberg.openkim.pipeline.operation.mail.part.AddMailTextOperation; -import net.sberg.openkim.pipeline.operation.mail.part.AnalyzeMailPartsOperation; -import oasis.names.tc.dss_x._1_0.profiles.verificationreport.schema_.VerificationReportType; +import net.sberg.openkim.pipeline.operation.mail.DecryptVerifyMailOperation; import org.apache.james.protocols.api.Request; import org.apache.james.protocols.api.Response; import org.apache.james.protocols.pop3.POP3Response; @@ -53,22 +37,14 @@ import org.apache.james.protocols.pop3.core.AbstractPOP3CommandHandler; import org.apache.james.protocols.pop3.core.CRLFTerminatedInputStream; import org.apache.james.protocols.pop3.core.ExtraDotInputStream; -import org.bouncycastle.asn1.cms.ContentInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.mail.Session; -import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimePart; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.Collection; -import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; public class Pop3GatewayRetrCmdHandler extends AbstractPOP3CommandHandler { @@ -97,337 +73,31 @@ private byte[] decryptVerify( ) throws Exception { Konnektor konnektor = logger.getDefaultLoggerContext().getKonnektor(); try { + DecryptVerifyMailOperation decryptVerifyMailOperation = (DecryptVerifyMailOperation) pipelineService.getOperation(DecryptVerifyMailOperation.BUILTIN_VENDOR+"."+DecryptVerifyMailOperation.NAME); - //Header X-KOM-LE-Version available - if (encryptedMsg.getHeader(MailUtils.X_KOM_LE_VERSION) == null || encryptedMsg.getHeader(MailUtils.X_KOM_LE_VERSION).length == 0) { - logger.logLine("Header " + MailUtils.X_KOM_LE_VERSION + " not available"); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - encryptedMsg.writeTo(byteArrayOutputStream); - byte[] result = byteArrayOutputStream.toByteArray(); - byteArrayOutputStream.close(); - return result; - } - logger.logLine("Header " + MailUtils.X_KOM_LE_VERSION + " available"); - - //unterstützte versionen nicht verfügbar - String[] komLeVersionHeader = encryptedMsg.getHeader(MailUtils.X_KOM_LE_VERSION); - if (!MailUtils.VALID_KIM_VERSIONS.contains(komLeVersionHeader[0])) { - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_X014); - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4008); - logger.logLine("Fehler: " + EnumErrorCode.CODE_X014 + " - " + EnumErrorCode.CODE_X014.getHrText()); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4008 + " - " + EnumErrorCode.CODE_4008.getHrText()); - throw new IllegalStateException("kim version is wrong"); - } - - //unterstützte version kleiner als die version der mail - String komLeVersion = komLeVersionHeader[0]; - if (StringUtils.isNewVersionHigher(logger.getDefaultLoggerContext().getKonfiguration().getXkimPtShortVersion(), komLeVersion)) { - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4008); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4008 + " - " + EnumErrorCode.CODE_4008.getHrText()); - throw new IllegalStateException("kim version is wrong: < kim version in mail"); - } - - //analyze mail - log.info("analyze mail encrypt format"); - logger.logLine("analyze mail encrypt format"); - - CheckEncryptedMailFormatOperation checkEncryptedMailFormatOperation = (CheckEncryptedMailFormatOperation) pipelineService.getOperation(CheckEncryptedMailFormatOperation.BUILTIN_VENDOR+"."+CheckEncryptedMailFormatOperation.NAME); DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - - defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_MSG, encryptedMsg); - defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_DECRYPT_MODE, true); - - AnalyzeMailPartsOperation analyzeMailPartsOperation = (AnalyzeMailPartsOperation) pipelineService.getOperation(AnalyzeMailPartsOperation.BUILTIN_VENDOR+"."+AnalyzeMailPartsOperation.NAME); - checkEncryptedMailFormatOperation.setAnalyzeMailPartsOperation(analyzeMailPartsOperation); - - checkEncryptedMailFormatOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("check encrypted mailformat finished"); - }, - (context, e) -> { - log.error("error on checking encrypted mailformat", e); - } - ); - - boolean valid = (boolean)defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_VALID_RESULT); - if (!valid) { - log.error("mail encrypt format is wrong"); - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4010); - throw new IllegalStateException("mail encrypt format is wrong"); - } - - log.info("analyze mail encrypt format finished"); - logger.logLine("analyze mail encrypt format finished"); - - byte[] encryptedPart = (byte[])defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_PART); - ContentInfo contentInfo = (ContentInfo)defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_CONTENT_INFO); - - //card handle - log.info("getDecryptCardHandle"); - logger.logLine("getDecryptCardHandle"); - - GetDecryptCardHandleOperation getDecryptCardHandleOperation = (GetDecryptCardHandleOperation) pipelineService.getOperation(GetDecryptCardHandleOperation.BUILTIN_VENDOR+"."+GetDecryptCardHandleOperation.NAME); - - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - defaultPipelineOperationContext.setEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_CONTENT_INFO, contentInfo); - defaultPipelineOperationContext.setEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_USER_MAIL_ADDRESS, userMailAddress); - - KonnektorLoadAllCardInformationOperation konnektorLoadAllCardInformationOperation = (KonnektorLoadAllCardInformationOperation) pipelineService.getOperation(KonnektorLoadAllCardInformationOperation.BUILTIN_VENDOR+"."+KonnektorLoadAllCardInformationOperation.NAME); - getDecryptCardHandleOperation.setKonnektorLoadAllCardInformationOperation(konnektorLoadAllCardInformationOperation); - - ReadCardCertificateOperation readCardCertificateOperation = (ReadCardCertificateOperation) pipelineService.getOperation(ReadCardCertificateOperation.BUILTIN_VENDOR+"."+ReadCardCertificateOperation.NAME); - getDecryptCardHandleOperation.setReadCardCertificateOperation(readCardCertificateOperation); - - getDecryptCardHandleOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("loading of decrypt card handle finished"); - }, - (context, e) -> { - log.error("error on loading of decrypt card handle", e); - } - ); - - boolean cardHandleFound = (boolean)defaultPipelineOperationContext.getEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_RESULT_CARD_HANDLE_FOUND); - if (!cardHandleFound) { - throw new IllegalStateException("card handle not found"); - } - String decryptCardHandle = (String)defaultPipelineOperationContext.getEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_RESULT_CARD_HANDLE); - - log.info("getDecryptCardHandle finished: " + decryptCardHandle); - logger.logLine("getDecryptCardHandle finished: " + decryptCardHandle); - - //decrypt - DecryptDocumentOperation decryptDocumentOperation = (DecryptDocumentOperation) pipelineService.getOperation(DecryptDocumentOperation.BUILTIN_VENDOR+"."+DecryptDocumentOperation.NAME); - - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - defaultPipelineOperationContext.setEnvironmentValue(DecryptDocumentOperation.NAME, DecryptDocumentOperation.ENV_DOCUMENT, encryptedPart); - defaultPipelineOperationContext.setEnvironmentValue(DecryptDocumentOperation.NAME, DecryptDocumentOperation.ENV_CARDHANDLE, decryptCardHandle); + defaultPipelineOperationContext.setEnvironmentValue(DecryptVerifyMailOperation.NAME, DecryptVerifyMailOperation.ENV_ENCRYPTED_MSG, encryptedMsg); + defaultPipelineOperationContext.setEnvironmentValue(DecryptVerifyMailOperation.NAME, DecryptVerifyMailOperation.ENV_USER_MAIL_ADDRESS, userMailAddress); + defaultPipelineOperationContext.setEnvironmentValue(DecryptVerifyMailOperation.NAME, DecryptVerifyMailOperation.ENV_SIGN_REPORT_SERVICE, signReportService); AtomicInteger failedCounter = new AtomicInteger(); - decryptDocumentOperation.execute( + decryptVerifyMailOperation.execute( defaultPipelineOperationContext, context -> { - log.info("decrypt mail finished"); + log.info("decrypt and verify mail finished"); }, (context, e) -> { - log.error("error on decrypting of mail", e); + log.error("error on decrypting and verifying mail", e); failedCounter.incrementAndGet(); - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); - } - ); - - byte[] decryptedMsgBytes = null; - byte[] signedContent = null; - if (failedCounter.get() == 0) { - DecryptDocumentResponse decryptDocumentResponse = (DecryptDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(DecryptDocumentOperation.NAME, DecryptDocumentOperation.ENV_DECRYPT_DOCUMENT_RESPONSE); - if (!decryptDocumentResponse.getStatus().getResult().equals("OK")) { - throw new IllegalStateException("decrypt response not ok for the konnektor: " + konnektor.getIp() + " - " + decryptDocumentResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + decryptDocumentResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); - } - DocumentType documentType = decryptDocumentResponse.getDocument(); - if (documentType == null) { - throw new IllegalStateException("decrypt response document empty for the konnektor: " + konnektor.getIp()); - } - if (documentType.getBase64Data().getValue() == null) { - throw new IllegalStateException("decrypt response document empty for the konnektor: " + konnektor.getIp()); - } - - //extract decrypted message and parse signed content - try { - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(documentType.getBase64Data().getValue()); - MimePart mimePart = new MimeBodyPart(byteArrayInputStream); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - InputStream is = mimePart.getInputStream(); - for (int c = is.read(); c != -1; c = is.read()) { - byteArrayOutputStream.write(c); - } - decryptedMsgBytes = byteArrayOutputStream.toByteArray(); - byteArrayOutputStream.close(); - - signedContent = CMSUtils.extractSignedContent(mimePart, true); - } catch (Exception e) { - log.error("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress, e); - logger.logLine("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_X023); - logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4253); - logger.logLine("Fehler: " + EnumErrorCode.CODE_X023 + " - " + EnumErrorCode.CODE_X023.getHrText()); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4253 + " - " + EnumErrorCode.CODE_4253.getHrText()); - - throw new IllegalStateException("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - } - else { - throw new IllegalStateException("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - - //verify document - File signReportFile = null; - - VerifySignedDocumentOperation verifySignedDocumentOperation = (VerifySignedDocumentOperation) pipelineService.getOperation(VerifySignedDocumentOperation.BUILTIN_VENDOR+"."+VerifySignedDocumentOperation.NAME); - - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - defaultPipelineOperationContext.setEnvironmentValue(VerifySignedDocumentOperation.NAME, VerifySignedDocumentOperation.ENV_SIGNED_CONTENT, decryptedMsgBytes); - defaultPipelineOperationContext.setEnvironmentValue(VerifySignedDocumentOperation.NAME, VerifySignedDocumentOperation.ENV_SIGNED_DATA_AS_BASE64, false); - - AtomicInteger verifyFailedCounter = new AtomicInteger(); - verifySignedDocumentOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("verify mail finished"); - }, - (context, e) -> { - log.error("error on verifying of mail", e); - verifyFailedCounter.incrementAndGet(); } ); if (failedCounter.get() == 0) { - VerifyDocumentResponse verifyDocumentResponse = (VerifyDocumentResponse)defaultPipelineOperationContext.getEnvironmentValue(VerifySignedDocumentOperation.NAME, VerifySignedDocumentOperation.ENV_VERIFY_DOCUMENT_RESPONSE); - - if (!verifyDocumentResponse.getStatus().getResult().equals("OK")) { - logger.logLine("verify response not ok for the konnektor: " + konnektor.getIp() + " - " + verifyDocumentResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + verifyDocumentResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4115); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4115 + " - " + EnumErrorCode.CODE_4115.getHrText()); - - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); - - throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - - if (verifyDocumentResponse.getVerificationResult() != null) { - logger.logLine("verification result: " + verifyDocumentResponse.getVerificationResult().getHighLevelResult()); - } - - VerifyDocumentResponse.OptionalOutputs oo = verifyDocumentResponse.getOptionalOutputs(); - if (oo != null && oo.getVerificationReport() != null) { - VerificationReportType verificationReportType = oo.getVerificationReport(); - - if (verificationReportType == null) { - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4253); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4253 + " - " + EnumErrorCode.CODE_4253.getHrText()); - - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); - - throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - - signReportFile = signReportService.execute(logger, verificationReportType); - if (signReportFile == null) { - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); - - throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - } else { - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4253); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4253 + " - " + EnumErrorCode.CODE_4253.getHrText()); - - logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); - logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); - - throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - } - else { - throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - - //extracted decrypted and verified message - byte[] preHeader = "Content-Type: message/rfc822\r\n\r\n".getBytes(StandardCharsets.UTF_8); - int preHeaderLength = preHeader.length; - byte[] signedContentPayload = Arrays.copyOfRange(signedContent, preHeaderLength, signedContent.length); - MimeMessage decryptedAndVerifiedMessage = new MimeMessage(Session.getInstance(new Properties()), new ByteArrayInputStream(signedContentPayload)); - - MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.FROM); - MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.SENDER); - MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.REPLY_TO); - MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.TO); - MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.CC); - MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.BCC); - - //set header Return-Path, Received - logger.logLine("set " + MailUtils.RETURN_PATH); - String[] returnPath = encryptedMsg.getHeader(MailUtils.RETURN_PATH); - if (returnPath != null && returnPath.length > 0) { - decryptedAndVerifiedMessage.setHeader(MailUtils.RETURN_PATH, returnPath[0]); - } - logger.logLine("set " + MailUtils.RECEIVED); - String[] received = encryptedMsg.getHeader(MailUtils.RECEIVED); - if (received != null && received.length > 0) { - for (int i = 0; i < received.length; i++) { - decryptedAndVerifiedMessage.addHeader(MailUtils.RECEIVED, received[i]); - } - } - logger.logLine("set " + MailUtils.REPLY_TO); - String[] replyTo = encryptedMsg.getHeader(MailUtils.REPLY_TO); - if (replyTo != null && replyTo.length > 0) { - decryptedAndVerifiedMessage.setHeader(MailUtils.REPLY_TO, replyTo[0]); - } - - //add signature report - AddMailAttachmentOperation addMailAttachmentOperation = (AddMailAttachmentOperation) pipelineService.getOperation(AddMailAttachmentOperation.BUILTIN_VENDOR+"."+AddMailAttachmentOperation.NAME); - - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_ATTACHMENT, signReportFile); - defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_CONTENT_TYPE, "application/pdf"); - defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_ATTACHMENT_NAME, "Signaturpruefbericht.pdf"); - defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_MSG, decryptedAndVerifiedMessage); - - AtomicInteger addAtachmentFailedCounter = new AtomicInteger(); - addMailAttachmentOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("add signatur file finished"); - }, - (context, e) -> { - log.error("error on adding of signatur file", e); - addAtachmentFailedCounter.incrementAndGet(); - } - ); - - if (addAtachmentFailedCounter.get() == 0) { - decryptedAndVerifiedMessage = (MimeMessage)defaultPipelineOperationContext.getEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_RESULT_MSG); - } - else { - throw new IllegalStateException("error on adding signature file for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); - } - - //add signature text - AddMailTextOperation addMailTextOperation = (AddMailTextOperation) pipelineService.getOperation(AddMailTextOperation.BUILTIN_VENDOR+"."+AddMailTextOperation.NAME); - - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - defaultPipelineOperationContext.setEnvironmentValue(AddMailTextOperation.NAME, AddMailTextOperation.ENV_TEXT, "----------------------------------\n!!!Die Signatur wurde erfolgreich geprueft!!!\n----------------------------------"); - defaultPipelineOperationContext.setEnvironmentValue(AddMailTextOperation.NAME, AddMailTextOperation.ENV_MSG, decryptedAndVerifiedMessage); - - AtomicInteger addTextFailedCounter = new AtomicInteger(); - addMailTextOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("add text finished"); - }, - (context, e) -> { - log.error("error on adding of text", e); - addTextFailedCounter.incrementAndGet(); - } - ); - - if (addTextFailedCounter.get() == 0) { - decryptedAndVerifiedMessage = (MimeMessage)defaultPipelineOperationContext.getEnvironmentValue(AddMailTextOperation.NAME, AddMailTextOperation.ENV_RESULT_MSG); + return (byte[])defaultPipelineOperationContext.getEnvironmentValue(DecryptVerifyMailOperation.NAME, DecryptVerifyMailOperation.ENV_RESULT_MSG_BYTES); } else { - throw new IllegalStateException("error on adding text for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + throw new IllegalStateException("error on decrypting and verifying mail"); } - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - decryptedAndVerifiedMessage.writeTo(byteArrayOutputStream); - byte[] result = byteArrayOutputStream.toByteArray(); - byteArrayOutputStream.close(); - - return result; } catch (Exception e) { log.error("error on mail decrypting and verifying for the konnektor: " + konnektor.getIp(), e); throw e; diff --git a/src/main/java/net/sberg/openkim/gateway/smtp/cmdhandler/SmtpGatewayAuthCmdHandler.java b/src/main/java/net/sberg/openkim/gateway/smtp/cmdhandler/SmtpGatewayAuthCmdHandler.java index 40a55bc..6131143 100644 --- a/src/main/java/net/sberg/openkim/gateway/smtp/cmdhandler/SmtpGatewayAuthCmdHandler.java +++ b/src/main/java/net/sberg/openkim/gateway/smtp/cmdhandler/SmtpGatewayAuthCmdHandler.java @@ -453,6 +453,7 @@ public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws Ce DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(((SmtpGatewaySession) session).getLogger()); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_DOMAIN, ((SmtpGatewaySession) session).getLogger().getDefaultLoggerContext().getMailServerHost()); defaultPipelineOperationContext.setEnvironmentValue(DnsRequestOperation.NAME, DnsRequestOperation.ENV_RECORD_TYPE, Type.string(Type.A)); + dnsRequestOperation.execute( defaultPipelineOperationContext, context -> { diff --git a/src/main/java/net/sberg/openkim/gateway/smtp/hook/SmtpGatewayMailHook.java b/src/main/java/net/sberg/openkim/gateway/smtp/hook/SmtpGatewayMailHook.java index 94fd7b5..c345233 100644 --- a/src/main/java/net/sberg/openkim/gateway/smtp/hook/SmtpGatewayMailHook.java +++ b/src/main/java/net/sberg/openkim/gateway/smtp/hook/SmtpGatewayMailHook.java @@ -16,13 +16,8 @@ */ package net.sberg.openkim.gateway.smtp.hook; -import de.gematik.ws.conn.connectorcommon.DocumentType; -import de.gematik.ws.conn.encryptionservice.v6_1_1.EncryptDocumentResponse; -import de.gematik.ws.conn.signatureservice.v7_5_5.SignDocumentResponse; -import de.gematik.ws.conn.signatureservice.v7_5_5.SignResponse; import net.sberg.openkim.common.FileUtils; import net.sberg.openkim.common.ICommonConstants; -import net.sberg.openkim.common.x509.CMSUtils; import net.sberg.openkim.common.x509.X509CertificateResult; import net.sberg.openkim.gateway.smtp.EnumSmtpGatewayState; import net.sberg.openkim.gateway.smtp.SmtpGatewaySession; @@ -33,14 +28,10 @@ import net.sberg.openkim.log.error.IErrorContext; import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; -import net.sberg.openkim.pipeline.operation.konnektor.GetSignCardHandleOperation; -import net.sberg.openkim.pipeline.operation.konnektor.KonnektorLoadAllCardInformationOperation; import net.sberg.openkim.pipeline.operation.konnektor.vzd.LoadVzdCertsOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.EncryptMailOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetJobNumberOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.SignMailOperation; -import net.sberg.openkim.pipeline.operation.mail.*; -import oasis.names.tc.dss._1_0.core.schema.SignatureObject; +import net.sberg.openkim.pipeline.operation.mail.CheckSendingMailOperation; +import net.sberg.openkim.pipeline.operation.mail.SendDsnOperation; +import net.sberg.openkim.pipeline.operation.mail.SignEncryptMailOperation; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.TrustStrategy; import org.apache.james.protocols.smtp.MailEnvelope; @@ -50,11 +41,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.mail.BodyPart; import javax.mail.Session; -import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; import javax.net.ssl.SSLContext; import java.io.ByteArrayOutputStream; import java.io.File; @@ -63,7 +51,6 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; @@ -138,221 +125,30 @@ private byte[] signEncrypt( ) throws Exception { Konnektor konnektor = logger.getDefaultLoggerContext().getKonnektor(); try { - //is a mimebodypart encrypted? - if (originMimeMessage.isMimeType("multipart/mixed") - && - originMimeMessage.getContent() instanceof MimeMultipart - && - ((MimeMultipart) originMimeMessage.getContent()).getCount() == 2 - ) { - MimeMultipart mimeMultipart = (MimeMultipart) originMimeMessage.getContent(); - BodyPart bodyPart = null; - if (mimeMultipart.getBodyPart(0).isMimeType("message/rfc822")) { - bodyPart = mimeMultipart.getBodyPart(0); - } - else if (mimeMultipart.getBodyPart(1).isMimeType("message/rfc822")) { - bodyPart = mimeMultipart.getBodyPart(1); - } - if (bodyPart != null) { - MimeMessage encryptedBodyPart = MailUtils.createMimeMessage(null, bodyPart.getInputStream(), true); + SignEncryptMailOperation signEncryptMailOperation = (SignEncryptMailOperation) pipelineService.getOperation(SignEncryptMailOperation.BUILTIN_VENDOR+"."+SignEncryptMailOperation.NAME); - CheckEncryptedMailFormatOperation checkEncryptedMailFormatOperation = (CheckEncryptedMailFormatOperation) pipelineService.getOperation(CheckEncryptedMailFormatOperation.BUILTIN_VENDOR+"."+CheckEncryptedMailFormatOperation.NAME); - DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_MSG, encryptedBodyPart); - defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_DECRYPT_MODE, false); - - checkEncryptedMailFormatOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("checking encrypted mail format finished"); - }, - (context, e) -> { - log.error("error on checking encrypted mail format", e); - } - ); - - boolean valid = (boolean)defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_VALID_RESULT); - if (valid && logger.getDefaultLoggerContext().getMailEncryptFormatErrorContext().isEmpty()) { - logger.logLine("bodypart is encrypted"); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - encryptedBodyPart.writeTo(byteArrayOutputStream); - byte[] result = byteArrayOutputStream.toByteArray(); - byteArrayOutputStream.close(); - return result; - } - else { - logger.logLine("bodypart is not encrypted"); - } - } - } - - //get card handle - GetSignCardHandleOperation getSignCardHandleOperation = (GetSignCardHandleOperation) pipelineService.getOperation(GetSignCardHandleOperation.BUILTIN_VENDOR+"."+GetSignCardHandleOperation.NAME); DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - KonnektorLoadAllCardInformationOperation konnektorLoadAllCardInformationOperation = (KonnektorLoadAllCardInformationOperation) pipelineService.getOperation(KonnektorLoadAllCardInformationOperation.BUILTIN_VENDOR+"."+KonnektorLoadAllCardInformationOperation.NAME); - getSignCardHandleOperation.setKonnektorLoadAllCardInformationOperation(konnektorLoadAllCardInformationOperation); - - getSignCardHandleOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("loading of signing card handle finished"); - }, - (context, e) -> { - log.error("error on loading of signing card handle", e); - } - ); - - boolean cardHandleFound = (boolean)defaultPipelineOperationContext.getEnvironmentValue(GetSignCardHandleOperation.NAME, GetSignCardHandleOperation.ENV_RESULT_CARD_HANDLE_FOUND); - if (!cardHandleFound) { - throw new IllegalStateException("card handle not found"); - } - String cardSignHandle = (String)defaultPipelineOperationContext.getEnvironmentValue(GetSignCardHandleOperation.NAME, GetSignCardHandleOperation.ENV_RESULT_CARD_HANDLE); - - List recipientSenderCerts = new ArrayList<>(recipientCerts); - boolean add = true; - for (Iterator iterator = fromSenderCerts.iterator(); iterator.hasNext(); ) { - add = true; - X509CertificateResult fromSender = iterator.next(); - for (Iterator iterator2 = recipientSenderCerts.iterator(); iterator2.hasNext(); ) { - X509CertificateResult x509CertificateResult = iterator2.next(); - if (x509CertificateResult.getMailAddress().equals(fromSender.getMailAddress().toLowerCase())) { - add = false; - break; - } - } - if (add) { - recipientSenderCerts.add(fromSender); - } - } - - //signing mail - SignMailOperation signMailOperation = (SignMailOperation) pipelineService.getOperation(SignMailOperation.BUILTIN_VENDOR+"."+SignMailOperation.NAME); - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - - defaultPipelineOperationContext.setEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_CARDHANDLE, cardSignHandle); - defaultPipelineOperationContext.setEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_MIMEMESSAGE, originMimeMessage); - defaultPipelineOperationContext.setEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_VZD_CERTS, recipientSenderCerts); - - GetJobNumberOperation getJobNumberOperation = (GetJobNumberOperation) pipelineService.getOperation(GetJobNumberOperation.BUILTIN_VENDOR+"."+GetJobNumberOperation.NAME); - signMailOperation.setGetJobNumberOperation(getJobNumberOperation); + defaultPipelineOperationContext.setEnvironmentValue(SignEncryptMailOperation.NAME, SignEncryptMailOperation.ENV_ORIGIN_MIMEMESSAGE, originMimeMessage); + defaultPipelineOperationContext.setEnvironmentValue(SignEncryptMailOperation.NAME, SignEncryptMailOperation.ENV_RECIPIENT_CERTS, recipientCerts); + defaultPipelineOperationContext.setEnvironmentValue(SignEncryptMailOperation.NAME, SignEncryptMailOperation.ENV_FROM_SENDER_CERTS, fromSenderCerts); AtomicInteger failedCounter = new AtomicInteger(); - signMailOperation.execute( + signEncryptMailOperation.execute( defaultPipelineOperationContext, context -> { - log.info("signing mail finished"); + log.info("sign and encrypt mail finished"); }, (context, e) -> { - log.error("error on signing mail", e); + log.error("error on mail signing and encrypting", e); failedCounter.incrementAndGet(); } ); - byte[] signedMsg = null; if (failedCounter.get() == 0) { - SignDocumentResponse signDocumentResponse = (SignDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_SIGN_DOCUMENT_RESPONSE); - if (signDocumentResponse.getSignResponse().isEmpty()) { - throw new IllegalStateException("empty sign response for the cardHandle: " + cardSignHandle); - } - SignResponse signResponse = signDocumentResponse.getSignResponse().get(0); - if (!signResponse.getStatus().getResult().equals("OK")) { - throw new IllegalStateException("sign response not ok for the cardHandle: " + cardSignHandle + " - " + signResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + signResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); - } - SignatureObject signatureObject = signResponse.getSignatureObject(); - if (signatureObject == null) { - throw new IllegalStateException("sign response signatureObject empty for the cardHandle: " + cardSignHandle); - } - if (signatureObject.getBase64Signature().getValue() == null) { - throw new IllegalStateException("sign response signatureObject empty for the cardHandle: " + cardSignHandle); - } - - MimeBodyPart mimeBodyPartSignedMsg = new MimeBodyPart(); - mimeBodyPartSignedMsg.setContent(signatureObject.getBase64Signature().getValue(), CMSUtils.SMIME_CONTENT_TYPE); - mimeBodyPartSignedMsg.setHeader("Content-Type", CMSUtils.SMIME_CONTENT_TYPE); - mimeBodyPartSignedMsg.setHeader("Content-Transfer-Encoding", "binary"); - mimeBodyPartSignedMsg.setDisposition(CMSUtils.SMIME_DISPOSITION); - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - mimeBodyPartSignedMsg.writeTo(byteArrayOutputStream); - signedMsg = byteArrayOutputStream.toByteArray(); - byteArrayOutputStream.close(); - - if (signedMsg == null) { - throw new IllegalStateException("error on signing mail"); - } - } - else { - throw new IllegalStateException("error on signing mail"); - } - - //encrypting mail - EncryptMailOperation encryptMailOperation = (EncryptMailOperation) pipelineService.getOperation(EncryptMailOperation.BUILTIN_VENDOR+"."+EncryptMailOperation.NAME); - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - - defaultPipelineOperationContext.setEnvironmentValue(EncryptMailOperation.NAME, EncryptMailOperation.ENV_SIGNED_MAIL, signedMsg); - defaultPipelineOperationContext.setEnvironmentValue(EncryptMailOperation.NAME, EncryptMailOperation.ENV_VZD_CERTS, recipientSenderCerts); - - AtomicInteger encryptFailedCounter = new AtomicInteger(); - encryptMailOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("encrypting mail finished"); - }, - (context, e) -> { - log.error("error on encrypting mail", e); - encryptFailedCounter.incrementAndGet(); - } - ); - - byte[] encryptedMsg = null; - if (encryptFailedCounter.get() == 0) { - EncryptDocumentResponse encryptDocumentResponse = (EncryptDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(EncryptMailOperation.NAME, EncryptMailOperation.ENV_ENCRYPT_DOCUMENT_RESPONSE); - if (!encryptDocumentResponse.getStatus().getResult().equals("OK")) { - throw new IllegalStateException("encrypt response not ok for the konnektor: " + konnektor.getIp() + " - " + encryptDocumentResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + encryptDocumentResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); - } - DocumentType documentType = encryptDocumentResponse.getDocument(); - if (documentType == null) { - throw new IllegalStateException("encrypt response document empty for the konnektor: " + konnektor.getIp()); - } - if (documentType.getBase64Data().getValue() == null) { - throw new IllegalStateException("encrypt response document empty for the konnektor: " + konnektor.getIp()); - } - - encryptedMsg = documentType.getBase64Data().getValue(); - if (encryptedMsg == null) { - throw new IllegalStateException("error on encrypting mail"); - } - } - else { - throw new IllegalStateException("error on encrypting mail"); - } - - //compose encrypting mail - ComposeEncryptedMailOperation composeEncryptedMailOperation = (ComposeEncryptedMailOperation) pipelineService.getOperation(ComposeEncryptedMailOperation.BUILTIN_VENDOR+"."+ComposeEncryptedMailOperation.NAME); - defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); - - defaultPipelineOperationContext.setEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_ENCRYPTED_MSG, encryptedMsg); - defaultPipelineOperationContext.setEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_RECIPIENT_CERTS, recipientSenderCerts); - defaultPipelineOperationContext.setEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_ORIGIN_MSG, originMimeMessage); - - AtomicInteger composeEncryptedMsgFailedCounter = new AtomicInteger(); - composeEncryptedMailOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("composing mail finished"); - }, - (context, e) -> { - log.error("error on composing mail", e); - composeEncryptedMsgFailedCounter.incrementAndGet(); - } - ); - - if (composeEncryptedMsgFailedCounter.get() == 0) { - byte[] result = (byte[]) defaultPipelineOperationContext.getEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_RESULT_MSG_BYTES); - return result; + return (byte[])defaultPipelineOperationContext.getEnvironmentValue(SignEncryptMailOperation.NAME, SignEncryptMailOperation.ENV_RESULT_MSG_BYTES); } else { - throw new IllegalStateException("error on composing mail"); + throw new IllegalStateException("error on mail signing and encrypting"); } } catch (Exception e) { log.error("error on mail signing and encrypting for the konnektor: " + konnektor.getIp(), e); diff --git a/src/main/java/net/sberg/openkim/konnektor/KonnektorService.java b/src/main/java/net/sberg/openkim/konnektor/KonnektorService.java index 768e7d7..499a1c1 100644 --- a/src/main/java/net/sberg/openkim/konnektor/KonnektorService.java +++ b/src/main/java/net/sberg/openkim/konnektor/KonnektorService.java @@ -30,10 +30,6 @@ import net.sberg.openkim.pipeline.operation.konnektor.KonnektorLoadAllCardInformationOperation; import net.sberg.openkim.pipeline.operation.konnektor.ntp.NtpRequestOperation; import net.sberg.openkim.pipeline.operation.konnektor.ntp.NtpResult; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetCardsOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetPinStatusOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetResourceInformationOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.ReadCardCertificateOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -223,6 +219,7 @@ private void checkNtp(Konnektor konnektor, DefaultLogger logger) { try { IPipelineOperation ntpPipelineOperation = pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ NtpRequestOperation.NAME); DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); + ntpPipelineOperation.execute( defaultPipelineOperationContext, context -> { @@ -246,11 +243,8 @@ private void loadAllCards(Konnektor konnektor, DefaultLogger logger) { logger.logLine("load card infos for the konnektor: " + konnektor.getIp()); KonnektorLoadAllCardInformationOperation konnektorLoadAllCardsPipelineOperation = (KonnektorLoadAllCardInformationOperation)pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ KonnektorLoadAllCardInformationOperation.NAME); - konnektorLoadAllCardsPipelineOperation.setGetCardsOperation((GetCardsOperation)pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ GetCardsOperation.NAME)); - konnektorLoadAllCardsPipelineOperation.setReadCardCertificateOperation((ReadCardCertificateOperation)pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ ReadCardCertificateOperation.NAME)); - konnektorLoadAllCardsPipelineOperation.setGetPinStatusOperation((GetPinStatusOperation)pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ GetPinStatusOperation.NAME)); - DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); + konnektorLoadAllCardsPipelineOperation.execute( defaultPipelineOperationContext, context -> { @@ -271,7 +265,6 @@ private void checkConnectivity(Konnektor konnektor, DefaultLogger logger) { logger.logLine("load connectivity info for the konnektor: " + konnektor.getIp()); KonnektorConnectionInformationOperation konnektorConnectionInfoPipelineOperation = (KonnektorConnectionInformationOperation) pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ KonnektorConnectionInformationOperation.NAME); - konnektorConnectionInfoPipelineOperation.setGetResourceInformationOperation((GetResourceInformationOperation) pipelineService.getOperation(IPipelineOperation.BUILTIN_VENDOR+"."+ GetResourceInformationOperation.NAME)); DefaultPipelineOperationContext defaultPipelineOperationContext = new DefaultPipelineOperationContext(logger); konnektorConnectionInfoPipelineOperation.execute( diff --git a/src/main/java/net/sberg/openkim/pipeline/PipelineService.java b/src/main/java/net/sberg/openkim/pipeline/PipelineService.java index 96846b7..5833520 100644 --- a/src/main/java/net/sberg/openkim/pipeline/PipelineService.java +++ b/src/main/java/net/sberg/openkim/pipeline/PipelineService.java @@ -22,7 +22,9 @@ public void init() throws Exception { public IPipelineOperation getOperation(String key) throws Exception { if (operationMap.containsKey(key)) { - return operationMap.get(key).getClass().getDeclaredConstructor().newInstance(); + IPipelineOperation pipelineOperation = operationMap.get(key).getClass().getDeclaredConstructor().newInstance(); + pipelineOperation.initialize(this); + return pipelineOperation; } throw new IllegalStateException("no operation available: "+key); } diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/IPipelineOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/IPipelineOperation.java index dfe1a02..b2064c6 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/IPipelineOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/IPipelineOperation.java @@ -16,6 +16,8 @@ */ package net.sberg.openkim.pipeline.operation; +import net.sberg.openkim.pipeline.PipelineService; + import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -48,4 +50,5 @@ public default boolean hasError(DefaultPipelineOperationContext defaultPipelineO } return false; } + public default void initialize(PipelineService pipelineService) throws Exception {} } diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetDecryptCardHandleOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetDecryptCardHandleOperation.java index ca46c13..43e9f08 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetDecryptCardHandleOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetDecryptCardHandleOperation.java @@ -29,6 +29,7 @@ import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.log.error.EnumErrorCode; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import net.sberg.openkim.pipeline.operation.konnektor.webservice.ReadCardCertificateOperation; @@ -57,12 +58,10 @@ public class GetDecryptCardHandleOperation implements IPipelineOperation { private ReadCardCertificateOperation readCardCertificateOperation; private KonnektorLoadAllCardInformationOperation konnektorLoadAllCardInformationOperation; - public void setReadCardCertificateOperation(ReadCardCertificateOperation readCardCertificateOperation) { - this.readCardCertificateOperation = readCardCertificateOperation; - } - - public void setKonnektorLoadAllCardInformationOperation(KonnektorLoadAllCardInformationOperation konnektorLoadAllCardInformationOperation) { - this.konnektorLoadAllCardInformationOperation = konnektorLoadAllCardInformationOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + readCardCertificateOperation = (ReadCardCertificateOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+ReadCardCertificateOperation.NAME); + konnektorLoadAllCardInformationOperation = (KonnektorLoadAllCardInformationOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+KonnektorLoadAllCardInformationOperation.NAME); } @Override @@ -103,14 +102,14 @@ public void execute(DefaultPipelineOperationContext defaultPipelineOperationCont logger.logLine("load all cards - start"); konnektorLoadAllCardInformationOperation.execute( - defaultPipelineOperationContext, - context -> { - log.info("load all cards - finished"); - logger.logLine("load all cards - finished"); - }, - (context, e) -> { - defaultPipelineOperationContext.setEnvironmentValue(konnektorLoadAllCardInformationOperation.getName(), ENV_EXCEPTION, e); - } + defaultPipelineOperationContext, + context -> { + log.info("load all cards - finished"); + logger.logLine("load all cards - finished"); + }, + (context, e) -> { + defaultPipelineOperationContext.setEnvironmentValue(konnektorLoadAllCardInformationOperation.getName(), ENV_EXCEPTION, e); + } ); List cards = konnektor.getCards(); @@ -130,16 +129,16 @@ public void execute(DefaultPipelineOperationContext defaultPipelineOperationCont ReadCardCertificateResponse readCardCertificateResponse = (ReadCardCertificateResponse) defaultPipelineOperationContext.getEnvironmentValue(readCardCertificateOperation.getName(), ReadCardCertificateOperation.ENV_READ_CARD_CERT_RESPONSE); if (!readCardCertificateResponse.getStatus().getResult().equals(KonnektorWebserviceUtils.STATUS_OK)) { defaultPipelineOperationContext.setEnvironmentValue( - readCardCertificateOperation.getName(), - ENV_EXCEPTION, - new IllegalStateException( - "request getCertificate status not OK for the konnektor: " - + konnektor.getIp() - + " and the cardHandle: " - + konnektorCard.getCardHandle() - + " and the certRef: " - + KonnektorWebserviceUtils.CERT_REF_ENC - ) + readCardCertificateOperation.getName(), + ENV_EXCEPTION, + new IllegalStateException( + "request getCertificate status not OK for the konnektor: " + + konnektor.getIp() + + " and the cardHandle: " + + konnektorCard.getCardHandle() + + " and the certRef: " + + KonnektorWebserviceUtils.CERT_REF_ENC + ) ); } else { for (Iterator konnektorCardIterator = readCardCertificateResponse.getX509DataInfoList().getX509DataInfo().iterator(); konnektorCardIterator.hasNext(); ) { diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetSignCardHandleOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetSignCardHandleOperation.java index ce49c39..5081d7b 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetSignCardHandleOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/GetSignCardHandleOperation.java @@ -24,6 +24,7 @@ import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.log.error.EnumErrorCode; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import org.apache.james.metrics.api.TimeMetric; @@ -46,8 +47,9 @@ public class GetSignCardHandleOperation implements IPipelineOperation { private KonnektorLoadAllCardInformationOperation konnektorLoadAllCardInformationOperation; - public void setKonnektorLoadAllCardInformationOperation(KonnektorLoadAllCardInformationOperation konnektorLoadAllCardInformationOperation) { - this.konnektorLoadAllCardInformationOperation = konnektorLoadAllCardInformationOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + konnektorLoadAllCardInformationOperation = (KonnektorLoadAllCardInformationOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+KonnektorLoadAllCardInformationOperation.NAME); } @Override diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorConnectionInformationOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorConnectionInformationOperation.java index f58cce5..371a28b 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorConnectionInformationOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorConnectionInformationOperation.java @@ -23,6 +23,7 @@ import net.sberg.openkim.konnektor.KonnektorWebserviceUtils; import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetResourceInformationOperation; @@ -41,8 +42,9 @@ public class KonnektorConnectionInformationOperation implements IPipelineOperati private GetResourceInformationOperation getResourceInformationOperation; - public void setGetResourceInformationOperation(GetResourceInformationOperation getResourceInformationOperation) { - this.getResourceInformationOperation = getResourceInformationOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + getResourceInformationOperation = (GetResourceInformationOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+GetResourceInformationOperation.NAME); } @Override diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorLoadAllCardInformationOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorLoadAllCardInformationOperation.java index 839193c..46405a4 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorLoadAllCardInformationOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/KonnektorLoadAllCardInformationOperation.java @@ -29,12 +29,10 @@ import net.sberg.openkim.konnektor.*; import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetCardsOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.GetPinStatusOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.ReadCardCertificateOperation; -import net.sberg.openkim.pipeline.operation.konnektor.webservice.VerifyPinOperation; +import net.sberg.openkim.pipeline.operation.konnektor.webservice.*; import org.apache.james.metrics.api.TimeMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,16 +53,11 @@ public class KonnektorLoadAllCardInformationOperation implements IPipelineOperat private ReadCardCertificateOperation readCardCertificateOperation; private GetPinStatusOperation getPinStatusOperation; - public void setGetCardsOperation(GetCardsOperation getCardsOperation) { - this.getCardsOperation = getCardsOperation; - } - - public void setGetPinStatusOperation(GetPinStatusOperation getPinStatusOperation) { - this.getPinStatusOperation = getPinStatusOperation; - } - - public void setReadCardCertificateOperation(ReadCardCertificateOperation readCardCertificateOperation) { - this.readCardCertificateOperation = readCardCertificateOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + getCardsOperation = (GetCardsOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+GetCardsOperation.NAME); + readCardCertificateOperation = (ReadCardCertificateOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+ReadCardCertificateOperation.NAME); + getPinStatusOperation = (GetPinStatusOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+GetPinStatusOperation.NAME); } @Override diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/webservice/SignMailOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/webservice/SignMailOperation.java index dce841a..a176db5 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/webservice/SignMailOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/konnektor/webservice/SignMailOperation.java @@ -26,6 +26,7 @@ import net.sberg.openkim.konnektor.*; import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import oasis.names.tc.dss._1_0.core.schema.*; @@ -54,8 +55,9 @@ public class SignMailOperation implements IPipelineOperation { private GetJobNumberOperation getJobNumberOperation; - public void setGetJobNumberOperation(GetJobNumberOperation getJobNumberOperation) { - this.getJobNumberOperation = getJobNumberOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + getJobNumberOperation = (GetJobNumberOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+GetJobNumberOperation.NAME); } @Override diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/mail/CheckEncryptedMailFormatOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/mail/CheckEncryptedMailFormatOperation.java index 5704022..3ca96d8 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/mail/CheckEncryptedMailFormatOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/mail/CheckEncryptedMailFormatOperation.java @@ -22,6 +22,7 @@ import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.log.error.EnumErrorCode; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import net.sberg.openkim.pipeline.operation.mail.part.AnalyzeMailPartsOperation; @@ -57,8 +58,9 @@ public class CheckEncryptedMailFormatOperation implements IPipelineOperation { private AnalyzeMailPartsOperation analyzeMailPartsOperation; - public void setAnalyzeMailPartsOperation(AnalyzeMailPartsOperation analyzeMailPartsOperation) { - this.analyzeMailPartsOperation = analyzeMailPartsOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + analyzeMailPartsOperation = (AnalyzeMailPartsOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+AnalyzeMailPartsOperation.NAME); } @Override diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/mail/DecryptVerifyMailOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/mail/DecryptVerifyMailOperation.java new file mode 100644 index 0000000..baae732 --- /dev/null +++ b/src/main/java/net/sberg/openkim/pipeline/operation/mail/DecryptVerifyMailOperation.java @@ -0,0 +1,425 @@ +/* + * Copyright 2023 sberg it-systeme GmbH + * + * 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://ec.europa.eu/idabc/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. + */ +package net.sberg.openkim.pipeline.operation.mail; + +import de.gematik.ws.conn.connectorcommon.DocumentType; +import de.gematik.ws.conn.encryptionservice.v6_1_1.DecryptDocumentResponse; +import de.gematik.ws.conn.signatureservice.v7_5_5.VerifyDocumentResponse; +import net.sberg.openkim.common.StringUtils; +import net.sberg.openkim.common.metrics.DefaultMetricFactory; +import net.sberg.openkim.common.x509.CMSUtils; +import net.sberg.openkim.gateway.pop3.signreport.SignReportService; +import net.sberg.openkim.konnektor.Konnektor; +import net.sberg.openkim.log.DefaultLogger; +import net.sberg.openkim.log.error.EnumErrorCode; +import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; +import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; +import net.sberg.openkim.pipeline.operation.IPipelineOperation; +import net.sberg.openkim.pipeline.operation.konnektor.GetDecryptCardHandleOperation; +import net.sberg.openkim.pipeline.operation.konnektor.webservice.DecryptDocumentOperation; +import net.sberg.openkim.pipeline.operation.konnektor.webservice.VerifySignedDocumentOperation; +import net.sberg.openkim.pipeline.operation.mail.part.AddMailAttachmentOperation; +import net.sberg.openkim.pipeline.operation.mail.part.AddMailTextOperation; +import oasis.names.tc.dss_x._1_0.profiles.verificationreport.schema_.VerificationReportType; +import org.apache.james.metrics.api.TimeMetric; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.Session; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimePart; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +@PipelineOperation +public class DecryptVerifyMailOperation implements IPipelineOperation { + + private static final Logger log = LoggerFactory.getLogger(DecryptVerifyMailOperation.class); + public static final String NAME = "DecryptVerifyMail"; + + public static final String ENV_ENCRYPTED_MSG = "encryptedMsg"; + public static final String ENV_USER_MAIL_ADDRESS = "userMailAddress"; + public static final String ENV_SIGN_REPORT_SERVICE = "signResportService"; + public static final String ENV_RESULT_MSG_BYTES = "resultMsgBytes"; + + private CheckEncryptedMailFormatOperation checkEncryptedMailFormatOperation; + private GetDecryptCardHandleOperation getDecryptCardHandleOperation; + private DecryptDocumentOperation decryptDocumentOperation; + private VerifySignedDocumentOperation verifySignedDocumentOperation; + private AddMailAttachmentOperation addMailAttachmentOperation; + private AddMailTextOperation addMailTextOperation; + + @Override + public void initialize(PipelineService pipelineService) throws Exception { + checkEncryptedMailFormatOperation = (CheckEncryptedMailFormatOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+CheckEncryptedMailFormatOperation.NAME); + getDecryptCardHandleOperation = (GetDecryptCardHandleOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+GetDecryptCardHandleOperation.NAME); + decryptDocumentOperation = (DecryptDocumentOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+DecryptDocumentOperation.NAME); + verifySignedDocumentOperation = (VerifySignedDocumentOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+VerifySignedDocumentOperation.NAME); + addMailAttachmentOperation = (AddMailAttachmentOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+AddMailAttachmentOperation.NAME); + addMailTextOperation = (AddMailTextOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+AddMailTextOperation.NAME); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public Consumer getDefaultOkConsumer() { + throw new IllegalStateException("not implemented"); + } + + @Override + public void execute(DefaultPipelineOperationContext defaultPipelineOperationContext, Consumer okConsumer, BiConsumer failConsumer) { + TimeMetric timeMetric = null; + + DefaultLogger logger = defaultPipelineOperationContext.getLogger(); + Konnektor konnektor = logger.getDefaultLoggerContext().getKonnektor(); + + try { + DefaultMetricFactory metricFactory = new DefaultMetricFactory(logger); + timeMetric = metricFactory.timer(NAME); + + MimeMessage encryptedMsg = (MimeMessage)defaultPipelineOperationContext.getEnvironmentValue(NAME, ENV_ENCRYPTED_MSG); + String userMailAddress = (String)defaultPipelineOperationContext.getEnvironmentValue(NAME, ENV_USER_MAIL_ADDRESS); + SignReportService signReportService = (SignReportService)defaultPipelineOperationContext.getEnvironmentValue(NAME, ENV_SIGN_REPORT_SERVICE); + + //Header X-KOM-LE-Version available -> not encrypted + if (encryptedMsg.getHeader(MailUtils.X_KOM_LE_VERSION) == null || encryptedMsg.getHeader(MailUtils.X_KOM_LE_VERSION).length == 0) { + logger.logLine("Header " + MailUtils.X_KOM_LE_VERSION + " not available"); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + encryptedMsg.writeTo(byteArrayOutputStream); + byte[] result = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + defaultPipelineOperationContext.setEnvironmentValue(NAME, ENV_RESULT_MSG_BYTES, result); + } + else { + logger.logLine("Header " + MailUtils.X_KOM_LE_VERSION + " available"); + + //unterstützte versionen nicht verfügbar + String[] komLeVersionHeader = encryptedMsg.getHeader(MailUtils.X_KOM_LE_VERSION); + if (!MailUtils.VALID_KIM_VERSIONS.contains(komLeVersionHeader[0])) { + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_X014); + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4008); + logger.logLine("Fehler: " + EnumErrorCode.CODE_X014 + " - " + EnumErrorCode.CODE_X014.getHrText()); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4008 + " - " + EnumErrorCode.CODE_4008.getHrText()); + throw new IllegalStateException("kim version is wrong"); + } + + //unterstützte version kleiner als die version der mail + String komLeVersion = komLeVersionHeader[0]; + if (StringUtils.isNewVersionHigher(logger.getDefaultLoggerContext().getKonfiguration().getXkimPtShortVersion(), komLeVersion)) { + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4008); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4008 + " - " + EnumErrorCode.CODE_4008.getHrText()); + throw new IllegalStateException("kim version is wrong: < kim version in mail"); + } + + //analyze mail + log.info("analyze mail encrypt format"); + logger.logLine("analyze mail encrypt format"); + + defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_MSG, encryptedMsg); + defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_DECRYPT_MODE, true); + + checkEncryptedMailFormatOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("check encrypted mailformat finished"); + }, + (context, e) -> { + log.error("error on checking encrypted mailformat", e); + } + ); + + boolean valid = (boolean) defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_VALID_RESULT); + if (!valid) { + log.error("mail encrypt format is wrong"); + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4010); + throw new IllegalStateException("mail encrypt format is wrong"); + } + + log.info("analyze mail encrypt format finished"); + logger.logLine("analyze mail encrypt format finished"); + + byte[] encryptedPart = (byte[]) defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_PART); + ContentInfo contentInfo = (ContentInfo) defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_CONTENT_INFO); + + //card handle + log.info("getDecryptCardHandle"); + logger.logLine("getDecryptCardHandle"); + + defaultPipelineOperationContext.setEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_CONTENT_INFO, contentInfo); + defaultPipelineOperationContext.setEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_USER_MAIL_ADDRESS, userMailAddress); + + getDecryptCardHandleOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("loading of decrypt card handle finished"); + }, + (context, e) -> { + log.error("error on loading of decrypt card handle", e); + } + ); + + boolean cardHandleFound = (boolean) defaultPipelineOperationContext.getEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_RESULT_CARD_HANDLE_FOUND); + if (!cardHandleFound) { + throw new IllegalStateException("card handle not found"); + } + String decryptCardHandle = (String) defaultPipelineOperationContext.getEnvironmentValue(GetDecryptCardHandleOperation.NAME, GetDecryptCardHandleOperation.ENV_RESULT_CARD_HANDLE); + + log.info("getDecryptCardHandle finished: " + decryptCardHandle); + logger.logLine("getDecryptCardHandle finished: " + decryptCardHandle); + + //decrypt + defaultPipelineOperationContext.setEnvironmentValue(DecryptDocumentOperation.NAME, DecryptDocumentOperation.ENV_DOCUMENT, encryptedPart); + defaultPipelineOperationContext.setEnvironmentValue(DecryptDocumentOperation.NAME, DecryptDocumentOperation.ENV_CARDHANDLE, decryptCardHandle); + + AtomicInteger failedCounter = new AtomicInteger(); + decryptDocumentOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("decrypt mail finished"); + }, + (context, e) -> { + log.error("error on decrypting of mail", e); + failedCounter.incrementAndGet(); + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); + } + ); + + byte[] decryptedMsgBytes = null; + byte[] signedContent = null; + if (failedCounter.get() == 0) { + DecryptDocumentResponse decryptDocumentResponse = (DecryptDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(DecryptDocumentOperation.NAME, DecryptDocumentOperation.ENV_DECRYPT_DOCUMENT_RESPONSE); + if (!decryptDocumentResponse.getStatus().getResult().equals("OK")) { + throw new IllegalStateException("decrypt response not ok for the konnektor: " + konnektor.getIp() + " - " + decryptDocumentResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + decryptDocumentResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); + } + DocumentType documentType = decryptDocumentResponse.getDocument(); + if (documentType == null) { + throw new IllegalStateException("decrypt response document empty for the konnektor: " + konnektor.getIp()); + } + if (documentType.getBase64Data().getValue() == null) { + throw new IllegalStateException("decrypt response document empty for the konnektor: " + konnektor.getIp()); + } + + //extract decrypted message and parse signed content + try { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(documentType.getBase64Data().getValue()); + MimePart mimePart = new MimeBodyPart(byteArrayInputStream); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + InputStream is = mimePart.getInputStream(); + for (int c = is.read(); c != -1; c = is.read()) { + byteArrayOutputStream.write(c); + } + decryptedMsgBytes = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + + signedContent = CMSUtils.extractSignedContent(mimePart, true); + } catch (Exception e) { + log.error("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress, e); + logger.logLine("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_X023); + logger.getDefaultLoggerContext().getMailDecryptErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4253); + logger.logLine("Fehler: " + EnumErrorCode.CODE_X023 + " - " + EnumErrorCode.CODE_X023.getHrText()); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4253 + " - " + EnumErrorCode.CODE_4253.getHrText()); + + throw new IllegalStateException("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + } else { + throw new IllegalStateException("error on extract decrypted message and parse signed content for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + + //verify document + File signReportFile = null; + + defaultPipelineOperationContext.setEnvironmentValue(VerifySignedDocumentOperation.NAME, VerifySignedDocumentOperation.ENV_SIGNED_CONTENT, decryptedMsgBytes); + defaultPipelineOperationContext.setEnvironmentValue(VerifySignedDocumentOperation.NAME, VerifySignedDocumentOperation.ENV_SIGNED_DATA_AS_BASE64, false); + + AtomicInteger verifyFailedCounter = new AtomicInteger(); + verifySignedDocumentOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("verify mail finished"); + }, + (context, e) -> { + log.error("error on verifying of mail", e); + verifyFailedCounter.incrementAndGet(); + } + ); + + if (failedCounter.get() == 0) { + VerifyDocumentResponse verifyDocumentResponse = (VerifyDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(VerifySignedDocumentOperation.NAME, VerifySignedDocumentOperation.ENV_VERIFY_DOCUMENT_RESPONSE); + + if (!verifyDocumentResponse.getStatus().getResult().equals("OK")) { + logger.logLine("verify response not ok for the konnektor: " + konnektor.getIp() + " - " + verifyDocumentResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + verifyDocumentResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4115); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4115 + " - " + EnumErrorCode.CODE_4115.getHrText()); + + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); + + throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + + if (verifyDocumentResponse.getVerificationResult() != null) { + logger.logLine("verification result: " + verifyDocumentResponse.getVerificationResult().getHighLevelResult()); + } + + VerifyDocumentResponse.OptionalOutputs oo = verifyDocumentResponse.getOptionalOutputs(); + if (oo != null && oo.getVerificationReport() != null) { + VerificationReportType verificationReportType = oo.getVerificationReport(); + + if (verificationReportType == null) { + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4253); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4253 + " - " + EnumErrorCode.CODE_4253.getHrText()); + + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); + + throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + + signReportFile = signReportService.execute(logger, verificationReportType); + if (signReportFile == null) { + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); + + throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + } else { + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4253); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4253 + " - " + EnumErrorCode.CODE_4253.getHrText()); + + logger.getDefaultLoggerContext().getMailSignVerifyErrorContext().getErrorCodes().add(EnumErrorCode.CODE_4011); + logger.logLine("Fehler: " + EnumErrorCode.CODE_4011 + " - " + EnumErrorCode.CODE_4011.getHrText()); + + throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + } else { + throw new IllegalStateException("error on verifying signed message for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + + //extracted decrypted and verified message + byte[] preHeader = "Content-Type: message/rfc822\r\n\r\n".getBytes(StandardCharsets.UTF_8); + int preHeaderLength = preHeader.length; + byte[] signedContentPayload = Arrays.copyOfRange(signedContent, preHeaderLength, signedContent.length); + MimeMessage decryptedAndVerifiedMessage = new MimeMessage(Session.getInstance(new Properties()), new ByteArrayInputStream(signedContentPayload)); + + MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.FROM); + MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.SENDER); + MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.REPLY_TO); + MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.TO); + MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.CC); + MailUtils.checkHeader(logger, konnektor, encryptedMsg, decryptedAndVerifiedMessage, MailUtils.BCC); + + //set header Return-Path, Received + logger.logLine("set " + MailUtils.RETURN_PATH); + String[] returnPath = encryptedMsg.getHeader(MailUtils.RETURN_PATH); + if (returnPath != null && returnPath.length > 0) { + decryptedAndVerifiedMessage.setHeader(MailUtils.RETURN_PATH, returnPath[0]); + } + logger.logLine("set " + MailUtils.RECEIVED); + String[] received = encryptedMsg.getHeader(MailUtils.RECEIVED); + if (received != null && received.length > 0) { + for (int i = 0; i < received.length; i++) { + decryptedAndVerifiedMessage.addHeader(MailUtils.RECEIVED, received[i]); + } + } + logger.logLine("set " + MailUtils.REPLY_TO); + String[] replyTo = encryptedMsg.getHeader(MailUtils.REPLY_TO); + if (replyTo != null && replyTo.length > 0) { + decryptedAndVerifiedMessage.setHeader(MailUtils.REPLY_TO, replyTo[0]); + } + + //add signature report + defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_ATTACHMENT, signReportFile); + defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_CONTENT_TYPE, "application/pdf"); + defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_ATTACHMENT_NAME, "Signaturpruefbericht.pdf"); + defaultPipelineOperationContext.setEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_MSG, decryptedAndVerifiedMessage); + + AtomicInteger addAtachmentFailedCounter = new AtomicInteger(); + addMailAttachmentOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("add signatur file finished"); + }, + (context, e) -> { + log.error("error on adding of signatur file", e); + addAtachmentFailedCounter.incrementAndGet(); + } + ); + + if (addAtachmentFailedCounter.get() == 0) { + decryptedAndVerifiedMessage = (MimeMessage) defaultPipelineOperationContext.getEnvironmentValue(AddMailAttachmentOperation.NAME, AddMailAttachmentOperation.ENV_RESULT_MSG); + } else { + throw new IllegalStateException("error on adding signature file for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + + //add signature text + defaultPipelineOperationContext.setEnvironmentValue(AddMailTextOperation.NAME, AddMailTextOperation.ENV_TEXT, "----------------------------------\n!!!Die Signatur wurde erfolgreich geprueft!!!\n----------------------------------"); + defaultPipelineOperationContext.setEnvironmentValue(AddMailTextOperation.NAME, AddMailTextOperation.ENV_MSG, decryptedAndVerifiedMessage); + + AtomicInteger addTextFailedCounter = new AtomicInteger(); + addMailTextOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("add text finished"); + }, + (context, e) -> { + log.error("error on adding of text", e); + addTextFailedCounter.incrementAndGet(); + } + ); + + if (addTextFailedCounter.get() == 0) { + decryptedAndVerifiedMessage = (MimeMessage) defaultPipelineOperationContext.getEnvironmentValue(AddMailTextOperation.NAME, AddMailTextOperation.ENV_RESULT_MSG); + } else { + throw new IllegalStateException("error on adding text for konnektor: " + konnektor.getIp() + " and the user mail address: " + userMailAddress); + } + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + decryptedAndVerifiedMessage.writeTo(byteArrayOutputStream); + byte[] result = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + defaultPipelineOperationContext.setEnvironmentValue(NAME, ENV_RESULT_MSG_BYTES, result); + } + + timeMetric.stopAndPublish(); + okConsumer.accept(defaultPipelineOperationContext); + } + catch (Exception e) { + log.error("error on executing the DecryptVerifyMailOperation for the konnektor: " + konnektor.getIp(), e); + if (timeMetric != null) { + timeMetric.stopAndPublish(); + } + + failConsumer.accept(defaultPipelineOperationContext, e); + } + } +} diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/mail/SignEncryptMailOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/mail/SignEncryptMailOperation.java new file mode 100644 index 0000000..b03b398 --- /dev/null +++ b/src/main/java/net/sberg/openkim/pipeline/operation/mail/SignEncryptMailOperation.java @@ -0,0 +1,314 @@ +/* + * Copyright 2023 sberg it-systeme GmbH + * + * 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://ec.europa.eu/idabc/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. + */ +package net.sberg.openkim.pipeline.operation.mail; + +import de.gematik.ws.conn.connectorcommon.DocumentType; +import de.gematik.ws.conn.encryptionservice.v6_1_1.EncryptDocumentResponse; +import de.gematik.ws.conn.signatureservice.v7_5_5.SignDocumentResponse; +import de.gematik.ws.conn.signatureservice.v7_5_5.SignResponse; +import net.sberg.openkim.common.metrics.DefaultMetricFactory; +import net.sberg.openkim.common.x509.CMSUtils; +import net.sberg.openkim.common.x509.X509CertificateResult; +import net.sberg.openkim.konnektor.Konnektor; +import net.sberg.openkim.log.DefaultLogger; +import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; +import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; +import net.sberg.openkim.pipeline.operation.IPipelineOperation; +import net.sberg.openkim.pipeline.operation.konnektor.GetSignCardHandleOperation; +import net.sberg.openkim.pipeline.operation.konnektor.webservice.EncryptMailOperation; +import net.sberg.openkim.pipeline.operation.konnektor.webservice.SignMailOperation; +import oasis.names.tc.dss._1_0.core.schema.SignatureObject; +import org.apache.james.metrics.api.TimeMetric; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.BodyPart; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +@PipelineOperation +public class SignEncryptMailOperation implements IPipelineOperation { + + private static final Logger log = LoggerFactory.getLogger(SignEncryptMailOperation.class); + public static final String NAME = "SignEncryptMail"; + + public static final String ENV_ORIGIN_MIMEMESSAGE = "originMimeMessage"; + public static final String ENV_RECIPIENT_CERTS = "recipientCerts"; + public static final String ENV_FROM_SENDER_CERTS = "fromSenderCerts"; + public static final String ENV_RESULT_MSG_BYTES = "resultMsgBytes"; + + private CheckEncryptedMailFormatOperation checkEncryptedMailFormatOperation; + private GetSignCardHandleOperation getSignCardHandleOperation; + private SignMailOperation signMailOperation; + private EncryptMailOperation encryptMailOperation; + private ComposeEncryptedMailOperation composeEncryptedMailOperation; + + @Override + public void initialize(PipelineService pipelineService) throws Exception { + checkEncryptedMailFormatOperation = (CheckEncryptedMailFormatOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+CheckEncryptedMailFormatOperation.NAME); + getSignCardHandleOperation = (GetSignCardHandleOperation) pipelineService.getOperation(BUILTIN_VENDOR + "." + GetSignCardHandleOperation.NAME); + signMailOperation = (SignMailOperation) pipelineService.getOperation(BUILTIN_VENDOR + "." + SignMailOperation.NAME); + encryptMailOperation = (EncryptMailOperation) pipelineService.getOperation(BUILTIN_VENDOR + "." + EncryptMailOperation.NAME); + composeEncryptedMailOperation = (ComposeEncryptedMailOperation) pipelineService.getOperation(BUILTIN_VENDOR + "." + ComposeEncryptedMailOperation.NAME); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public Consumer getDefaultOkConsumer() { + throw new IllegalStateException("not implemented"); + } + + @Override + public void execute(DefaultPipelineOperationContext defaultPipelineOperationContext, Consumer okConsumer, BiConsumer failConsumer) { + TimeMetric timeMetric = null; + + DefaultLogger logger = defaultPipelineOperationContext.getLogger(); + Konnektor konnektor = logger.getDefaultLoggerContext().getKonnektor(); + + try { + DefaultMetricFactory metricFactory = new DefaultMetricFactory(logger); + timeMetric = metricFactory.timer(NAME); + + MimeMessage originMimeMessage = (MimeMessage)defaultPipelineOperationContext.getEnvironmentValue(NAME, ENV_ORIGIN_MIMEMESSAGE); + List recipientCerts = (List)defaultPipelineOperationContext.getEnvironmentValue(NAME, ENV_RECIPIENT_CERTS); + List fromSenderCerts = (List)defaultPipelineOperationContext.getEnvironmentValue(NAME, ENV_FROM_SENDER_CERTS); + + //is a mimebodypart encrypted? + boolean encrypted = false; + if (originMimeMessage.isMimeType("multipart/mixed") + && + originMimeMessage.getContent() instanceof MimeMultipart + && + ((MimeMultipart) originMimeMessage.getContent()).getCount() == 2 + ) { + MimeMultipart mimeMultipart = (MimeMultipart) originMimeMessage.getContent(); + BodyPart bodyPart = null; + if (mimeMultipart.getBodyPart(0).isMimeType("message/rfc822")) { + bodyPart = mimeMultipart.getBodyPart(0); + } + else if (mimeMultipart.getBodyPart(1).isMimeType("message/rfc822")) { + bodyPart = mimeMultipart.getBodyPart(1); + } + if (bodyPart != null) { + MimeMessage encryptedBodyPart = MailUtils.createMimeMessage(null, bodyPart.getInputStream(), true); + + defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_ENCRYPTED_MSG, encryptedBodyPart); + defaultPipelineOperationContext.setEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_DECRYPT_MODE, false); + + checkEncryptedMailFormatOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("checking encrypted mail format finished"); + }, + (context, e) -> { + log.error("error on checking encrypted mail format", e); + } + ); + + boolean valid = (boolean)defaultPipelineOperationContext.getEnvironmentValue(CheckEncryptedMailFormatOperation.NAME, CheckEncryptedMailFormatOperation.ENV_VALID_RESULT); + if (valid && logger.getDefaultLoggerContext().getMailEncryptFormatErrorContext().isEmpty()) { + logger.logLine("bodypart is encrypted"); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + encryptedBodyPart.writeTo(byteArrayOutputStream); + byte[] result = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + defaultPipelineOperationContext.setEnvironmentValue(NAME, ENV_RESULT_MSG_BYTES, result); + encrypted = true; + } + else { + logger.logLine("bodypart is not encrypted"); + } + } + } + + if (!encrypted) { + //get card handle + getSignCardHandleOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("loading of signing card handle finished"); + }, + (context, e) -> { + log.error("error on loading of signing card handle", e); + } + ); + + boolean cardHandleFound = (boolean) defaultPipelineOperationContext.getEnvironmentValue(GetSignCardHandleOperation.NAME, GetSignCardHandleOperation.ENV_RESULT_CARD_HANDLE_FOUND); + if (!cardHandleFound) { + throw new IllegalStateException("card handle not found"); + } + String cardSignHandle = (String) defaultPipelineOperationContext.getEnvironmentValue(GetSignCardHandleOperation.NAME, GetSignCardHandleOperation.ENV_RESULT_CARD_HANDLE); + + List recipientSenderCerts = new ArrayList<>(recipientCerts); + boolean add = true; + for (Iterator iterator = fromSenderCerts.iterator(); iterator.hasNext(); ) { + add = true; + X509CertificateResult fromSender = iterator.next(); + for (Iterator iterator2 = recipientSenderCerts.iterator(); iterator2.hasNext(); ) { + X509CertificateResult x509CertificateResult = iterator2.next(); + if (x509CertificateResult.getMailAddress().equals(fromSender.getMailAddress().toLowerCase())) { + add = false; + break; + } + } + if (add) { + recipientSenderCerts.add(fromSender); + } + } + + //signing mail + defaultPipelineOperationContext.setEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_CARDHANDLE, cardSignHandle); + defaultPipelineOperationContext.setEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_MIMEMESSAGE, originMimeMessage); + defaultPipelineOperationContext.setEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_VZD_CERTS, recipientSenderCerts); + + AtomicInteger failedCounter = new AtomicInteger(); + signMailOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("signing mail finished"); + }, + (context, e) -> { + log.error("error on signing mail", e); + failedCounter.incrementAndGet(); + } + ); + + byte[] signedMsg = null; + if (failedCounter.get() == 0) { + SignDocumentResponse signDocumentResponse = (SignDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(SignMailOperation.NAME, SignMailOperation.ENV_SIGN_DOCUMENT_RESPONSE); + if (signDocumentResponse.getSignResponse().isEmpty()) { + throw new IllegalStateException("empty sign response for the cardHandle: " + cardSignHandle); + } + SignResponse signResponse = signDocumentResponse.getSignResponse().get(0); + if (!signResponse.getStatus().getResult().equals("OK")) { + throw new IllegalStateException("sign response not ok for the cardHandle: " + cardSignHandle + " - " + signResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + signResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); + } + SignatureObject signatureObject = signResponse.getSignatureObject(); + if (signatureObject == null) { + throw new IllegalStateException("sign response signatureObject empty for the cardHandle: " + cardSignHandle); + } + if (signatureObject.getBase64Signature().getValue() == null) { + throw new IllegalStateException("sign response signatureObject empty for the cardHandle: " + cardSignHandle); + } + + MimeBodyPart mimeBodyPartSignedMsg = new MimeBodyPart(); + mimeBodyPartSignedMsg.setContent(signatureObject.getBase64Signature().getValue(), CMSUtils.SMIME_CONTENT_TYPE); + mimeBodyPartSignedMsg.setHeader("Content-Type", CMSUtils.SMIME_CONTENT_TYPE); + mimeBodyPartSignedMsg.setHeader("Content-Transfer-Encoding", "binary"); + mimeBodyPartSignedMsg.setDisposition(CMSUtils.SMIME_DISPOSITION); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + mimeBodyPartSignedMsg.writeTo(byteArrayOutputStream); + signedMsg = byteArrayOutputStream.toByteArray(); + byteArrayOutputStream.close(); + + if (signedMsg == null) { + throw new IllegalStateException("error on signing mail"); + } + } else { + throw new IllegalStateException("error on signing mail"); + } + + //encrypting mail + defaultPipelineOperationContext.setEnvironmentValue(EncryptMailOperation.NAME, EncryptMailOperation.ENV_SIGNED_MAIL, signedMsg); + defaultPipelineOperationContext.setEnvironmentValue(EncryptMailOperation.NAME, EncryptMailOperation.ENV_VZD_CERTS, recipientSenderCerts); + + AtomicInteger encryptFailedCounter = new AtomicInteger(); + encryptMailOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("encrypting mail finished"); + }, + (context, e) -> { + log.error("error on encrypting mail", e); + encryptFailedCounter.incrementAndGet(); + } + ); + + byte[] encryptedMsg = null; + if (encryptFailedCounter.get() == 0) { + EncryptDocumentResponse encryptDocumentResponse = (EncryptDocumentResponse) defaultPipelineOperationContext.getEnvironmentValue(EncryptMailOperation.NAME, EncryptMailOperation.ENV_ENCRYPT_DOCUMENT_RESPONSE); + if (!encryptDocumentResponse.getStatus().getResult().equals("OK")) { + throw new IllegalStateException("encrypt response not ok for the konnektor: " + konnektor.getIp() + " - " + encryptDocumentResponse.getStatus().getError().getTrace().get(0).getErrorText() + " - " + encryptDocumentResponse.getStatus().getError().getTrace().get(0).getDetail().getValue()); + } + DocumentType documentType = encryptDocumentResponse.getDocument(); + if (documentType == null) { + throw new IllegalStateException("encrypt response document empty for the konnektor: " + konnektor.getIp()); + } + if (documentType.getBase64Data().getValue() == null) { + throw new IllegalStateException("encrypt response document empty for the konnektor: " + konnektor.getIp()); + } + + encryptedMsg = documentType.getBase64Data().getValue(); + if (encryptedMsg == null) { + throw new IllegalStateException("error on encrypting mail"); + } + } else { + throw new IllegalStateException("error on encrypting mail"); + } + + //compose encrypting mail + defaultPipelineOperationContext.setEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_ENCRYPTED_MSG, encryptedMsg); + defaultPipelineOperationContext.setEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_RECIPIENT_CERTS, recipientSenderCerts); + defaultPipelineOperationContext.setEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_ORIGIN_MSG, originMimeMessage); + + AtomicInteger composeEncryptedMsgFailedCounter = new AtomicInteger(); + composeEncryptedMailOperation.execute( + defaultPipelineOperationContext, + context -> { + log.info("composing mail finished"); + }, + (context, e) -> { + log.error("error on composing mail", e); + composeEncryptedMsgFailedCounter.incrementAndGet(); + } + ); + + if (composeEncryptedMsgFailedCounter.get() == 0) { + byte[] result = (byte[]) defaultPipelineOperationContext.getEnvironmentValue(ComposeEncryptedMailOperation.NAME, ComposeEncryptedMailOperation.ENV_RESULT_MSG_BYTES); + defaultPipelineOperationContext.setEnvironmentValue(NAME, ENV_RESULT_MSG_BYTES, result); + } else { + throw new IllegalStateException("error on composing mail"); + } + } + + timeMetric.stopAndPublish(); + okConsumer.accept(defaultPipelineOperationContext); + } + catch (Exception e) { + log.error("error on executing the SignEncryptMailOperation for the konnektor: " + konnektor.getIp(), e); + if (timeMetric != null) { + timeMetric.stopAndPublish(); + } + + failConsumer.accept(defaultPipelineOperationContext, e); + } + } +} diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailAttachmentOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailAttachmentOperation.java index 1c06ed6..bba5098 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailAttachmentOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailAttachmentOperation.java @@ -20,6 +20,7 @@ import net.sberg.openkim.konnektor.Konnektor; import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import org.apache.james.metrics.api.TimeMetric; @@ -50,8 +51,9 @@ public class AddMailAttachmentOperation implements IPipelineOperation { private AnalyzeMailPartsOperation analyzeMailPartsOperation; - public void setAnalyzeMailPartsOperation(AnalyzeMailPartsOperation analyzeMailPartsOperation) { - this.analyzeMailPartsOperation = analyzeMailPartsOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + analyzeMailPartsOperation = (AnalyzeMailPartsOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+AnalyzeMailPartsOperation.NAME); } @Override diff --git a/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailTextOperation.java b/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailTextOperation.java index 7289b5d..4a6b1e6 100644 --- a/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailTextOperation.java +++ b/src/main/java/net/sberg/openkim/pipeline/operation/mail/part/AddMailTextOperation.java @@ -20,6 +20,7 @@ import net.sberg.openkim.konnektor.Konnektor; import net.sberg.openkim.log.DefaultLogger; import net.sberg.openkim.pipeline.PipelineOperation; +import net.sberg.openkim.pipeline.PipelineService; import net.sberg.openkim.pipeline.operation.DefaultPipelineOperationContext; import net.sberg.openkim.pipeline.operation.IPipelineOperation; import org.apache.james.metrics.api.TimeMetric; @@ -45,8 +46,9 @@ public class AddMailTextOperation implements IPipelineOperation { private AnalyzeMailPartsOperation analyzeMailPartsOperation; - public void setAnalyzeMailPartsOperation(AnalyzeMailPartsOperation analyzeMailPartsOperation) { - this.analyzeMailPartsOperation = analyzeMailPartsOperation; + @Override + public void initialize(PipelineService pipelineService) throws Exception { + analyzeMailPartsOperation = (AnalyzeMailPartsOperation) pipelineService.getOperation(BUILTIN_VENDOR+"."+AnalyzeMailPartsOperation.NAME); } @Override