|
| 1 | +# Copyright 2014-2021 The aiosmtpd Developers |
| 2 | +# SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +"""Test SMTP smuggling.""" |
| 5 | + |
| 6 | +from email.mime.text import MIMEText |
| 7 | +from smtplib import SMTP, SMTP_SSL |
| 8 | +from typing import Generator, Union |
| 9 | + |
| 10 | +import pytest |
| 11 | +import smtplib |
| 12 | + |
| 13 | +from aiosmtpd.controller import Controller |
| 14 | +from aiosmtpd.testing.helpers import ReceivingHandler |
| 15 | +from aiosmtpd.testing.statuscodes import SMTP_STATUS_CODES as S |
| 16 | + |
| 17 | +from aiosmtpd.smtp import SMTP as Server |
| 18 | +from aiosmtpd.smtp import Session as ServerSession |
| 19 | +from aiosmtpd.smtp import Envelope |
| 20 | + |
| 21 | +from .conftest import Global, controller_data, handler_data |
| 22 | + |
| 23 | +from aiosmtpd.testing.helpers import ( |
| 24 | + ReceivingHandler |
| 25 | +) |
| 26 | + |
| 27 | +def new_data(self, msg): |
| 28 | + self.putcmd("data") |
| 29 | + |
| 30 | + (code, repl) = self.getreply() |
| 31 | + if self.debuglevel > 0: |
| 32 | + self._print_debug('data:', (code, repl)) |
| 33 | + if code != 354: |
| 34 | + raise SMTPDataError(code, repl) |
| 35 | + else: |
| 36 | + ##### Patching input encoding so we can send raw messages |
| 37 | + #if isinstance(msg, str): |
| 38 | + # msg = smtplib._fix_eols(msg).encode('ascii') |
| 39 | + #q = smtplib._quote_periods(msg) |
| 40 | + #if q[-2:] != smtplib.bCRLF: |
| 41 | + # q = q + smtplib.bCRLF |
| 42 | + #q = q + b"." + smtplib.bCRLF |
| 43 | + q = msg |
| 44 | + self.send(q) |
| 45 | + (code, msg) = self.getreply() |
| 46 | + if self.debuglevel > 0: |
| 47 | + self._print_debug('data:', (code, msg)) |
| 48 | + return (code, msg) |
| 49 | + |
| 50 | +def return_unchanged(data): |
| 51 | + return data |
| 52 | + |
| 53 | +class TestSmuggling: |
| 54 | + @handler_data(class_=ReceivingHandler) |
| 55 | + def test_smtp_smuggling(self, plain_controller, client): |
| 56 | + smtplib._fix_eols = return_unchanged |
| 57 | + smtplib._quote_periods = return_unchanged |
| 58 | + smtplib.SMTP.data = new_data |
| 59 | + |
| 60 | + handler = plain_controller.handler |
| 61 | + sender = "sender@example.com" |
| 62 | + recipients = ["rcpt1@example.com"] |
| 63 | + resp = client.helo("example.com") |
| 64 | + assert resp == S.S250_FQDN |
| 65 | + # Trying SMTP smuggling with a fake \n.\r\n end-of-data sequence. |
| 66 | + message_data = b"""\ |
| 67 | +From: Anne Person <anne@example.com>\r\n\ |
| 68 | +To: Bart Person <bart@example.com>\r\n\ |
| 69 | +Subject: A test\r\n\ |
| 70 | +Message-ID: <ant>\r\n\ |
| 71 | +\r\n\ |
| 72 | +Testing\ |
| 73 | +\n.\r\n\ |
| 74 | +NO SMUGGLING |
| 75 | +\r\n.\r\n\ |
| 76 | +""" |
| 77 | + results = client.sendmail(sender, recipients, message_data) |
| 78 | + client.quit() |
| 79 | + assert b"NO SMUGGLING" in handler.box[0].content |
0 commit comments