mirror of
https://github.com/chatmail/relay.git
synced 2026-05-11 16:34:39 +00:00
Compare commits
5 Commits
link2xt/py
...
allow_k9_e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cd096f4ce | ||
|
|
21778fa4f3 | ||
|
|
14342383cf | ||
|
|
926de76010 | ||
|
|
ee25d35db1 |
@@ -17,7 +17,8 @@ def check_encrypted(message):
|
|||||||
"""Check that the message is an OpenPGP-encrypted message."""
|
"""Check that the message is an OpenPGP-encrypted message."""
|
||||||
if not message.is_multipart():
|
if not message.is_multipart():
|
||||||
return False
|
return False
|
||||||
if message.get("subject") != "...":
|
subject = message.get("subject")
|
||||||
|
if subject not in ("...", "Encrypted Message"):
|
||||||
return False
|
return False
|
||||||
if message.get_content_type() != "multipart/encrypted":
|
if message.get_content_type() != "multipart/encrypted":
|
||||||
return False
|
return False
|
||||||
|
|||||||
92
chatmaild/src/chatmaild/tests/mail-data/encrypted-k9.eml
Normal file
92
chatmaild/src/chatmaild/tests/mail-data/encrypted-k9.eml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
Date: Mon, 05 Feb 2024 12:22:17 +0100
|
||||||
|
From: Jus <tqwertyjd@nine.testrun.org>
|
||||||
|
To: REDACTED
|
||||||
|
User-Agent: K-9 Mail for Android
|
||||||
|
Message-ID: <A238D610-1471-4A32-B387-B07811665F6D@nine.testrun.org>
|
||||||
|
Autocrypt: addr=tqwertyjd@nine.testrun.org; keydata=
|
||||||
|
mQGNBGWNXoMBDAC+D3Na6zJX8d8NEIIoYqcGsOeJCtPs4DZIE8x4nVIRewwG6+CU0/Su8J1sdNL8
|
||||||
|
InVYnE0DUnRfL9RpT/6oHPsbuN8Yo/xyZbc6Df0MgstrbkiIpIb6YdpMB9vnS9phpTDXuVXwOdb+
|
||||||
|
Q8woi46bZ4jdCm1x/5zW8e2fbahHSSFjDYTKydu3SVTeKPNVdHv9gG7SNQy0emOCP7NXxloi8+aR
|
||||||
|
4fbgfWpm6yb/pJFDH6jmPZ8LK228qXqSv6urquaCu/yD4S+XR/DvGqj2lA/ntvNhDOjrK4gWt5EA
|
||||||
|
4djfnTK6z/vt/IkSSca5ITjcbyPBpXnId896NQk76sAdG+K+mJGMJn9YahoI4UvISfCp/B5Fw3Bq
|
||||||
|
5NmeL5zKN14R5AW5E/Y2J693MJ+VubRoB3VR/RZi5ZeEd1aLkxhqITv6m8FRXrSpC6fIhbqAZGmm
|
||||||
|
91OAAVNn5/MqaAaWJ5iUKGlNJrDFHVBXEpNah24FEoe6olNiBDNnWJ9tqOmZIiIDPCl8FIEAEQEA
|
||||||
|
AbQadHF3ZXJ0eWpkQG5pbmUudGVzdHJ1bi5vcmeJAbAEEwEKABoECwkIBwIVCgIWAQIZAAWCZY1e
|
||||||
|
gwKeAQKbAwAKCRDtNhlhxu8KoFcjDACfMwEEuEStLsY8Wo/r/mmhZKLjgwRgdcVV7sFpksgk+Myy
|
||||||
|
UyL5VUEi9KVd4lKWNqDSi9S67lW+6hwf/kUrycVIT5AA0i8ZXdtroUpkUIwMOaSEfGpUhPI/kQbz
|
||||||
|
wqYJYES1XPqtpUmL4WR+52CHwtEeKZp+jiKnSNeh1QocBYjld0617dpb6XnAVl+69sQUHioxX7Bu
|
||||||
|
c60CuABcFw78/9hvzX37NC7mvP1vbYS7iEze5p2CUweKtrnnDJpi+oBLAucKQRErIUfJUV/XFdE4
|
||||||
|
j4m+NWAtcnyRVx3WruEWW+fzzb7+fc3fwV8pGCUcD4cb/Bzssg3LVLQiBENRXTmTc5RFxQXWbZae
|
||||||
|
5f6VLAkVEdoxOMVT2dCjLbwo1nPl9emTTIneRLjLX/cTNdbVZuq/Kv/SoXa05ayljSlZmrCF8k3x
|
||||||
|
zESSeJLrrHkoSPoXECeAJbZyMYmOxZPZChVQhUCxDBAR9wzJmLoHBxoDxYMq16S+Ws4Z+lR2cHj2
|
||||||
|
4lFAMIzCKsy5AY0EZY1egwEMAIkCo235tKDEUjcW8w77AHFf6+W0183E7US8ze3C8T3UUDsh1nQn
|
||||||
|
h+nZFOnKBRNQHUwRzWgV0ZQmllTrZt67fHOwywqHtaQMe90cZXbvhVoTzehw3B9bYT1j/24LDMy/
|
||||||
|
/eQBZuQeSlcLD6+BC0ro7EGxn5T24CAsmMjrI2ppjgZFlcXo9bA+Xp6rI/HX8AQgWbbegtGnSIDB
|
||||||
|
K20+e+xWANaWUsSBhIwsx2qz0IEq+RER60Zd1xZ41acVyNbDHNocEBnfzOF4GXRAz4M/v9l7ABep
|
||||||
|
21ALLC/OOKuC8cZDeY+HAbJ0qxggh//+ucpfBF0poOQDJzfNaOGysfn/0NGfxRVbFJc8fNc9P5+K
|
||||||
|
fnjm4RdNkwQRXQeQfqPU9a4AlAH5vl8zHabyYIJUUtP+b7VF6VPfSVzJ+h4BPPIVS/TqKQM6HShX
|
||||||
|
rGs9/DcXfDfcIXxhAfo2M+VKkrlunBev0OrhIDLNn5IigNIa78ZN9cZ/3SZVTfOzFnFuFtnO50tv
|
||||||
|
q5OpvQARAQABiQGfBBgBCgAJBYJljV6DApsMAAoJEO02GWHG7wqgwnQL/ijcTiKNO2Cw4pvgggbL
|
||||||
|
8e2mgXCQn0aNufbYeylGdX/BP2SMRku5OubjESU0oMVx/Hhy19UkUFhCuOeouSNsbTd6w8Ou+nkh
|
||||||
|
6bs4KJvhMUFVQe6dE8Reci3EoImcTxV9nqWuvhdXkPddht9Pa5PoRpJlpWxHKpMfrPwWtbW/J8qn
|
||||||
|
dnnc+x9FqxLVY+Z75GbrrMI/I2ClvbfgMnOGQxyZRhcPesiaMyp4bYbX3zxrIZXSG68CQERiMXk8
|
||||||
|
UAeZFPgnm4Hh0rP5cn9enn8tj67ruFsEAU3YMi7eOVOSFlamjH0PTVr3ztdoMathEL7n1s5ksk5b
|
||||||
|
Rgo0SgQy4OgApJIB0B16Zhcd66I4sTZLb2RRkFO9uHDFIOuJGTqYfR3ZjWlEftfxW80g7uLZYwfW
|
||||||
|
gzMOEa9jSZpfWpiWDYfVYcHqQTOAoyc1ndwJno/4pO+kRmYoIUaoBqNqiqNtnTl9eiJHcb8kuaxa
|
||||||
|
PP5Qy9N6C2QONUAb4aFBPe0cYXQ6AUnOqBmd3w==
|
||||||
|
Subject: Encrypted Message
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
Content-Type: multipart/encrypted; boundary="----GAXGEBIG1Q6UA7H3D91DE8MM3Q54OF";
|
||||||
|
protocol="application/pgp-encrypted"
|
||||||
|
|
||||||
|
------GAXGEBIG1Q6UA7H3D91DE8MM3Q54OF
|
||||||
|
Content-Type: application/pgp-encrypted
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
|
||||||
|
Version: 1
|
||||||
|
------GAXGEBIG1Q6UA7H3D91DE8MM3Q54OF
|
||||||
|
Content-Type: application/octet-stream; name="encrypted.asc"
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
Content-Disposition: inline; filename="encrypted.asc"
|
||||||
|
|
||||||
|
-----BEGIN PGP MESSAGE-----
|
||||||
|
|
||||||
|
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
|
||||||
|
MrxVY64iHOwasTdMu9F+fv8+akI=
|
||||||
|
=Dj6B
|
||||||
|
-----END PGP MESSAGE-----
|
||||||
|
|
||||||
|
------GAXGEBIG1Q6UA7H3D91DE8MM3Q54OF--
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import random
|
import random
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
import importlib.resources
|
import importlib.resources
|
||||||
import itertools
|
import itertools
|
||||||
from email.parser import BytesParser
|
from email.parser import BytesParser
|
||||||
@@ -57,7 +59,12 @@ def db(tmpdir):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def maildata(request):
|
def maildata(request):
|
||||||
datadir = importlib.resources.files(__package__).joinpath("mail-data")
|
try:
|
||||||
|
datadir = importlib.resources.files(__package__).joinpath("mail-data")
|
||||||
|
except TypeError:
|
||||||
|
# in python3.9 or lower, the above doesn't work, so we get datadir this way:
|
||||||
|
datadir = Path(os.getcwd()).joinpath("chatmaild/src/chatmaild/tests/mail-data")
|
||||||
|
|
||||||
assert datadir.exists(), datadir
|
assert datadir.exists(), datadir
|
||||||
|
|
||||||
def maildata(name, from_addr, to_addr):
|
def maildata(name, from_addr, to_addr):
|
||||||
|
|||||||
@@ -63,6 +63,17 @@ def test_filtermail_encryption_detection(maildata):
|
|||||||
assert not check_encrypted(msg)
|
assert not check_encrypted(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def test_filtermail_encryption_detection_k9subject(maildata):
|
||||||
|
msg = maildata(
|
||||||
|
"encrypted-k9.eml", from_addr="1@example.org", to_addr="2@example.org"
|
||||||
|
)
|
||||||
|
assert check_encrypted(msg)
|
||||||
|
|
||||||
|
# if the subject is not "..." it is not considered ac-encrypted
|
||||||
|
msg.replace_header("Subject", "Click this link")
|
||||||
|
assert not check_encrypted(msg)
|
||||||
|
|
||||||
|
|
||||||
def test_filtermail_is_mdn(maildata, gencreds, handler):
|
def test_filtermail_is_mdn(maildata, gencreds, handler):
|
||||||
from_addr = gencreds()[0]
|
from_addr = gencreds()[0]
|
||||||
to_addr = gencreds()[0] + ".other"
|
to_addr = gencreds()[0] + ".other"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import importlib
|
|||||||
import subprocess
|
import subprocess
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class DNS:
|
class DNS:
|
||||||
def __init__(self, out, mail_domain):
|
def __init__(self, out, mail_domain):
|
||||||
@@ -34,7 +36,7 @@ class DNS:
|
|||||||
cmd = "ip a | grep inet6 | grep 'scope global' | sed -e 's#/64 scope global##' | sed -e 's#inet6##'"
|
cmd = "ip a | grep inet6 | grep 'scope global' | sed -e 's#/64 scope global##' | sed -e 's#inet6##'"
|
||||||
return self.shell(cmd).strip()
|
return self.shell(cmd).strip()
|
||||||
|
|
||||||
def get(self, typ: str, domain: str) -> str | None:
|
def get(self, typ: str, domain: str) -> Optional[str]:
|
||||||
"""Get a DNS entry"""
|
"""Get a DNS entry"""
|
||||||
dig_result = self.shell(f"dig -r -q {domain} -t {typ} +short")
|
dig_result = self.shell(f"dig -r -q {domain} -t {typ} +short")
|
||||||
line = dig_result.partition("\n")[0]
|
line = dig_result.partition("\n")[0]
|
||||||
@@ -54,22 +56,25 @@ def show_dns(args, out) -> int:
|
|||||||
ssh = f"ssh root@{mail_domain}"
|
ssh = f"ssh root@{mail_domain}"
|
||||||
dns = DNS(out, mail_domain)
|
dns = DNS(out, mail_domain)
|
||||||
|
|
||||||
def read_dkim_entries(entry):
|
|
||||||
lines = []
|
|
||||||
for line in entry.split("\n"):
|
|
||||||
if line.startswith(";") or not line.strip():
|
|
||||||
continue
|
|
||||||
line = line.replace("\t", " ")
|
|
||||||
lines.append(line)
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
print("Checking your DKIM keys and DNS entries...")
|
print("Checking your DKIM keys and DNS entries...")
|
||||||
try:
|
try:
|
||||||
acme_account_url = out.shell_output(f"{ssh} -- acmetool account-url")
|
acme_account_url = out.shell_output(f"{ssh} -- acmetool account-url")
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print("Please run `cmdeploy run` first.")
|
print("Please run `cmdeploy run` first.")
|
||||||
return 1
|
return 1
|
||||||
dkim_entry = read_dkim_entries(out.shell_output(f"{ssh} -- opendkim-genzone -F"))
|
|
||||||
|
dkim_selector = "opendkim"
|
||||||
|
dkim_pubkey = out.shell_output(
|
||||||
|
ssh + f" -- openssl rsa -in /etc/dkimkeys/{dkim_selector}.private"
|
||||||
|
" -pubout 2>/dev/null | awk '/-/{next}{printf(\"%s\",$0)}'"
|
||||||
|
)
|
||||||
|
dkim_entry_value = f"v=DKIM1;k=rsa;p={dkim_pubkey};s=email;t=s"
|
||||||
|
dkim_entry_str = ""
|
||||||
|
while len(dkim_entry_value) >= 255:
|
||||||
|
dkim_entry_str += '"' + dkim_entry_value[:255] + '" '
|
||||||
|
dkim_entry_value = dkim_entry_value[255:]
|
||||||
|
dkim_entry_str += '"' + dkim_entry_value + '"'
|
||||||
|
dkim_entry = f"{dkim_selector}._domainkey.{mail_domain}. TXT {dkim_entry_str}"
|
||||||
|
|
||||||
ipv6 = dns.get_ipv6()
|
ipv6 = dns.get_ipv6()
|
||||||
reverse_ipv6 = dns.check_ptr_record(ipv6, mail_domain)
|
reverse_ipv6 = dns.check_ptr_record(ipv6, mail_domain)
|
||||||
@@ -97,7 +102,6 @@ def show_dns(args, out) -> int:
|
|||||||
return 0
|
return 0
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
started_dkim_parsing = False
|
|
||||||
for line in zonefile.splitlines():
|
for line in zonefile.splitlines():
|
||||||
line = line.format(
|
line = line.format(
|
||||||
acme_account_url=acme_account_url,
|
acme_account_url=acme_account_url,
|
||||||
@@ -124,28 +128,23 @@ def show_dns(args, out) -> int:
|
|||||||
current = dns.get("SRV", domain[:-1])
|
current = dns.get("SRV", domain[:-1])
|
||||||
if current != f"{prio} {weight} {port} {value}":
|
if current != f"{prio} {weight} {port} {value}":
|
||||||
to_print.append(line)
|
to_print.append(line)
|
||||||
if " TXT " in line:
|
if " TXT " in line:
|
||||||
domain, value = line.split(" TXT ")
|
domain, value = line.split(" TXT ")
|
||||||
current = dns.get("TXT", domain.strip()[:-1])
|
current = dns.get("TXT", domain.strip()[:-1])
|
||||||
if domain.startswith("_mta-sts."):
|
if domain.startswith("_mta-sts."):
|
||||||
if current:
|
if current:
|
||||||
if current.split("id=")[0] == value.split("id=")[0]:
|
if current.split("id=")[0] == value.split("id=")[0]:
|
||||||
continue
|
continue
|
||||||
if current != value:
|
|
||||||
|
# TXT records longer than 255 bytes
|
||||||
|
# are split into multiple <character-string>s.
|
||||||
|
# This typically happens with DKIM record
|
||||||
|
# which contains long RSA key.
|
||||||
|
#
|
||||||
|
# Removing `" "` before comparison
|
||||||
|
# to get back a single string.
|
||||||
|
if current.replace('" "', "") != value.replace('" "', ""):
|
||||||
to_print.append(line)
|
to_print.append(line)
|
||||||
if "IN TXT ( " in line:
|
|
||||||
started_dkim_parsing = True
|
|
||||||
dkim_lines = [line]
|
|
||||||
if started_dkim_parsing and line.startswith('"'):
|
|
||||||
dkim_lines.append(" " + line)
|
|
||||||
domain, data = "\n".join(dkim_lines).split(" IN TXT ")
|
|
||||||
current = dns.get("TXT", domain.strip()[:-1])
|
|
||||||
if current:
|
|
||||||
current = "( %s )" % (current.replace('" "', '"\n "'))
|
|
||||||
if current.replace(";", "\\;") != data:
|
|
||||||
to_print.append(dkim_entry)
|
|
||||||
else:
|
|
||||||
to_print.append(dkim_entry)
|
|
||||||
|
|
||||||
exit_code = 0
|
exit_code = 0
|
||||||
if to_print:
|
if to_print:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import threading
|
import threading
|
||||||
import queue
|
import queue
|
||||||
|
import socket
|
||||||
|
|
||||||
from chatmaild.config import read_config
|
from chatmaild.config import read_config
|
||||||
from cmdeploy.cmdeploy import main
|
from cmdeploy.cmdeploy import main
|
||||||
@@ -78,3 +79,24 @@ def test_concurrent_logins_same_account(
|
|||||||
|
|
||||||
for _ in conns:
|
for _ in conns:
|
||||||
assert login_results.get()
|
assert login_results.get()
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_vrfy(chatmail_config):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock.connect((chatmail_config.mail_domain, 25))
|
||||||
|
banner = sock.recv(1024)
|
||||||
|
print(banner)
|
||||||
|
sock.send(b"VRFY wrongaddress@%s\r\n" % (chatmail_config.mail_domain.encode(),))
|
||||||
|
result = sock.recv(1024)
|
||||||
|
print(result)
|
||||||
|
sock.send(b"VRFY echo@%s\r\n" % (chatmail_config.mail_domain.encode(),))
|
||||||
|
result2 = sock.recv(1024)
|
||||||
|
print(result2)
|
||||||
|
assert result[0:10] == result2[0:10]
|
||||||
|
sock.send(b"VRFY wrongaddress\r\n")
|
||||||
|
result = sock.recv(1024)
|
||||||
|
print(result)
|
||||||
|
sock.send(b"VRFY echo\r\n")
|
||||||
|
result2 = sock.recv(1024)
|
||||||
|
print(result2)
|
||||||
|
assert result[0:10] == result2[0:10] == b"252 2.0.0 "
|
||||||
|
|||||||
Reference in New Issue
Block a user