Exemple #1
0
def save_message(message, raw_payload):
    """ Function decompresses, decrypts and verifies the received message"""
    try:
        payload = email.message_from_string(raw_payload)
        micContent = None
        models.Log.objects.create(message=message, status="S", text=_(u"Begin Processing of received AS2 message"))
        if not models.Organization.objects.filter(as2_name=as2utils.unescape_as2name(payload.get("as2-to"))).exists():
            raise as2utils.as2partnernotfound("Unknown AS2 organization with id %s" % payload.get("as2-to"))
        message.organization = models.Organization.objects.get(
            as2_name=as2utils.unescape_as2name(payload.get("as2-to"))
        )
        if not models.Partner.objects.filter(as2_name=as2utils.unescape_as2name(payload.get("as2-from"))).exists():
            raise as2utils.as2partnernotfound("Unknown AS2 Trading partner with id %s" % payload.get("as2-from"))
        message.partner = models.Partner.objects.get(as2_name=as2utils.unescape_as2name(payload.get("as2-from")))
        models.Log.objects.create(
            message=message,
            status="S",
            text=_(u'Message is for Organization "%s" from partner "%s"' % (message.organization, message.partner)),
        )
        # micContent = payload.get_payload()
        filename = payload.get_filename()
        if message.partner.encryption and payload.get_content_type() != "application/pkcs7-mime":
            raise as2utils.as2insufficientsecurity(
                "Incoming messages from AS2 partner %s are defined to be encrypted" % message.partner.as2_name
            )
        if (
            payload.get_content_type() == "application/pkcs7-mime"
            and payload.get_param("smime-type") == "enveloped-data"
        ):
            models.Log.objects.create(
                message=message,
                status="S",
                text=_(u"Decrypting the payload using private key %s" % message.organization.encryption_key),
            )
            message.encrypted = True
            ### Check if data is base64, if not then encode
            try:
                payload.get_payload().encode("ascii")
            except Exception, e:
                payload.set_payload(payload.get_payload().encode("base64"))
            pyas2init.logger.debug("Decrypting the payload :\n%s" % payload.get_payload())
            try:
                decrypted_content = as2utils.decrypt_payload(
                    as2utils.mimetostring(payload, 78),
                    str(message.organization.encryption_key.certificate.path),
                    str(message.organization.encryption_key.certificate_passphrase),
                )
                # micContent,raw_payload = as2utils.canonicalize(decrypted_content),decrypted_content
                raw_payload = decrypted_content
                payload = email.message_from_string(decrypted_content)
                ### Check if decrypted content is the actual content
                if payload.get_content_type() == "text/plain":
                    payload = email.Message.Message()
                    payload.set_payload(decrypted_content)
                    payload.set_type("application/edi-consent")
                    if filename:
                        payload.add_header("Content-Disposition", "attachment", filename=filename)
            except Exception, msg:
                raise as2utils.as2decryptionfailed("Failed to decrypt message, exception message is %s" % msg)
Exemple #2
0
def get_partner_from_payload(payload):
    message_partner_as2name = as2utils.unescape_as2name(
        payload.get('as2-from'))
    partners = models.Partner.objects.filter(
        as2_identifier=message_partner_as2name)

    # We got a single partner so just return it
    if partners.count() == 1:
        return partners[0]

    # We got multiple entries for given as2_name, determine which one to use
    # by partner's extra_headers
    elif partners.count() > 1:
        for partner in partners:
            partner_headers = partner.extra_headers_as_dict()
            payload_headers = {}

            # Collect header data
            for partner_header in partner_headers:
                payload_header_value = payload.get(partner_header)
                if payload_header_value:
                    payload_headers[partner_header] = payload_header_value

            # Compare payload header and partner header data
            if dict_contents_equals(partner_headers, payload_headers):
                return partner
Exemple #3
0
def save_message(message, payload, raw_payload):
    """ Function decompresses, decrypts and verifies the received AS2 message
     Takes an AS2 message as input and returns the actual payload ex. X12 message """

    try:
        # Initialize variables
        mic_content = None
        mic_alg = None
        filename = payload.get_filename()

        # Search for the organization adn partner, raise error if none exists.
        models.Log.objects.create(
            message=message,
            status='S',
            text=_(u'Begin Processing of received AS2 message'))

        if not models.Organization.objects.filter(
                as2_name=as2utils.unescape_as2name(payload.get(
                    'as2-to'))).exists():
            raise as2utils.As2PartnerNotFound(
                'Unknown AS2 organization with id %s' % payload.get('as2-to'))
        message.organization = models.Organization.objects.get(
            as2_name=as2utils.unescape_as2name(payload.get('as2-to')))

        if not models.Partner.objects.filter(
                as2_name=as2utils.unescape_as2name(payload.get(
                    'as2-from'))).exists():
            raise as2utils.As2PartnerNotFound(
                'Unknown AS2 Trading partner with id %s' %
                payload.get('as2-from'))
        message.partner = models.Partner.objects.get(
            as2_name=as2utils.unescape_as2name(payload.get('as2-from')))
        models.Log.objects.create(
            message=message,
            status='S',
            text=_(u'Message is for Organization "%s" from partner "%s"' %
                   (message.organization, message.partner)))

        # Check if message from this partner are expected to be encrypted
        if message.partner.encryption and payload.get_content_type(
        ) != 'application/pkcs7-mime':
            raise as2utils.As2InsufficientSecurity(
                u'Incoming messages from AS2 partner {0:s} are defined to be encrypted'
                .format(message.partner.as2_name))

        # Check if payload is encrypted and if so decrypt it
        if payload.get_content_type() == 'application/pkcs7-mime' \
                and payload.get_param('smime-type') == 'enveloped-data':
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(
                    u'Decrypting the payload using private key {0:s}'.format(
                        message.organization.encryption_key)))
            message.encrypted = True

            # Check if encrypted data is base64 encoded, if not then encode
            try:
                payload.get_payload().encode('ascii')
            except UnicodeDecodeError:
                payload.set_payload(payload.get_payload().encode('base64'))

            # Decrypt the base64 encoded data using the partners public key
            pyas2init.logger.debug(u'Decrypting the payload :\n{0:s}'.format(
                payload.get_payload()))
            try:
                decrypted_content = as2utils.decrypt_payload(
                    as2utils.mimetostring(payload, 78),
                    str(message.organization.encryption_key.certificate.path),
                    str(message.organization.encryption_key.
                        certificate_passphrase))
                raw_payload = decrypted_content
                payload = email.message_from_string(decrypted_content)

                # Check if decrypted content is the actual content i.e. no compression and no signatures
                if payload.get_content_type() == 'text/plain':
                    payload = email.Message.Message()
                    payload.set_payload(decrypted_content)
                    payload.set_type('application/edi-consent')
                    if filename:
                        payload.add_header('Content-Disposition',
                                           'attachment',
                                           filename=filename)
            except Exception, msg:
                raise as2utils.As2DecryptionFailed(
                    'Failed to decrypt message, exception message is %s' % msg)

        # Check if message from this partner are expected to be signed
        if message.partner.signature and payload.get_content_type(
        ) != 'multipart/signed':
            raise as2utils.As2InsufficientSecurity(
                u'Incoming messages from AS2 partner {0:s} are defined to be signed'
                .format(message.partner.as2_name))

        # Check if message is signed and if so verify it
        if payload.get_content_type() == 'multipart/signed':
            if not message.partner.signature_key:
                raise as2utils.As2InsufficientSecurity(
                    'Partner has no signature verification key defined')
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(
                    u'Message is signed, Verifying it using public key {0:s}'.
                    format(message.partner.signature_key)))
            pyas2init.logger.debug(
                'Verifying the signed payload:\n{0:s}'.format(
                    payload.as_string()))
            message.signed = True
            mic_alg = payload.get_param('micalg').lower() or 'sha1'

            # Get the partners public and ca certificates
            cert = str(message.partner.signature_key.certificate.path)
            ca_cert = cert
            if message.partner.signature_key.ca_cert:
                ca_cert = str(message.partner.signature_key.ca_cert.path)
            verify_cert = message.partner.signature_key.verify_cert

            # Extract the signature and signed content from the mime message
            main_boundary = '--' + payload.get_boundary()
            for part in payload.walk():
                if part.get_content_type() in [
                        "application/pkcs7-signature",
                        "application/x-pkcs7-signature"
                ]:
                    __, raw_sig = as2utils.check_binary_sig(
                        part, main_boundary, raw_payload)
                else:
                    payload = part

            # Verify message using raw payload received from partner
            try:
                as2utils.verify_payload(raw_payload, None, cert, ca_cert,
                                        verify_cert)
            except Exception:
                # Verify message using extracted signature and canonicalzed message
                try:
                    as2utils.verify_payload(as2utils.canonicalize2(payload),
                                            raw_sig, cert, ca_cert,
                                            verify_cert)
                except Exception, e:
                    raise as2utils.As2InvalidSignature(
                        'Signature Verification Failed, exception message is {0:s}'
                        .format(e))

            mic_content = as2utils.canonicalize2(payload)
Exemple #4
0
def save_message(message, payload, raw_payload):
    """ Function decompresses, decrypts and verifies the received AS2 message
     Takes an AS2 message as input and returns the actual payload ex. X12 message """

    try:
        # Initialize variables
        mic_content = None
        mic_alg = None
        filename = payload.get_filename()

        # Search for the organization adn partner, raise error if none exists.
        models.Log.objects.create(message=message, status='S', text=_(u'Begin Processing of received AS2 message'))

        if not models.Organization.objects.filter(as2_name=as2utils.unescape_as2name(payload.get('as2-to'))).exists():
            raise as2utils.As2PartnerNotFound('Unknown AS2 organization with id %s' % payload.get('as2-to'))
        message.organization = models.Organization.objects.get(
            as2_name=as2utils.unescape_as2name(payload.get('as2-to')))

        if not models.Partner.objects.filter(as2_name=as2utils.unescape_as2name(payload.get('as2-from'))).exists():
            raise as2utils.As2PartnerNotFound('Unknown AS2 Trading partner with id %s' % payload.get('as2-from'))
        message.partner = models.Partner.objects.get(as2_name=as2utils.unescape_as2name(payload.get('as2-from')))
        models.Log.objects.create(
            message=message,
            status='S',
            text=_(u'Message is for Organization "%s" from partner "%s"' % (message.organization, message.partner))
         )

        # Check if message from this partner are expected to be encrypted
        if message.partner.encryption and payload.get_content_type() != 'application/pkcs7-mime':
            raise as2utils.As2InsufficientSecurity(
                u'Incoming messages from AS2 partner {0:s} are defined to be encrypted'.format(
                    message.partner.as2_name))

        # Check if payload is encrypted and if so decrypt it
        if payload.get_content_type() == 'application/pkcs7-mime' \
                and payload.get_param('smime-type') == 'enveloped-data':
            models.Log.objects.create(message=message, status='S', text=_(
                u'Decrypting the payload using private key {0:s}'.format(message.organization.encryption_key)))
            message.encrypted = True

            # Check if encrypted data is base64 encoded, if not then encode
            try:
                payload.get_payload().encode('ascii')
            except UnicodeDecodeError:
                payload.set_payload(payload.get_payload().encode('base64'))

            # Decrypt the base64 encoded data using the partners public key
            pyas2init.logger.debug(u'Decrypting the payload :\n{0:s}'.format(payload.get_payload()))
            try:
                decrypted_content = as2utils.decrypt_payload(
                    as2utils.mimetostring(payload, 78),
                    str(message.organization.encryption_key.certificate.path),
                    str(message.organization.encryption_key.certificate_passphrase)
                )
                raw_payload = decrypted_content
                payload = email.message_from_string(decrypted_content)

                # Check if decrypted content is the actual content i.e. no compression and no signatures
                if payload.get_content_type() == 'text/plain':
                    payload = email.Message.Message()
                    payload.set_payload(decrypted_content)
                    payload.set_type('application/edi-consent')
                    if filename:
                        payload.add_header('Content-Disposition', 'attachment', filename=filename)
            except Exception, msg:
                raise as2utils.As2DecryptionFailed('Failed to decrypt message, exception message is %s' % msg)

        # Check if message from this partner are expected to be signed
        if message.partner.signature and payload.get_content_type() != 'multipart/signed':
            raise as2utils.As2InsufficientSecurity(
                u'Incoming messages from AS2 partner {0:s} are defined to be signed'.format(message.partner.as2_name))

        # Check if message is signed and if so verify it
        if payload.get_content_type() == 'multipart/signed':
            if not message.partner.signature_key:
                raise as2utils.As2InsufficientSecurity('Partner has no signature verification key defined')
            models.Log.objects.create(message=message, status='S', text=_(
                u'Message is signed, Verifying it using public key {0:s}'.format(message.partner.signature_key)))
            pyas2init.logger.debug('Verifying the signed payload:\n{0:s}'.format(payload.as_string()))
            message.signed = True
            mic_alg = payload.get_param('micalg').lower() or 'sha1'

            # Get the partners public and ca certificates
            cert = str(message.partner.signature_key.certificate.path)
            ca_cert = cert
            if message.partner.signature_key.ca_cert:
                ca_cert = str(message.partner.signature_key.ca_cert.path)
            verify_cert = message.partner.signature_key.verify_cert

            # Extract the signature and signed content from the mime message
            main_boundary = '--' + payload.get_boundary()
            for part in payload.walk():
                if part.get_content_type() == "application/pkcs7-signature":
                    __, raw_sig = as2utils.check_binary_sig(part, main_boundary, raw_payload)
                else:
                    payload = part

            # Verify message using raw payload received from partner
            try:
                as2utils.verify_payload(raw_payload, None, cert, ca_cert, verify_cert)
            except Exception:
                # Verify message using extracted signature and canonicalzed message
                try:
                    as2utils.verify_payload(as2utils.canonicalize2(payload), raw_sig, cert, ca_cert, verify_cert)
                except Exception, e:
                    raise as2utils.As2InvalidSignature(
                        'Signature Verification Failed, exception message is {0:s}'.format(e))

            mic_content = as2utils.canonicalize2(payload)