use of com.helger.commons.io.stream.NonBlockingByteArrayOutputStream in project as2-lib by phax.
the class AS2ReceiverHandler method sendMDN.
protected void sendMDN(@Nonnull final String sClientInfo, @Nonnull final IAS2HttpResponseHandler aResponseHandler, @Nonnull final AS2Message aMsg, @Nonnull final DispositionType aDisposition, @Nonnull final String sText, @Nonnull final ESuccess eSuccess) {
final boolean bAllowErrorMDN = !aMsg.partnership().isBlockErrorMDN();
if (eSuccess.isSuccess() || bAllowErrorMDN) {
try {
final IAS2Session aSession = m_aReceiverModule.getSession();
final IMessageMDN aMdn = AS2Helper.createMDN(aSession, aMsg, aDisposition, sText);
if (aMsg.isRequestingAsynchMDN()) {
// if asyncMDN requested, close existing synchronous connection and
// initiate separate MDN send
final HttpHeaderMap aHeaders = new HttpHeaderMap();
aHeaders.setContentLength(0);
try (final NonBlockingByteArrayOutputStream aData = new NonBlockingByteArrayOutputStream()) {
// Empty data
// Ideally this would be HTTP 204 (no content)
aResponseHandler.sendHttpResponse(CHttp.HTTP_OK, aHeaders, aData);
}
if (LOGGER.isInfoEnabled())
LOGGER.info("Setup to send async MDN [" + aDisposition.getAsString() + "] " + sClientInfo + aMsg.getLoggingText());
// trigger explicit async sending
aSession.getMessageProcessor().handle(IProcessorSenderModule.DO_SEND_ASYNC_MDN, aMsg, null);
} else {
// otherwise, send sync MDN back on same connection
if (LOGGER.isInfoEnabled())
LOGGER.info("Sending back sync MDN [" + aDisposition.getAsString() + "] " + sClientInfo + aMsg.getLoggingText());
// Get data and therefore content length for sync MDN
try (final NonBlockingByteArrayOutputStream aData = new NonBlockingByteArrayOutputStream()) {
final MimeBodyPart aPart = aMdn.getData();
StreamHelper.copyInputStreamToOutputStream(aPart.getInputStream(), aData);
aMdn.headers().setContentLength(aData.size());
// start HTTP response
aResponseHandler.sendHttpResponse(CHttp.HTTP_OK, aMdn.headers(), aData);
}
// Save sent MDN for later examination
try {
aSession.getMessageProcessor().handle(IProcessorStorageModule.DO_STOREMDN, aMsg, null);
} catch (final AS2ComponentNotFoundException | AS2NoModuleException ex) {
// No message processor found
// or No module found in message processor
}
if (LOGGER.isInfoEnabled())
LOGGER.info("sent MDN [" + aDisposition.getAsString() + "] " + sClientInfo + aMsg.getLoggingText());
}
} catch (final Exception ex) {
WrappedAS2Exception.wrap(ex).terminate(aMsg);
}
}
}
use of com.helger.commons.io.stream.NonBlockingByteArrayOutputStream in project as2-lib by phax.
the class BCCryptoHelper method decrypt.
@Nonnull
public MimeBodyPart decrypt(@Nonnull final MimeBodyPart aPart, @Nonnull final X509Certificate aX509Cert, @Nonnull final PrivateKey aPrivateKey, final boolean bForceDecrypt, @Nonnull final AS2ResourceHelper aResHelper) throws GeneralSecurityException, MessagingException, CMSException, SMIMEException, IOException {
ValueEnforcer.notNull(aPart, "MimeBodyPart");
ValueEnforcer.notNull(aX509Cert, "X509Cert");
ValueEnforcer.notNull(aPrivateKey, "PrivateKey");
ValueEnforcer.notNull(aResHelper, "ResHelper");
if (LOGGER.isDebugEnabled())
LOGGER.debug("BCCryptoHelper.decrypt; X509 subject=" + aX509Cert.getSubjectX500Principal().getName() + "; forceDecrypt=" + bForceDecrypt);
// Make sure the data is encrypted
if (!bForceDecrypt && !isEncrypted(aPart))
throw new GeneralSecurityException("Content-Type '" + aPart.getContentType() + "' indicates data isn't encrypted");
// Get the recipient object for decryption
final RecipientId aRecipientID = new JceKeyTransRecipientId(aX509Cert);
// Parse the MIME body into an SMIME envelope object
RecipientInformation aRecipient = null;
try {
final SMIMEEnvelopedParser aEnvelope = new SMIMEEnvelopedParser(aPart);
aRecipient = aEnvelope.getRecipientInfos().get(aRecipientID);
} catch (final Exception ex) {
LOGGER.error("Error retrieving RecipientInformation", ex);
}
if (aRecipient == null)
throw new GeneralSecurityException("Certificate does not match part signature");
// try to decrypt the data
// Custom file: see #103
final FileBackedMimeBodyPart aDecryptedDataBodyPart = SMIMEUtil.toMimeBodyPart(aRecipient.getContentStream(new JceKeyTransEnvelopedRecipient(aPrivateKey).setProvider(m_sSecurityProviderName)), aResHelper.createTempFile());
if (DUMP_DECRYPTED_DIR_PATH != null) {
// dump decrypted
try (final NonBlockingByteArrayOutputStream aBAOS = new NonBlockingByteArrayOutputStream(aDecryptedDataBodyPart.getSize())) {
aDecryptedDataBodyPart.writeTo(aBAOS);
_dumpDecrypted(aBAOS.toByteArray());
}
}
return aDecryptedDataBodyPart;
}
use of com.helger.commons.io.stream.NonBlockingByteArrayOutputStream in project as2-lib by phax.
the class MimeBodyPartFuncTest method testWriteContentTransferEncoding8Bit.
@Test
public void testWriteContentTransferEncoding8Bit() throws MessagingException, IOException {
final String sTestMsg = "Test message\nLine 2\n\nLine 4\nEOF";
// Build message content
final MimeBodyPart aPart = new MimeBodyPart();
aPart.setText(sTestMsg, StandardCharsets.ISO_8859_1.name());
aPart.addHeader("x-custom", "junit");
aPart.addHeader(CHttpHeader.CONTENT_TYPE, "text/plain");
aPart.addHeader(CHttpHeader.CONTENT_TRANSFER_ENCODING, EContentTransferEncoding._8BIT.getID());
aPart.addHeader(CHttpHeader.CONTENT_LENGTH, Integer.toString(sTestMsg.length()));
final NonBlockingByteArrayOutputStream aBAOS = new NonBlockingByteArrayOutputStream();
aPart.writeTo(aBAOS);
StreamHelper.close(aBAOS);
final String sMsgPart = aBAOS.getAsString(StandardCharsets.ISO_8859_1);
if (false)
LOGGER.info(sMsgPart);
assertTrue(sMsgPart, sMsgPart.contains("Content-Type: text/plain"));
assertTrue(sMsgPart, sMsgPart.contains("Content-Transfer-Encoding: 8bit"));
assertTrue(sMsgPart, sMsgPart.contains("x-custom: junit"));
assertTrue(sMsgPart, sMsgPart.contains(sTestMsg));
}
use of com.helger.commons.io.stream.NonBlockingByteArrayOutputStream in project as2-lib by phax.
the class MimeBodyPartFuncTest method testReadContentTransferEncodingBase64.
@Test
public void testReadContentTransferEncodingBase64() throws MessagingException, IOException {
final String sHTTP = "Content-Type: text/plain" + CHttp.EOL + "Content-Transfer-Encoding: base64" + CHttp.EOL + "x-custom: junit" + CHttp.EOL + "Content-Length: 44" + CHttp.EOL + CHttp.EOL + "VGVzdCBtZXNzYWdlCkxpbmUgMgoKTGluZSA0CkVPRg==" + CHttp.EOL;
InputStream aIS = new StringInputStream(sHTTP, StandardCharsets.ISO_8859_1);
// Parse all HTTP headers from stream
final InternetHeaders aHeaders = new InternetHeaders(aIS);
final String sCTE = aHeaders.getHeader(CHttpHeader.CONTENT_TRANSFER_ENCODING)[0];
if (StringHelper.hasText(sCTE))
aIS = AS2IOHelper.getContentTransferEncodingAwareInputStream(aIS, sCTE);
// Read the payload
final byte[] aData = StreamHelper.getAllBytes(aIS);
// Extract content type
final String sReceivedContentType = AS2HttpHelper.getCleanContentType(aHeaders.getHeader(CHttpHeader.CONTENT_TYPE)[0]);
final MimeBodyPart aReceivedPart = new MimeBodyPart();
aReceivedPart.setDataHandler(new ByteArrayDataSource(aData, sReceivedContentType, null).getAsDataHandler());
aReceivedPart.setHeader("x-received", "true");
final NonBlockingByteArrayOutputStream aBAOS = new NonBlockingByteArrayOutputStream();
aReceivedPart.writeTo(aBAOS);
StreamHelper.close(aBAOS);
final String sMsgPart = aBAOS.getAsString(StandardCharsets.ISO_8859_1);
if (true)
LOGGER.info(sMsgPart);
}
use of com.helger.commons.io.stream.NonBlockingByteArrayOutputStream in project as2-lib by phax.
the class AS2SenderModule method receiveSyncMDN.
/**
* @param aMsg
* AS2Message
* @param aHttpClient
* URLConnection
* @param aOriginalMIC
* mic value from original msg
* @param aIncomingDumper
* Incoming dumper. May be <code>null</code>.
* @param aResHelper
* Resource helper
* @throws AS2Exception
* in case of an error
* @throws IOException
* in case of an IO error
*/
protected void receiveSyncMDN(@Nonnull final AS2Message aMsg, @Nonnull final AS2HttpClient aHttpClient, @Nonnull final MIC aOriginalMIC, @Nullable final IHTTPIncomingDumper aIncomingDumper, @Nonnull final AS2ResourceHelper aResHelper) throws AS2Exception, IOException {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Receiving synchronous MDN for message" + aMsg.getLoggingText());
try {
// Create a MessageMDN and copy HTTP headers
final IMessageMDN aMDN = new AS2MessageMDN(aMsg);
// Bug in ph-commons 9.1.3 in addAllHeaders!
aMDN.headers().addAllHeaders(aHttpClient.getResponseHeaderFields());
// Receive the MDN data
final InputStream aConnIS = aHttpClient.getInputStream();
final NonBlockingByteArrayOutputStream aMDNStream = new NonBlockingByteArrayOutputStream();
// Retrieve the whole MDN content
StreamHelper.copyByteStream().from(aConnIS).closeFrom(true).to(aMDNStream).closeTo(true).limit(StringParser.parseLong(aMDN.getHeader(CHttpHeader.CONTENT_LENGTH), -1)).build();
// Dump collected message
if (aIncomingDumper != null)
aIncomingDumper.dumpIncomingRequest(aMDN.headers().getAllHeaderLines(true), aMDNStream.getBufferOrCopy(), aMDN);
if (LOGGER.isTraceEnabled()) {
// Debug print the whole MDN stream
LOGGER.trace("Retrieved MDN stream data:\n" + aMDNStream.getAsString(StandardCharsets.ISO_8859_1));
}
final MimeBodyPart aPart = new MimeBodyPart(AS2HttpHelper.getAsInternetHeaders(aMDN.headers()), aMDNStream.getBufferOrCopy());
aMDN.setData(aPart);
// get the MDN partnership info
aMDN.partnership().setSenderAS2ID(aMDN.getHeader(CHttpHeader.AS2_FROM));
aMDN.partnership().setReceiverAS2ID(aMDN.getHeader(CHttpHeader.AS2_TO));
// Set the appropriate key store aliases
aMDN.partnership().setSenderX509Alias(aMsg.partnership().getReceiverX509Alias());
aMDN.partnership().setReceiverX509Alias(aMsg.partnership().getSenderX509Alias());
// Update the partnership
getSession().getPartnershipFactory().updatePartnership(aMDN, false);
final ICertificateFactory aCertFactory = getSession().getCertificateFactory();
final X509Certificate aSenderCert = aCertFactory.getCertificate(aMDN, ECertificatePartnershipType.SENDER);
boolean bUseCertificateInBodyPart;
final ETriState eUseCertificateInBodyPart = aMsg.partnership().getVerifyUseCertificateInBodyPart();
if (eUseCertificateInBodyPart.isDefined()) {
// Use per partnership
bUseCertificateInBodyPart = eUseCertificateInBodyPart.getAsBooleanValue();
} else {
// Use global value
bUseCertificateInBodyPart = getSession().isCryptoVerifyUseCertificateInBodyPart();
}
AS2Helper.parseMDN(aMsg, aSenderCert, bUseCertificateInBodyPart, m_aVerificationCertificateConsumer, aResHelper);
try {
getSession().getMessageProcessor().handle(IProcessorStorageModule.DO_STOREMDN, aMsg, null);
} catch (final AS2ComponentNotFoundException | AS2NoModuleException ex) {
// No message processor found
// Or no module found in message processor
}
final String sDisposition = aMDN.attrs().getAsString(AS2MessageMDN.MDNA_DISPOSITION);
if (LOGGER.isInfoEnabled())
LOGGER.info("Received synchronous AS2 MDN [" + sDisposition + "]" + aMsg.getLoggingText());
// Asynch MDN 2007-03-12
// Verify if the original mic is equal to the mic in returned MDN
final String sReturnMIC = aMDN.attrs().getAsString(AS2MessageMDN.MDNA_MIC);
final MIC aReturnMIC = MIC.parse(sReturnMIC);
// Catch ReturnMIC == null in case the attribute is simply missing
final boolean bMICMatch = aOriginalMIC != null && aReturnMIC != null && aReturnMIC.equals(aOriginalMIC);
if (bMICMatch) {
// MIC was matched - all good
m_aMICMatchingHandler.onMICMatch(aMsg, sReturnMIC);
} else {
// file was sent completely but the returned mic was not matched,
m_aMICMatchingHandler.onMICMismatch(aMsg, aOriginalMIC == null ? null : aOriginalMIC.getAsAS2String(), sReturnMIC);
}
if (m_aIncomingMDNCallback != null)
m_aIncomingMDNCallback.onIncomingMDN(true, aMDN, aMDN.getHeader(CHttpHeader.AS2_FROM), aMDN.getHeader(CHttpHeader.AS2_TO), sDisposition, aMDN.attrs().getAsString(AS2MessageMDN.MDNA_MIC), aMDN.attrs().getAsString(AS2MessageMDN.MDNA_ORIG_MESSAGEID), aMDN.attrs().getAsBoolean(AS2Message.ATTRIBUTE_RECEIVED_SIGNED, false), bMICMatch);
DispositionType.createFromString(sDisposition).validate(aMsg, aMDN.getText());
} catch (final IOException ex) {
throw ex;
} catch (final Exception ex) {
throw WrappedAS2Exception.wrap(ex).setSourceMsg(aMsg);
}
}
Aggregations