Beispiel #1
0
  /**
   * Read headers and payload from the passed input stream provider.
   *
   * @param aISP The abstract input stream provider to use. May not be <code>null</code>.
   * @param aResponseHandler The HTTP response handler to be used. May not be <code>null</code>.
   * @param aMsg The Message to be filled. May not be <code>null</code>.
   * @return The payload of the HTTP request.
   * @throws IOException In case of error reading from the InputStream
   * @throws MessagingException In case header line parsing fails
   */
  @Nonnull
  public static byte[] readHttpRequest(
      @Nonnull final IAS2InputStreamProvider aISP,
      @Nonnull final IAS2HttpResponseHandler aResponseHandler,
      @Nonnull final IMessage aMsg)
      throws IOException, MessagingException {
    // Get the stream to read from
    final InputStream aIS = aISP.getInputStream();
    if (aIS == null) throw new IllegalStateException("Failed to open InputStream from " + aISP);

    // Read the HTTP meta data
    final String[] aRequest = _readRequestInfo(aIS);
    // Request method (e.g. "POST")
    aMsg.setAttribute(MA_HTTP_REQ_TYPE, aRequest[0]);
    // Request URL (e.g. "/as2")
    aMsg.setAttribute(MA_HTTP_REQ_URL, aRequest[1]);
    // HTTP version (e.g. "HTTP/1.1")
    aMsg.setAttribute(MA_HTTP_REQ_VERSION, aRequest[2]);

    // Parse all HTTP headers from stream
    final InternetHeaders aHeaders = new InternetHeaders(aIS);
    aMsg.setHeaders(aHeaders);

    // Read the message body - no Content-Transfer-Encoding handling
    final byte[] aPayload = readHttpPayload(aIS, aResponseHandler, aMsg);

    // Dump on demand
    if (isHTTPIncomingDumpEnabled())
      dumpIncomingHttpRequest(getAllHTTPHeaderLines(aHeaders), aPayload, aMsg);

    return aPayload;

    // Don't close the IS here!
  }
 @Nonnull
 public X509Certificate getCertificate(
     @Nonnull final IMessage aMsg, @Nullable final ECertificatePartnershipType ePartnershipType)
     throws OpenAS2Exception {
   final String sAlias = getAlias(aMsg.getPartnership(), ePartnershipType);
   return internalGetCertificate(sAlias, ePartnershipType);
 }
  protected void decompress(@Nonnull final IMessage aMsg) throws DispositionException {
    try {
      if (aMsg.getPartnership().isDisableDecompress()) {
        s_aLogger.info(
            "Message claims to be compressed but decompression is disabled"
                + aMsg.getLoggingText());
      } else {
        if (s_aLogger.isDebugEnabled()) s_aLogger.debug("Decompressing a compressed AS2 message");

        final SMIMECompressed aCompressed = new SMIMECompressed(aMsg.getData());
        // decompression step MimeBodyPart
        final MimeBodyPart aDecompressedPart =
            SMIMEUtil.toMimeBodyPart(aCompressed.getContent(new ZlibExpanderProvider()));
        // Update the message object
        aMsg.setData(aDecompressedPart);
        // Remember that message was decompressed
        aMsg.setAttribute(AS2Message.ATTRIBUTE_RECEIVED_COMPRESSED, Boolean.TRUE.toString());
        s_aLogger.info("Successfully decompressed incoming AS2 message" + aMsg.getLoggingText());
      }
    } catch (final Exception ex) {
      s_aLogger.error("Error decompressing received message", ex);
      throw new DispositionException(
          DispositionType.createError("unexpected-processing-error"),
          AbstractActiveNetModule.DISP_DECOMPRESSION_ERROR,
          ex);
    }
  }
Beispiel #4
0
  @Nonnull
  public static byte[] readHttpPayload(
      @Nonnull final InputStream aIS,
      @Nonnull final IAS2HttpResponseHandler aResponseHandler,
      @Nonnull final IMessage aMsg)
      throws IOException {
    ValueEnforcer.notNull(aIS, "InputStream");
    ValueEnforcer.notNull(aResponseHandler, "ResponseHandler");
    ValueEnforcer.notNull(aMsg, "Msg");

    final DataInputStream aDataIS = new DataInputStream(aIS);

    // Retrieve the message content
    byte[] aData = null;
    final String sContentLength = aMsg.getHeader(CAS2Header.HEADER_CONTENT_LENGTH);
    if (sContentLength == null) {
      // No "Content-Length" header present
      final String sTransferEncoding = aMsg.getHeader(CAS2Header.HEADER_TRANSFER_ENCODING);
      if (sTransferEncoding != null) {
        // Remove all whitespaces in the value
        if (sTransferEncoding.replaceAll("\\s+", "").equalsIgnoreCase("chunked")) {
          // chunked encoding
          int nLength = 0;
          for (; ; ) {
            // First get hex chunk length; followed by CRLF
            int nBlocklen = 0;
            for (; ; ) {
              int ch = aDataIS.readByte();
              if (ch == '\n') break;
              if (ch >= 'a' && ch <= 'f') ch -= ('a' - 10);
              else if (ch >= 'A' && ch <= 'F') ch -= ('A' - 10);
              else if (ch >= '0' && ch <= '9') ch -= '0';
              else continue;
              nBlocklen = (nBlocklen * 16) + ch;
            }
            // Zero length is end of chunks
            if (nBlocklen == 0) break;
            // Ok, now read new chunk
            final int nNewlen = nLength + nBlocklen;
            final byte[] aNewData = new byte[nNewlen];
            if (nLength > 0) System.arraycopy(aData, 0, aNewData, 0, nLength);
            aDataIS.readFully(aNewData, nLength, nBlocklen);
            aData = aNewData;
            nLength = nNewlen;
            // And now the CRLF after the chunk;
            while (true) {
              final int n = aDataIS.readByte();
              if (n == '\n') break;
            }
          }
          aMsg.setHeader(CAS2Header.HEADER_CONTENT_LENGTH, Integer.toString(nLength));
        } else {
          // No "Content-Length" and unsupported "Transfer-Encoding"
          sendSimpleHTTPResponse(aResponseHandler, HttpURLConnection.HTTP_LENGTH_REQUIRED);
          throw new IOException("Transfer-Encoding unimplemented: " + sTransferEncoding);
        }
      } else {
        // No "Content-Length" and no "Transfer-Encoding"
        sendSimpleHTTPResponse(aResponseHandler, HttpURLConnection.HTTP_LENGTH_REQUIRED);
        throw new IOException("Content-Length missing");
      }
    } else {
      // "Content-Length" is present
      // Receive the transmission's data
      // XX if a value > 2GB comes in, this will fail!!
      final int nContentSize = Integer.parseInt(sContentLength);
      aData = new byte[nContentSize];
      aDataIS.readFully(aData);
    }

    return aData;
  }
  protected void verify(@Nonnull final IMessage aMsg) throws OpenAS2Exception {
    final ICertificateFactory aCertFactory = m_aReceiverModule.getSession().getCertificateFactory();
    final ICryptoHelper aCryptoHelper = AS2Helper.getCryptoHelper();

    try {
      final boolean bDisableVerify = aMsg.getPartnership().isDisableVerify();
      final boolean bMsgIsSigned = aCryptoHelper.isSigned(aMsg.getData());
      final boolean bForceVerify = aMsg.getPartnership().isForceVerify();
      if (bMsgIsSigned && bDisableVerify) {
        s_aLogger.info(
            "Message claims to be signed but signature validation is disabled"
                + aMsg.getLoggingText());
      } else if (bMsgIsSigned || bForceVerify) {
        if (bForceVerify && !bMsgIsSigned)
          s_aLogger.info("Forced verify signature" + aMsg.getLoggingText());
        else if (s_aLogger.isDebugEnabled())
          s_aLogger.debug("Verifying signature" + aMsg.getLoggingText());

        final X509Certificate aSenderCert =
            aCertFactory.getCertificateOrNull(aMsg, ECertificatePartnershipType.SENDER);
        boolean bUseCertificateInBodyPart;
        final ETriState eUseCertificateInBodyPart =
            aMsg.getPartnership().getVerifyUseCertificateInBodyPart();
        if (eUseCertificateInBodyPart.isDefined()) {
          // Use per partnership
          bUseCertificateInBodyPart = eUseCertificateInBodyPart.getAsBooleanValue();
        } else {
          // Use global value
          bUseCertificateInBodyPart =
              m_aReceiverModule.getSession().isCryptoVerifyUseCertificateInBodyPart();
        }

        final MimeBodyPart aVerifiedData =
            aCryptoHelper.verify(
                aMsg.getData(), aSenderCert, bUseCertificateInBodyPart, bForceVerify);
        aMsg.setData(aVerifiedData);
        // Remember that message was signed and verified
        aMsg.setAttribute(AS2Message.ATTRIBUTE_RECEIVED_SIGNED, Boolean.TRUE.toString());
        s_aLogger.info(
            "Successfully verified signature of incoming AS2 message" + aMsg.getLoggingText());
      }
    } catch (final Exception ex) {
      s_aLogger.error(
          "Error verifying signature " + aMsg.getLoggingText() + ": " + ex.getMessage());
      throw new DispositionException(
          DispositionType.createError("integrity-check-failed"),
          AbstractActiveNetModule.DISP_VERIFY_SIGNATURE_FAILED,
          ex);
    }
  }
  protected void decrypt(@Nonnull final IMessage aMsg) throws OpenAS2Exception {
    final ICertificateFactory aCertFactory = m_aReceiverModule.getSession().getCertificateFactory();
    final ICryptoHelper aCryptoHelper = AS2Helper.getCryptoHelper();

    try {
      final boolean bDisableDecrypt = aMsg.getPartnership().isDisableDecrypt();
      final boolean bMsgIsEncrypted = aCryptoHelper.isEncrypted(aMsg.getData());
      final boolean bForceDecrypt = aMsg.getPartnership().isForceDecrypt();
      if (bMsgIsEncrypted && bDisableDecrypt) {
        s_aLogger.info(
            "Message claims to be encrypted but decryption is disabled" + aMsg.getLoggingText());
      } else if (bMsgIsEncrypted || bForceDecrypt) {
        // Decrypt
        if (bForceDecrypt && !bMsgIsEncrypted)
          s_aLogger.info("Forced decrypting" + aMsg.getLoggingText());
        else if (s_aLogger.isDebugEnabled()) s_aLogger.debug("Decrypting" + aMsg.getLoggingText());

        final X509Certificate aReceiverCert =
            aCertFactory.getCertificate(aMsg, ECertificatePartnershipType.RECEIVER);
        final PrivateKey aReceiverKey = aCertFactory.getPrivateKey(aMsg, aReceiverCert);
        final MimeBodyPart aDecryptedData =
            aCryptoHelper.decrypt(aMsg.getData(), aReceiverCert, aReceiverKey, bForceDecrypt);
        aMsg.setData(aDecryptedData);
        // Remember that message was encrypted
        aMsg.setAttribute(AS2Message.ATTRIBUTE_RECEIVED_ENCRYPTED, Boolean.TRUE.toString());
        s_aLogger.info("Successfully decrypted incoming AS2 message" + aMsg.getLoggingText());
      }
    } catch (final Exception ex) {
      s_aLogger.error("Error decrypting " + aMsg.getLoggingText() + ": " + ex.getMessage());
      throw new DispositionException(
          DispositionType.createError("decryption-failed"),
          AbstractActiveNetModule.DISP_DECRYPTION_ERROR,
          ex);
    }
  }