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)
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
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)
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)