From 94a13aabf0023fd8c3224e08669833ff8e1c7056 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Sun, 24 Sep 2017 15:43:23 +0200 Subject: [PATCH] Handle nginx authentication requests in the admin container --- admin/mailu/__init__.py | 3 +- admin/mailu/internal/__init__.py | 6 +++ admin/mailu/internal/nginx.py | 64 ++++++++++++++++++++++++++++++++ admin/mailu/internal/views.py | 14 +++++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 admin/mailu/internal/__init__.py create mode 100644 admin/mailu/internal/nginx.py create mode 100644 admin/mailu/internal/views.py diff --git a/admin/mailu/__init__.py b/admin/mailu/__init__.py index 947a72f9..e62ea738 100644 --- a/admin/mailu/__init__.py +++ b/admin/mailu/__init__.py @@ -74,8 +74,9 @@ def inject_user(): return dict(current_user=flask_login.current_user) # Import views -from mailu import ui +from mailu import ui, internal app.register_blueprint(ui.ui, url_prefix='/ui') +app.register_blueprint(internal.internal, url_prefix='/internal') # Create the prefix middleware class PrefixMiddleware(object): diff --git a/admin/mailu/internal/__init__.py b/admin/mailu/internal/__init__.py new file mode 100644 index 00000000..9e8c3690 --- /dev/null +++ b/admin/mailu/internal/__init__.py @@ -0,0 +1,6 @@ +from flask import Blueprint + + +internal = Blueprint('internal', __name__) + +from mailu.internal import views diff --git a/admin/mailu/internal/nginx.py b/admin/mailu/internal/nginx.py new file mode 100644 index 00000000..6fcb3b2b --- /dev/null +++ b/admin/mailu/internal/nginx.py @@ -0,0 +1,64 @@ +from mailu import db, models + + +SUPPORTED_AUTH_METHODS = ["none", "plain"] + +STATUSES = { + "authentication": ("Authentication credentials invalid", { + "imap": "AUTHENTICATIONFAILED", + "smtp": "535 5.7.8", + "pop3": "" + }), +} + + +def handle_authentication(headers): + """ Handle an HTTP nginx authentication request + See: http://nginx.org/en/docs/mail/ngx_mail_auth_http_module.html#protocol + """ + method = headers["Auth-Method"] + protocol = headers["Auth-Protocol"] + server, port = get_server(headers["Auth-Protocol"]) + # Incoming mail, no authentication + if method == "none" and protocol == "smtp": + return { + "Auth-Status": "OK", + "Auth-Server": server, + "Auth-Port": port + } + # Authenticated user + elif method == "plain": + user_email = headers["Auth-User"] + password = headers["Auth-Pass"] + user = models.User.query.get(user_email) + if user and user.check_password(password): + return { + "Auth-Status": "OK", + "Auth-Server": server, + "Auth-Port": port + } + else: + status, code = get_status(protocol, "authentication") + return { + "Auth-Status": status, + "Auth-Error-Code": code, + "Auth-Wait": 0 + } + # Unexpected + else: + return {} + + +def get_status(protocol, status): + """ Return the proper error code depending on the protocol + """ + status, codes = STATUSES[status] + return status, codes[protocol] + + +def get_server(protocol): + servers = { + "imap": ("172.18.0.12", 143), + "smtp": ("172.18.0.9", 25) + } + return servers[protocol] diff --git a/admin/mailu/internal/views.py b/admin/mailu/internal/views.py new file mode 100644 index 00000000..f1dd9d19 --- /dev/null +++ b/admin/mailu/internal/views.py @@ -0,0 +1,14 @@ +from mailu import db, models +from mailu.internal import internal, nginx + +import flask + + +@internal.route("/nginx") +def nginx_authentication(): + headers = nginx.handle_authentication(flask.request.headers) + response = flask.Response() + for key, value in headers.items(): + response.headers[key] = str(value) + return response +