Merge branch 'master' into fix-sender-checks

This commit is contained in:
kaiyou
2018-10-20 10:18:36 +02:00
committed by GitHub
36 changed files with 864 additions and 99 deletions

View File

@@ -7,7 +7,7 @@ COPY requirements-prod.txt requirements.txt
RUN apk add --no-cache openssl \
&& apk add --no-cache --virtual build-dep openssl-dev libffi-dev python-dev build-base \
&& pip install -r requirements.txt \
&& apk del build-dep
&& apk del --no-cache build-dep
COPY mailu ./mailu
COPY migrations ./migrations

View File

@@ -12,7 +12,7 @@ import docker
import socket
import uuid
from werkzeug.contrib import fixers
from werkzeug.contrib import fixers, profiler
# Create application
app = flask.Flask(__name__)
@@ -57,12 +57,15 @@ default_config = {
'RECAPTCHA_PUBLIC_KEY': '',
'RECAPTCHA_PRIVATE_KEY': '',
# Advanced settings
'PASSWORD_SCHEME': 'SHA512-CRYPT',
'PASSWORD_SCHEME': 'BLF-CRYPT',
# Host settings
'HOST_IMAP': 'imap',
'HOST_POP3': 'imap',
'HOST_SMTP': 'smtp',
'HOST_WEBMAIL': 'webmail',
'HOST_FRONT': 'front',
'HOST_AUTHSMTP': os.environ.get('HOST_SMTP', 'smtp'),
'POD_ADDRESS_RANGE': None
}
# Load configuration from the environment if available
@@ -80,6 +83,10 @@ if app.config.get("DEBUG"):
import flask_debugtoolbar
toolbar = flask_debugtoolbar.DebugToolbarExtension(app)
# Profiler
if app.config.get("DEBUG"):
app.wsgi_app = profiler.ProfilerMiddleware(app.wsgi_app, restrictions=[30])
# Manager commnad
manager = flask_script.Manager(app)
manager.add_command('db', flask_migrate.MigrateCommand)
@@ -129,4 +136,5 @@ class PrefixMiddleware(object):
environ['SCRIPT_NAME'] = prefix
return self.app(environ, start_response)
app.wsgi_app = PrefixMiddleware(fixers.ProxyFix(app.wsgi_app))

View File

@@ -1,14 +1,24 @@
from mailu import db, models
from mailu import db, models, app
from mailu.internal import internal
import flask
import socket
@internal.route("/dovecot/passdb/<user_email>")
def dovecot_passdb_dict(user_email):
user = models.User.query.get(user_email) or flask.abort(404)
allow_nets = []
allow_nets.append(
app.config.get("POD_ADDRESS_RANGE") or
socket.gethostbyname(app.config["HOST_FRONT"])
)
allow_nets.append(socket.gethostbyname(app.config["HOST_WEBMAIL"]))
print(allow_nets)
return flask.jsonify({
"password": user.password,
"password": None,
"nopassword": "Y",
"allow_nets": ",".join(allow_nets)
})

View File

@@ -287,8 +287,10 @@ class User(Base, Email):
def get_id(self):
return self.email
scheme_dict = {'SHA512-CRYPT': "sha512_crypt",
scheme_dict = {'PBKDF2': "pbkdf2_sha512",
'BLF-CRYPT': "bcrypt",
'SHA512-CRYPT': "sha512_crypt",
'SHA256-CRYPT': "sha256_crypt",
'MD5-CRYPT': "md5_crypt",
'CRYPT': "des_crypt"}
@@ -298,8 +300,14 @@ class User(Base, Email):
)
def check_password(self, password):
context = User.pw_context
reference = re.match('({[^}]+})?(.*)', self.password).group(2)
return User.pw_context.verify(password, reference)
result = context.verify(password, reference)
if result and context.identify(reference) != context.default_scheme():
self.set_password(password)
db.session.add(self)
db.session.commit()
return result
def set_password(self, password, hash_scheme=app.config['PASSWORD_SCHEME'], raw=False):
"""Set password for user with specified encryption scheme

View File

@@ -1,6 +1,7 @@
alembic==0.9.9
asn1crypto==0.24.0
Babel==2.5.3
bcrypt==3.1.4
blinker==1.4
certifi==2018.4.16
cffi==1.11.5

View File

@@ -17,3 +17,4 @@ tabulate
PyYAML
PyOpenSSL
dnspython
bcrypt

View File

@@ -2,7 +2,7 @@ FROM alpine:3.8
RUN apk add --no-cache \
dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \
python3 py3-pip \
bash python3 py3-pip \
&& pip3 install --upgrade pip \
&& pip3 install jinja2 podop tenacity

4
core/dovecot/conf/bin/ham Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
tee >(rspamc -h antispam:11334 -P mailu learn_ham /dev/stdin) \
| rspamc -h antispam:11334 -P mailu -f 13 fuzzy_add /dev/stdin

View File

@@ -1,3 +0,0 @@
#!/bin/sh
rspamc -h antispam:11334 -P mailu "learn_$1" /dev/stdin <&0

4
core/dovecot/conf/bin/spam Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
tee >(rspamc -h antispam:11334 -P mailu learn_spam /dev/stdin) \
>(rspamc -h antispam:11334 -P mailu -f 11 fuzzy_add /dev/stdin)

View File

@@ -136,7 +136,8 @@ service managesieve {
}
plugin {
sieve = dict:proxy:/tmp/podop.socket:sieve
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_before = dict:proxy:/tmp/podop.socket:sieve
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_extensions = +spamtest +spamtestplus +editheader
sieve_global_extensions = +vnd.dovecot.execute

View File

@@ -8,4 +8,4 @@ if string "${mailbox}" "Trash" {
stop;
}
execute :pipe "mailtrain" "ham";
execute :pipe "ham";

View File

@@ -1,3 +1,3 @@
require "vnd.dovecot.execute";
execute :pipe "mailtrain" "spam";
execute :pipe "spam";

View File

@@ -36,5 +36,5 @@ for dovecot_file in glob.glob("/conf/*.conf"):
# Run Podop, then postfix
multiprocessing.Process(target=start_podop).start()
os.system("chown -R mail:mail /mail /var/lib/dovecot")
os.system("chown -R mail:mail /mail /var/lib/dovecot /conf")
os.execv("/usr/sbin/dovecot", ["dovecot", "-c", "/etc/dovecot/dovecot.conf", "-F"])

View File

@@ -91,8 +91,10 @@ http {
{% endif %}
location {{ WEB_WEBMAIL }} {
{% if WEB_WEBMAIL != '/' %}
rewrite ^({{ WEB_WEBMAIL }})$ $1/ permanent;
rewrite ^{{ WEB_WEBMAIL }}/(.*) /$1 break;
{% endif %}
include /etc/nginx/proxy.conf;
client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
proxy_pass http://$webmail;

View File

@@ -32,7 +32,7 @@ relayhost = {{ RELAYHOST }}
recipient_delimiter = {{ RECIPIENT_DELIMITER }}
# Only the front server is allowed to perform xclient
smtpd_authorized_xclient_hosts={{ FRONT_ADDRESS }}
smtpd_authorized_xclient_hosts={{ FRONT_ADDRESS }} {{ POD_ADDRESS_RANGE }}
###############
# TLS