Compare commits

...

9 Commits

Author SHA1 Message Date
missytake
6b6f6f1c50 tried to write a test to test exceeded quota, but not sure delta even gets a proper error on recipient's full mailbox 2023-10-16 01:51:17 +02:00
missytake
f4cf4ab955 sieve is not installed and we don't need it 2023-10-16 01:41:38 +02:00
holger krekel
48d890ee82 make quota work 2023-10-16 01:41:36 +02:00
missytake
3c57155c40 fix: typo in postfix/master.cf 2023-10-16 01:31:03 +02:00
link2xt
cf1be90115 Switch from BLF-CRYPT to SHA512-CRYPT 2023-10-15 21:42:14 +00:00
link2xt
5781d3b04e Make scripts/measure_tls_and_logins.py executable 2023-10-15 21:42:14 +00:00
link2xt
862b09d268 dovecot: enable authentication cache 2023-10-15 21:42:14 +00:00
link2xt
9b438a7a96 Test different users logging in with the same password 2023-10-15 21:42:14 +00:00
link2xt
a107fb3cca Avoid reusing accounts between tests
Add time as a prefix.
2023-10-15 21:42:14 +00:00
10 changed files with 84 additions and 18 deletions

View File

@@ -16,7 +16,7 @@ def encrypt_password(password: str):
password = password.encode("ascii") password = password.encode("ascii")
# https://doc.dovecot.org/configuration_manual/authentication/password_schemes/ # https://doc.dovecot.org/configuration_manual/authentication/password_schemes/
process = subprocess.Popen( process = subprocess.Popen(
["doveadm", "pw", "-s", "BLF-CRYPT"], ["doveadm", "pw", "-s", "SHA512-CRYPT"],
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
) )
@@ -59,7 +59,7 @@ def handle_dovecot_request(msg, db):
if short_command == "L": # LOOKUP if short_command == "L": # LOOKUP
parts = msg[1:].split("\t") parts = msg[1:].split("\t")
keyname, user = parts[:2] keyname, user = parts[:2]
namespace, type, arg = keyname.split("/", 3) namespace, type, *args = keyname.split("/")
reply_command = "F" reply_command = "F"
res = "" res = ""
if namespace == "shared": if namespace == "shared":
@@ -70,7 +70,7 @@ def handle_dovecot_request(msg, db):
else: else:
reply_command = "N" reply_command = "N"
elif type == "passdb": elif type == "passdb":
res = lookup_passdb(db, user, password=arg) res = lookup_passdb(db, user, password=args[0])
if res: if res:
reply_command = "O" reply_command = "O"
else: else:

View File

@@ -1,5 +1,5 @@
uri = proxy:/run/dovecot/doveauth.socket:auth uri = proxy:/run/dovecot/doveauth.socket:auth
iterate_disable = yes iterate_disable = yes
default_pass_scheme = plain default_pass_scheme = plain
password_key = passdb/%w password_key = passdb/%w/%u
user_key = userdb/%u user_key = userdb/%u

View File

@@ -4,10 +4,14 @@ protocols = imap lmtp
auth_mechanisms = plain auth_mechanisms = plain
auth_verbose = yes mail_plugins = quota
auth_debug = yes mail_debug = yes
auth_debug_passwords = yes
auth_verbose_passwords = plain # uncomment this if you want to debug authentication and user creation
#auth_verbose = yes
#auth_debug = yes
#auth_debug_passwords = yes
#auth_verbose_passwords = plain
# Authentication for system users. # Authentication for system users.
passdb { passdb {
@@ -59,13 +63,28 @@ mail_privileged_group = vmail
# Enable IMAP COMPRESS (RFC 4978). # Enable IMAP COMPRESS (RFC 4978).
# <https://datatracker.ietf.org/doc/html/rfc4978.html> # <https://datatracker.ietf.org/doc/html/rfc4978.html>
protocol imap { protocol imap {
mail_plugins = $mail_plugins imap_zlib mail_plugins = $mail_plugins imap_zlib imap_quota
}
protocol lmtp {
mail_plugins = $mail_plugins quota
} }
plugin { plugin {
imap_compress_deflate_level = 6 imap_compress_deflate_level = 6
} }
plugin {
# for now we define static quota-rules for all users
quota = maildir:User quota
quota_rule = *:storage=100M
quota_max_mail_size=30M
quota_grace = 0
quota_over_flag_value = TRUE
}
service lmtp { service lmtp {
user=vmail user=vmail

View File

@@ -28,7 +28,7 @@ submission inet n - y - - smtpd
-o smtpd_recipient_restrictions= -o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING -o milter_macro_daemon_name=ORIGINATING
-o content_filter=filter:unix:private/filtemail -o content_filter=filter:unix:private/filtermail
smtps inet n - y - - smtpd smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps -o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes -o smtpd_tls_wrappermode=yes

View File

@@ -4,6 +4,7 @@ import imaplib
import smtplib import smtplib
import itertools import itertools
import pytest import pytest
import time
@pytest.fixture @pytest.fixture
@@ -49,12 +50,13 @@ class SmtpConn:
@pytest.fixture @pytest.fixture
def gencreds(maildomain): def gencreds(maildomain):
prefix = str(time.time())
count = itertools.count() count = itertools.count()
def gen(): def gen():
while 1: while 1:
num = next(count) num = next(count)
yield f"user{num}@{maildomain}", f"password{num}" yield f"user{prefix}_{num}@{maildomain}", f"password{prefix}_{num}"
return lambda: next(gen()) return lambda: next(gen())

View File

@@ -12,6 +12,19 @@ class TestDovecot:
imap.connect() imap.connect()
imap.login(user, password) imap.login(user, password)
def test_login_same_password(self, imap, gencreds):
"""Test two different users logging in with the same password.
This ensures that authentication process does not confuse the users
by using only the password hash as a key.
"""
user1, password1 = gencreds()
user2, _password2 = gencreds()
imap.connect()
imap.login(user1, password1)
imap.connect()
imap.login(user2, password1)
def test_login_fail(self, imap, gencreds): def test_login_fail(self, imap, gencreds):
user, password = gencreds() user, password = gencreds()
imap.connect() imap.connect()

View File

@@ -1,3 +1,8 @@
import os.path
import random
import time
class TestMailSending: class TestMailSending:
def test_one_on_one(self, cmfactory, lp): def test_one_on_one(self, cmfactory, lp):
ac1, ac2 = cmfactory.get_online_accounts(2) ac1, ac2 = cmfactory.get_online_accounts(2)
@@ -9,3 +14,32 @@ class TestMailSending:
lp.sec("wait for ac2 to receive message") lp.sec("wait for ac2 to receive message")
msg2 = ac2._evtracker.wait_next_incoming_message() msg2 = ac2._evtracker.wait_next_incoming_message()
assert msg2.text == "message0" assert msg2.text == "message0"
def test_exceed_quota(self, cmfactory, lp, tmpdir):
ac1, ac2 = cmfactory.get_online_accounts(2)
chat = cmfactory.get_accepted_chat(ac1, ac2)
ac2.set_config("download_limit", 1024 * 2) # set download_limit to 2 KB avoid downloading all those 5MB files
lp.sec("ac1: send 25 5 MB files to ac2")
alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890"
for i in range(25):
attachment = tmpdir / f"attachment{i}"
with open(attachment, "w+") as f:
for j in range(1024 * 1024 * 5):
f.write(random.choice(alphanumeric))
print("Sent out msg", str(i))
chat.send_file(str(attachment))
ac2.wait_next_incoming_message()
lp.sec("ac2: check that at least one message failed")
failed = False
for i in range(25):
if chat.get_messages()[i].is_out_failed():
failed = True
print(chat.get_messages()[i].get_message_info())
try:
assert failed
except:
import pdb; pdb.set_trace()

View File

@@ -2,13 +2,10 @@
## Dovecot goals/steps ## Dovecot goals/steps
2. (holger) per-user storage quota (adaptive) - automatic expiry of messages older than M days
a) define a static 100MB per-user quota
3. automatic expiry of messages older than M days
- delete unconditionally messages older than 40 days - delete unconditionally messages older than 40 days
4. limit: max-connections per account - limit: configure max-connections per account
## Filtermail ## Filtermail

View File

@@ -7,7 +7,7 @@ domain = os.environ.get("CHATMAIL_DOMAIN", "c3.testrun.org")
print("connecting") print("connecting")
conn = imaplib.IMAP4_SSL(domain) conn = imaplib.IMAP4_SSL(domain)
print("logging in") print("logging in")
conn.login(f"measure{time.time()}", "pass") conn.login(f"imapcapa", "pass")
status, res = conn.capability() status, res = conn.capability()
for capa in sorted(res[0].decode().split()): for capa in sorted(res[0].decode().split()):
print(capa) print(capa)

1
scripts/measure_tls_and_logins.py Normal file → Executable file
View File

@@ -1,3 +1,4 @@
#!/usr/bin/env python3
import os import os
import time import time
import imaplib import imaplib