diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index 63dec50a..b5fda17d 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -28,9 +28,9 @@ STATUSES = { WEBMAIL_PORTS = ['14190', '10143', '10025'] -def check_credentials(user, password, ip, protocol=None, auth_port=None, source_port=None): +def check_credentials(user, password, ip, protocol=None, auth_port=None, source_port=None, raw_user=None): if not user or not user.enabled or (protocol == "imap" and not user.enable_imap and not auth_port in WEBMAIL_PORTS) or (protocol == "pop3" and not user.enable_pop): - app.logger.info(f'Login attempt for: {user}/{protocol}/{auth_port} from: {ip}/{source_port}: failed: account disabled') + app.logger.info(f'Login attempt for: {user or raw_user!r}/{protocol}/{auth_port} from: {ip}/{source_port}: failed: account disabled') return False # webmails if auth_port in WEBMAIL_PORTS and password.startswith('token-'): @@ -104,7 +104,7 @@ def handle_authentication(headers): else: is_valid_user = user is not None ip = urllib.parse.unquote(headers["Client-Ip"]) - if check_credentials(user, password, ip, protocol, headers["Auth-Port"], headers['Client-Port']): + if check_credentials(user, password, ip, protocol, headers["Auth-Port"], headers['Client-Port'], user_email): server, port = get_server(headers["Auth-Protocol"], True) return { "Auth-Status": "OK", diff --git a/core/admin/mailu/internal/views/auth.py b/core/admin/mailu/internal/views/auth.py index 51ffda9f..c51bf103 100644 --- a/core/admin/mailu/internal/views/auth.py +++ b/core/admin/mailu/internal/views/auth.py @@ -116,7 +116,7 @@ def basic_authentication(): exc = str(exc).split('\n', 1)[0] app.logger.warn(f'Invalid user {user_email!r}: {exc}') else: - if user is not None and nginx.check_credentials(user, password.decode('utf-8'), client_ip, "web", flask.request.headers.get('X-Real-Port', None)): + if user is not None and nginx.check_credentials(user, password.decode('utf-8'), client_ip, "web", flask.request.headers.get('X-Real-Port', None), user_email): response = flask.Response() response.headers["X-User"] = models.IdnaEmail.process_bind_param(flask_login, user.email, "") utils.limiter.exempt_ip_from_ratelimits(client_ip) diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py index 62b400d3..cc8a0950 100644 --- a/core/admin/mailu/internal/views/postfix.py +++ b/core/admin/mailu/internal/views/postfix.py @@ -125,6 +125,8 @@ def postfix_sender_map(sender): This is for bounces to come back the reverse path properly. """ + if sender.count('@') > 1 or sender.startswith('"'): + return flask.abort(404) srs = srslib.SRS(flask.current_app.srs_key) domain = flask.current_app.config["DOMAIN"] try: diff --git a/towncrier/newsfragments/2841.misc b/towncrier/newsfragments/2841.misc new file mode 100644 index 00000000..57a96f3b --- /dev/null +++ b/towncrier/newsfragments/2841.misc @@ -0,0 +1 @@ +Ensure we log which account was not found/invalid