-
Notifications
You must be signed in to change notification settings - Fork 36
Force Binary Canonicalization #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # Generated by Django 3.1.7 on 2022-07-25 09:00 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ("pyas2", "0003_auto_20221208_1310"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AddField( | ||
| model_name="partner", | ||
| name="canonicalize_as_binary", | ||
| field=models.BooleanField( | ||
| default=False, verbose_name="Force binary canonicalization" | ||
| ), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,22 +2,22 @@ | |
| from email.parser import HeaderParser | ||
| from unittest import mock | ||
|
|
||
| from django.test import TestCase, Client | ||
| from django.test import Client, TestCase | ||
| from pyas2lib.as2 import Message as As2Message | ||
| from pyas2lib.utils import canonicalize | ||
| from requests import Response | ||
| from requests.exceptions import RequestException | ||
|
|
||
| from pyas2.models import ( | ||
| PrivateKey, | ||
| PublicCertificate, | ||
| Mdn, | ||
| Message, | ||
| Organization, | ||
| Partner, | ||
| Message, | ||
| Mdn, | ||
| PrivateKey, | ||
| PublicCertificate, | ||
| ) | ||
| from pyas2.tests import TEST_DIR | ||
|
|
||
| from pyas2lib.as2 import Message as As2Message | ||
|
|
||
|
|
||
| class BasicServerClientTestCase(TestCase): | ||
| """Test cases for the AS2 server and client. | ||
|
|
@@ -534,6 +534,68 @@ def testEncryptSignMessageAsyncSignMdn(self, mock_request): | |
| mock_request.side_effect = RequestException() | ||
| out_message.mdn.send_async_mdn() | ||
|
|
||
| @mock.patch("requests.post") | ||
| def testForceBinaryCanonicalization(self, mock_request): | ||
| """Test Permutation 15: Sender sends text data using binary canonicalization | ||
| and requests a synchronous receipt.""" | ||
|
|
||
| partner = Partner.objects.create( | ||
| name="AS2 Server", | ||
| as2_name="as2server", | ||
| target_url="http://localhost:8080/pyas2/as2receive", | ||
| signature="sha1", | ||
| signature_cert=self.server_crt, | ||
| encryption=None, | ||
| encryption_cert=None, | ||
| mdn=True, | ||
| mdn_mode="SYNC", | ||
| ) | ||
|
|
||
| receiver = Partner.objects.get(as2_name="as2client") | ||
| receiver.canonicalize_as_binary = True | ||
| receiver.save() | ||
|
|
||
| as2message = As2Message( | ||
| sender=self.organization.as2org, receiver=partner.as2partner | ||
| ) | ||
|
|
||
| with mock.patch("pyas2lib.as2.canonicalize") as mock_canonicalize: | ||
| mock_canonicalize.side_effect = self.mock_canonicalize_function | ||
|
|
||
| as2message.build( | ||
| self.payload, | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we are using the same payload as the other tests so how is canonicalize_as_binary affecting this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me try to elaborate. The symptoms I had seen, which this functionality resolves was: So in order to mimic that someone basically sends and creates the signature to only have content with just
I chose the later.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would choose the first option here because the intent of the test is more clear
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I can change it - not sure I can make it before May though - just fixing the content did not yield the result, so will need more time to dig into it. Making the first option has another downside - if for whatever reason we need to recreate the content, the way how it was done will be lost (unless someone will find this discussion here). I do question however, if the efforts to make this "round trip" test is worthwhile as the functionality in pyas2-lib was made to patch a specific partner solution that in my opinion behaves out of standard specifications. |
||
| filename="testmessage.edi", | ||
| subject=partner.subject, | ||
| content_type=partner.content_type, | ||
| ) | ||
|
|
||
| in_message, _ = Message.objects.create_from_as2message( | ||
| as2message=as2message, payload=self.payload, direction="OUT", status="P" | ||
| ) | ||
|
|
||
| mock_request.side_effect = SendMessageMock(self.client) | ||
| in_message.send_message( | ||
| as2message.headers, self.mock_message_content(as2message) | ||
| ) | ||
|
|
||
| # Check if message was processed successfully | ||
| out_message = Message.objects.get( | ||
| message_id=in_message.message_id, direction="IN" | ||
| ) | ||
|
|
||
| receiver.canonicalize_as_binary = False | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are we doing this here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "receiver"'s canonicalize_as_binary is set to False by default in the setup. I do set it to True to test the functionality during the test and then set it back to the setup value. I probably should persist the initial value of the setup and the reset to that. Will make that change as well in next update. |
||
| receiver.save() | ||
|
|
||
| self.assertEqual(out_message.status, "S") | ||
| self.assertTrue(out_message.signed) | ||
| self.assertEqual(in_message.status, "S") | ||
| self.assertIsNotNone(in_message.mdn) | ||
|
|
||
| # Check if input and output files are the same | ||
| self.assertTrue( | ||
| self.compareFiles(in_message.payload.name, out_message.payload.name) | ||
| ) | ||
|
|
||
| @mock.patch("requests.post") | ||
| def build_and_send(self, partner, mock_request): | ||
| # Build and send the message to server | ||
|
|
@@ -565,6 +627,20 @@ def compareFiles(filename1, filename2): | |
| lineA == lineB for lineA, lineB in zip(a.readlines(), b.readlines()) | ||
| ) | ||
|
|
||
| @staticmethod | ||
| def mock_message_content(message): | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this needed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as2message.content uses mime_to_bytes which will replace with . Different outputs will be like this: Without Send Message Mock:
With sending Message Mock:
|
||
| """Prevent binary content line feeds of being altered when sending.""" | ||
| message_bytes = message.payload.as_bytes() | ||
| boundary = b"--" + message.payload.get_boundary().encode("utf-8") | ||
| temp = message_bytes.split(boundary) | ||
| temp.pop(0) | ||
| return boundary + boundary.join(temp) | ||
|
|
||
| @staticmethod | ||
| def mock_canonicalize_function(email_msg, canonicalize_as_binary=False): | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are we doing this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On SENDING, pyas2-lib does not process "canonicalize_as_binary" for the receiving partner, so we need to simulate this. It is not something we want to put our outgoing functionality and also should not put into pyas2-lib. So this is for simulation only. Without Mock:
With Mock:
|
||
| """Explicitly ignore the canonicalize_as_binary argument and force it to True.""" | ||
| return canonicalize(email_msg, canonicalize_as_binary=True) | ||
|
|
||
|
|
||
| class SendMessageMock(object): | ||
| def __init__(self, test_client): | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.