Search in sources :

Example 1 with AS2DispositionException

use of com.helger.as2lib.disposition.AS2DispositionException in project as2-lib by phax.

the class AS2SenderModule method _sendViaHTTP.

private void _sendViaHTTP(@Nonnull final AS2Message aMsg, @Nonnull final MimeBodyPart aSecuredMimePart, @Nullable final MIC aMIC, @Nullable final EContentTransferEncoding eCTE, @Nullable final IHTTPOutgoingDumper aOutgoingDumper, @Nullable final IHTTPIncomingDumper aIncomingDumper, @Nonnull final AS2ResourceHelper aResHelper) throws AS2Exception, IOException, MessagingException {
    final Partnership aPartnership = aMsg.partnership();
    // Create the HTTP connection
    final String sUrl = aPartnership.getAS2URL();
    final EHttpMethod eRequestMethod = EHttpMethod.POST;
    // decide on the connection type to use according to the MimeBodyPart:
    // If it contains the data, (and no DataHandler), then use HttpUrlClient,
    // otherwise, use HttpClient
    final AS2HttpClient aConn = getHttpClient(sUrl, eRequestMethod, getSession().getHttpProxy());
    try {
        if (aOutgoingDumper != null)
            aOutgoingDumper.start(sUrl, aMsg);
        if (LOGGER.isInfoEnabled())
            LOGGER.info("Connecting to " + sUrl + aMsg.getLoggingText());
        final boolean bQuoteHeaderValues = isQuoteHeaderValues();
        updateHttpHeaders(new AS2HttpHeaderSetter(aConn, aOutgoingDumper, bQuoteHeaderValues), aMsg);
        if (aOutgoingDumper != null)
            aOutgoingDumper.finishedHeaders();
        aMsg.attrs().putIn(CNetAttribute.MA_DESTINATION_IP, aConn.getURL().getHost());
        aMsg.attrs().putIn(CNetAttribute.MA_DESTINATION_PORT, aConn.getURL().getPort());
        final InputStream aMsgIS = aSecuredMimePart.getInputStream();
        // Transfer the data
        final StopWatch aSW = StopWatch.createdStarted();
        final long nBytes = aConn.send(aMsgIS, eCTE, aOutgoingDumper, aResHelper);
        aSW.stop();
        if (LOGGER.isInfoEnabled())
            LOGGER.info("AS2 Message transferred " + AS2IOHelper.getTransferRate(nBytes, aSW) + aMsg.getLoggingText());
        if (aOutgoingDumper != null)
            aOutgoingDumper.finishedPayload();
        final int nHttpResponseCode = aConn.getResponseCode();
        if (getOutgoingHttpCallback() != null)
            getOutgoingHttpCallback().onOutgoingHttpMessage(true, aMsg.getAS2From(), aMsg.getAS2To(), aMsg.getMessageID(), aMIC == null ? null : aMIC.getClone(), eCTE, sUrl, nHttpResponseCode);
        // Check the HTTP Response code
        if (AS2HttpClient.isErrorResponseCode(nHttpResponseCode)) {
            if (LOGGER.isErrorEnabled())
                LOGGER.error("Error URL '" + sUrl + "' - HTTP " + nHttpResponseCode + " " + aConn.getResponseMessage() + " " + aMsg.getLoggingText());
            throw new AS2HttpResponseException(sUrl, nHttpResponseCode, aConn.getResponseMessage());
        }
        // Receive an MDN
        try {
            // Receive an MDN
            if (aMsg.isRequestingMDN()) {
                // Check if the AsyncMDN is required
                if (aPartnership.getAS2ReceiptDeliveryOption() == null) {
                    // Note: If an MDN is requested, a MIC is present
                    assert aMIC != null;
                    receiveSyncMDN(aMsg, aConn, aMIC, aIncomingDumper, aResHelper);
                    if (LOGGER.isInfoEnabled())
                        LOGGER.info("message sent" + aMsg.getLoggingText());
                }
            }
        } catch (final AS2DispositionException ex) {
            // was not successful
            throw ex;
        } catch (final AS2Exception ex) {
            // Don't re-send or fail, just log an error if one occurs while
            // receiving the MDN
            onReceivedMDNError(aMsg, ex);
        }
    } finally {
        // Closes all resources
        aConn.disconnect();
    }
}
Also used : InputStream(java.io.InputStream) StopWatch(com.helger.commons.timing.StopWatch) AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) AS2HttpHeaderSetter(com.helger.as2lib.util.http.AS2HttpHeaderSetter) Partnership(com.helger.as2lib.partner.Partnership) EHttpMethod(com.helger.commons.http.EHttpMethod) AS2Exception(com.helger.as2lib.exception.AS2Exception) WrappedAS2Exception(com.helger.as2lib.exception.WrappedAS2Exception) AS2HttpClient(com.helger.as2lib.util.http.AS2HttpClient)

Example 2 with AS2DispositionException

use of com.helger.as2lib.disposition.AS2DispositionException in project as2-lib by phax.

the class MessageFileModule method handle.

public void handle(@Nonnull final String sAction, @Nonnull final IMessage aMsg, @Nullable final Map<String, Object> aOptions) throws AS2Exception {
    // store message content
    try {
        final File aMsgFile = getFile(aMsg, getAttributeAsStringRequired(ATTR_FILENAME));
        try (final InputStream aIS = aMsg.getData().getInputStream()) {
            store(aMsgFile, aIS);
        }
        aMsg.attrs().put(MessageParameters.ATTR_STORED_FILE_NAME, aMsgFile.getAbsolutePath());
        LOGGER.info("stored message to " + aMsgFile.getAbsolutePath() + aMsg.getLoggingText());
    } catch (final AS2DispositionException ex) {
        // Re-throw "as is"
        throw ex;
    } catch (final Exception ex) {
        throw AS2DispositionException.wrap(ex, () -> DispositionType.createError("error-storing-transaction"), () -> AbstractActiveNetModule.DISP_STORAGE_FAILED);
    }
    // Store message headers and attributes
    final String sHeaderFilename = getHeaderFilename();
    if (sHeaderFilename != null) {
        try {
            final File aHeaderFile = getFile(aMsg, sHeaderFilename);
            try (final InputStream aIS = getHeaderStream(aMsg, getCharset())) {
                store(aHeaderFile, aIS);
            }
            LOGGER.info("stored headers to " + aHeaderFile.getAbsolutePath() + aMsg.getLoggingText());
        } catch (final IOException ex) {
            throw WrappedAS2Exception.wrap(ex);
        }
    }
}
Also used : AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) StringInputStream(com.helger.commons.io.stream.StringInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) File(java.io.File) AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) IOException(java.io.IOException) AS2InvalidParameterException(com.helger.as2lib.params.AS2InvalidParameterException) AS2Exception(com.helger.as2lib.exception.AS2Exception) WrappedAS2Exception(com.helger.as2lib.exception.WrappedAS2Exception)

Example 3 with AS2DispositionException

use of com.helger.as2lib.disposition.AS2DispositionException in project as2-lib by phax.

the class AS2ReceiverHandler method handleIncomingMessage.

/**
 * This method can be used to handle an incoming HTTP message AFTER the
 * headers where extracted.
 *
 * @param sClientInfo
 *        Client connection info
 * @param aMsgData
 *        The message body
 * @param aMsg
 *        The AS2 message that will be filled by this method
 * @param aResponseHandler
 *        The response handler which handles HTTP error messages as well as
 *        synchronous MDN.
 */
public void handleIncomingMessage(@Nonnull final String sClientInfo, @Nonnull final DataSource aMsgData, @Nonnull final AS2Message aMsg, @Nonnull final IAS2HttpResponseHandler aResponseHandler) {
    // handler, to avoid the decrypted content gets removed (see issue #135)
    try (final AS2ResourceHelper aResHelper = new AS2ResourceHelper()) {
        try {
            final IAS2Session aSession = m_aReceiverModule.getSession();
            try {
                // Put received data in a MIME body part
                final String sReceivedContentType = AS2HttpHelper.getCleanContentType(aMsg.getHeader(CHttpHeader.CONTENT_TYPE));
                final MimeBodyPart aReceivedPart = new MimeBodyPart();
                aReceivedPart.setDataHandler(new DataHandler(aMsgData));
                // Header must be set AFTER the DataHandler!
                aReceivedPart.setHeader(CHttpHeader.CONTENT_TYPE, sReceivedContentType);
                aMsg.setData(aReceivedPart);
            } catch (final Exception ex) {
                throw new AS2DispositionException(DispositionType.createError("unexpected-processing-error"), AbstractActiveNetModule.DISP_PARSING_MIME_FAILED, ex);
            }
            // update the message
            try {
                final String sAS2From = aMsg.getAS2From();
                aMsg.partnership().setSenderAS2ID(sAS2From);
                final String sAS2To = aMsg.getAS2To();
                aMsg.partnership().setReceiverAS2ID(sAS2To);
                // Fill all partnership attributes etc.
                aSession.getPartnershipFactory().updatePartnership(aMsg, false);
            } catch (final AS2Exception ex) {
                throw AS2DispositionException.wrap(ex, () -> DispositionType.createError("authentication-failed"), () -> AbstractActiveNetModule.DISP_PARTNERSHIP_NOT_FOUND);
            }
            // Per RFC5402 compression is always before encryption but can be before
            // or after signing of message but only in one place
            final ICryptoHelper aCryptoHelper = AS2Helper.getCryptoHelper();
            boolean bIsDecompressed = false;
            // Decrypt and verify signature of the data, and attach data to the
            // message
            decrypt(aMsg, aResHelper);
            if (aCryptoHelper.isCompressed(aMsg.getContentType())) {
                if (LOGGER.isTraceEnabled())
                    LOGGER.trace("Decompressing received message before checking signature...");
                decompress(aMsg);
                bIsDecompressed = true;
            }
            verify(aMsg, aResHelper);
            if (aCryptoHelper.isCompressed(aMsg.getContentType())) {
                // or after signing of message but only in one place
                if (bIsDecompressed) {
                    throw new AS2DispositionException(DispositionType.createError("decompression-failed"), AbstractActiveNetModule.DISP_DECOMPRESSION_ERROR, new Exception("Message has already been decompressed. Per RFC5402 it cannot occur twice."));
                }
                if (LOGGER.isTraceEnabled())
                    if (aMsg.attrs().containsKey(AS2Message.ATTRIBUTE_RECEIVED_SIGNED))
                        LOGGER.trace("Decompressing received message after verifying signature...");
                    else
                        LOGGER.trace("Decompressing received message after decryption...");
                decompress(aMsg);
                bIsDecompressed = true;
            }
            if (LOGGER.isTraceEnabled())
                try {
                    LOGGER.trace("SMIME Decrypted Content-Disposition: " + aMsg.getContentDisposition() + "\n      Content-Type received: " + aMsg.getContentType() + "\n      HEADERS after decryption: " + aMsg.getData().getAllHeaders() + "\n      Content-Disposition in MSG detData() MIMEPART after decryption: " + aMsg.getData().getContentType());
                } catch (final MessagingException ex) {
                    if (LOGGER.isErrorEnabled())
                        LOGGER.error("Failed to trace message: " + aMsg, ex);
                }
            // Validate the received message before storing
            try {
                aSession.getMessageProcessor().handle(IProcessorStorageModule.DO_VALIDATE_BEFORE_STORE, aMsg, null);
            } catch (final AS2NoModuleException ex) {
            // No module installed - ignore
            } catch (final AS2Exception ex) {
                // Issue 90 - use CRLF as separator
                throw AS2DispositionException.wrap(ex, () -> DispositionType.createError("unexpected-processing-error"), () -> StringHelper.getConcatenatedOnDemand(AbstractActiveNetModule.DISP_VALIDATION_FAILED, CHttp.EOL, _getDispositionText(ex)));
            }
            // Store the received message
            try {
                aSession.getMessageProcessor().handle(IProcessorStorageModule.DO_STORE, aMsg, null);
            } catch (final AS2NoModuleException ex) {
            // No module installed - ignore
            } catch (final AS2Exception ex) {
                // Issue 90 - use CRLF as separator
                throw AS2DispositionException.wrap(ex, () -> DispositionType.createError("unexpected-processing-error"), () -> StringHelper.getConcatenatedOnDemand(AbstractActiveNetModule.DISP_STORAGE_FAILED, CHttp.EOL, _getDispositionText(ex)));
            }
            // Validate the received message after storing
            try {
                aSession.getMessageProcessor().handle(IProcessorStorageModule.DO_VALIDATE_AFTER_STORE, aMsg, null);
            } catch (final AS2NoModuleException ex) {
            // No module installed - ignore
            } catch (final AS2Exception ex) {
                // Issue 90 - use CRLF as separator
                throw AS2DispositionException.wrap(ex, () -> DispositionType.createError("unexpected-processing-error"), () -> StringHelper.getConcatenatedOnDemand(AbstractActiveNetModule.DISP_VALIDATION_FAILED, CHttp.EOL, _getDispositionText(ex)));
            }
            try {
                if (aMsg.isRequestingMDN()) {
                    if (LOGGER.isTraceEnabled())
                        LOGGER.trace("AS2 message is requesting an MDN");
                    // Transmit a success MDN if requested
                    sendMDN(sClientInfo, aResponseHandler, aMsg, DispositionType.createSuccess(), AbstractActiveNetModule.DISP_SUCCESS, ESuccess.SUCCESS);
                } else {
                    if (LOGGER.isTraceEnabled())
                        LOGGER.trace("AS2 message is not requesting an MDN - just sending HTTP 200 (OK)");
                    // Just send a HTTP OK
                    HTTPHelper.sendSimpleHTTPResponse(aResponseHandler, CHttp.HTTP_OK);
                    if (LOGGER.isInfoEnabled())
                        LOGGER.info("sent HTTP OK " + sClientInfo + aMsg.getLoggingText());
                }
            } catch (final Exception ex) {
                throw new AS2Exception("Error creating and returning MDN, message was stilled processed", ex);
            }
        } catch (final AS2DispositionException ex) {
            sendMDN(sClientInfo, aResponseHandler, aMsg, ex.getDisposition(), ex.getText(), ESuccess.FAILURE);
            m_aReceiverModule.handleError(aMsg, ex);
        } catch (final AS2Exception ex) {
            m_aReceiverModule.handleError(aMsg, ex);
        } finally {
            // close the temporary shared stream if it exists
            final TempSharedFileInputStream sis = aMsg.getTempSharedFileInputStream();
            if (null != sis) {
                try {
                    sis.closeAll();
                } catch (final IOException e) {
                    LOGGER.error("Exception while closing TempSharedFileInputStream", e);
                }
            }
        }
    }
}
Also used : MessagingException(javax.mail.MessagingException) TempSharedFileInputStream(com.helger.as2lib.util.http.TempSharedFileInputStream) DataHandler(javax.activation.DataHandler) IOException(java.io.IOException) ICryptoHelper(com.helger.as2lib.crypto.ICryptoHelper) MessagingException(javax.mail.MessagingException) AS2NoModuleException(com.helger.as2lib.processor.AS2NoModuleException) AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) AS2ProcessorException(com.helger.as2lib.processor.AS2ProcessorException) CMSException(org.bouncycastle.cms.CMSException) AS2Exception(com.helger.as2lib.exception.AS2Exception) WrappedAS2Exception(com.helger.as2lib.exception.WrappedAS2Exception) IOException(java.io.IOException) SMIMEException(org.bouncycastle.mail.smime.SMIMEException) AS2ComponentNotFoundException(com.helger.as2lib.session.AS2ComponentNotFoundException) IAS2Session(com.helger.as2lib.session.IAS2Session) AS2ResourceHelper(com.helger.as2lib.util.AS2ResourceHelper) AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) AS2NoModuleException(com.helger.as2lib.processor.AS2NoModuleException) AS2Exception(com.helger.as2lib.exception.AS2Exception) WrappedAS2Exception(com.helger.as2lib.exception.WrappedAS2Exception) MimeBodyPart(javax.mail.internet.MimeBodyPart)

Example 4 with AS2DispositionException

use of com.helger.as2lib.disposition.AS2DispositionException in project as2-lib by phax.

the class AS2ReceiverHandler method decrypt.

protected void decrypt(@Nonnull final IMessage aMsg, @Nonnull final AS2ResourceHelper aResHelper) throws AS2Exception {
    final ICertificateFactory aCertFactory = m_aReceiverModule.getSession().getCertificateFactory();
    final ICryptoHelper aCryptoHelper = AS2Helper.getCryptoHelper();
    try {
        final boolean bDisableDecrypt = aMsg.partnership().isDisableDecrypt();
        final boolean bMsgIsEncrypted = aCryptoHelper.isEncrypted(aMsg.getData());
        final boolean bForceDecrypt = aMsg.partnership().isForceDecrypt();
        if (bMsgIsEncrypted && bDisableDecrypt) {
            if (LOGGER.isInfoEnabled())
                LOGGER.info("Message claims to be encrypted but decryption is disabled" + aMsg.getLoggingText());
        } else if (bMsgIsEncrypted || bForceDecrypt) {
            // Decrypt
            if (bForceDecrypt && !bMsgIsEncrypted) {
                if (LOGGER.isInfoEnabled())
                    LOGGER.info("Forced decrypting" + aMsg.getLoggingText());
            } else if (LOGGER.isDebugEnabled())
                LOGGER.debug("Decrypting" + aMsg.getLoggingText());
            final X509Certificate aReceiverCert = aCertFactory.getCertificate(aMsg, ECertificatePartnershipType.RECEIVER);
            final PrivateKey aReceiverKey = aCertFactory.getPrivateKey(aReceiverCert);
            final MimeBodyPart aDecryptedData = aCryptoHelper.decrypt(aMsg.getData(), aReceiverCert, aReceiverKey, bForceDecrypt, aResHelper);
            aMsg.setData(aDecryptedData);
            // Remember that message was encrypted
            aMsg.attrs().putIn(AS2Message.ATTRIBUTE_RECEIVED_ENCRYPTED, true);
            if (LOGGER.isInfoEnabled())
                LOGGER.info("Successfully decrypted incoming AS2 message" + aMsg.getLoggingText());
        }
    } catch (final AS2DispositionException ex) {
        // Re-throw "as is"
        throw ex;
    } catch (final Exception ex) {
        if (LOGGER.isErrorEnabled())
            LOGGER.error("Error decrypting " + aMsg.getLoggingText() + ": " + ex.getMessage());
        throw new AS2DispositionException(DispositionType.createError("decryption-failed"), AbstractActiveNetModule.DISP_DECRYPTION_ERROR, ex);
    }
}
Also used : AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) PrivateKey(java.security.PrivateKey) ICertificateFactory(com.helger.as2lib.cert.ICertificateFactory) ICryptoHelper(com.helger.as2lib.crypto.ICryptoHelper) MimeBodyPart(javax.mail.internet.MimeBodyPart) X509Certificate(java.security.cert.X509Certificate) MessagingException(javax.mail.MessagingException) AS2NoModuleException(com.helger.as2lib.processor.AS2NoModuleException) AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) AS2ProcessorException(com.helger.as2lib.processor.AS2ProcessorException) CMSException(org.bouncycastle.cms.CMSException) AS2Exception(com.helger.as2lib.exception.AS2Exception) WrappedAS2Exception(com.helger.as2lib.exception.WrappedAS2Exception) IOException(java.io.IOException) SMIMEException(org.bouncycastle.mail.smime.SMIMEException) AS2ComponentNotFoundException(com.helger.as2lib.session.AS2ComponentNotFoundException)

Example 5 with AS2DispositionException

use of com.helger.as2lib.disposition.AS2DispositionException in project as2-lib by phax.

the class AS2ReceiverHandler method decompress.

protected void decompress(@Nonnull final IMessage aMsg) throws AS2DispositionException {
    try {
        if (aMsg.partnership().isDisableDecompress()) {
            if (LOGGER.isInfoEnabled())
                LOGGER.info("Message claims to be compressed but decompression is disabled" + aMsg.getLoggingText());
        } else {
            if (LOGGER.isDebugEnabled())
                LOGGER.debug("Decompressing a compressed AS2 message");
            MimeBodyPart aDecompressedPart;
            final ZlibExpanderProvider aExpander = new ZlibExpanderProvider();
            // Compress using stream
            if (LOGGER.isDebugEnabled()) {
                final StringBuilder aSB = new StringBuilder();
                aSB.append("Headers before uncompress\n");
                final MimeBodyPart part = aMsg.getData();
                final Enumeration<String> aHeaderLines = part.getAllHeaderLines();
                while (aHeaderLines.hasMoreElements()) {
                    aSB.append(aHeaderLines.nextElement()).append('\n');
                }
                aSB.append("done");
                LOGGER.debug(aSB.toString());
            }
            // The default buffer size in BufferedInputStream is 8192
            final SMIMECompressedParser aCompressedParser = new SMIMECompressedParser(aMsg.getData());
            // TODO: get buffer from configuration
            aDecompressedPart = SMIMEUtil.toMimeBodyPart(aCompressedParser.getContent(aExpander));
            // Update the message object
            aMsg.setData(aDecompressedPart);
            // Remember that message was decompressed
            aMsg.attrs().putIn(AS2Message.ATTRIBUTE_RECEIVED_COMPRESSED, true);
            if (LOGGER.isInfoEnabled())
                LOGGER.info("Successfully decompressed incoming AS2 message" + aMsg.getLoggingText());
        }
    } catch (final SMIMEException | CMSException | MessagingException ex) {
        if (LOGGER.isErrorEnabled())
            LOGGER.error("Error decompressing received message", ex);
        throw new AS2DispositionException(DispositionType.createError("unexpected-processing-error"), AbstractActiveNetModule.DISP_DECOMPRESSION_ERROR, ex);
    }
}
Also used : AS2DispositionException(com.helger.as2lib.disposition.AS2DispositionException) ZlibExpanderProvider(org.bouncycastle.cms.jcajce.ZlibExpanderProvider) MessagingException(javax.mail.MessagingException) SMIMEException(org.bouncycastle.mail.smime.SMIMEException) SMIMECompressedParser(org.bouncycastle.mail.smime.SMIMECompressedParser) MimeBodyPart(javax.mail.internet.MimeBodyPart) CMSException(org.bouncycastle.cms.CMSException)

Aggregations

AS2DispositionException (com.helger.as2lib.disposition.AS2DispositionException)5 AS2Exception (com.helger.as2lib.exception.AS2Exception)4 WrappedAS2Exception (com.helger.as2lib.exception.WrappedAS2Exception)4 IOException (java.io.IOException)3 MessagingException (javax.mail.MessagingException)3 MimeBodyPart (javax.mail.internet.MimeBodyPart)3 CMSException (org.bouncycastle.cms.CMSException)3 SMIMEException (org.bouncycastle.mail.smime.SMIMEException)3 ICryptoHelper (com.helger.as2lib.crypto.ICryptoHelper)2 AS2NoModuleException (com.helger.as2lib.processor.AS2NoModuleException)2 AS2ProcessorException (com.helger.as2lib.processor.AS2ProcessorException)2 AS2ComponentNotFoundException (com.helger.as2lib.session.AS2ComponentNotFoundException)2 InputStream (java.io.InputStream)2 ICertificateFactory (com.helger.as2lib.cert.ICertificateFactory)1 AS2InvalidParameterException (com.helger.as2lib.params.AS2InvalidParameterException)1 Partnership (com.helger.as2lib.partner.Partnership)1 IAS2Session (com.helger.as2lib.session.IAS2Session)1 AS2ResourceHelper (com.helger.as2lib.util.AS2ResourceHelper)1 AS2HttpClient (com.helger.as2lib.util.http.AS2HttpClient)1 AS2HttpHeaderSetter (com.helger.as2lib.util.http.AS2HttpHeaderSetter)1