2265: Prevent an exception from being thrown if the username isn't an email address r=mergify[bot] a=nextgens

## What type of PR?

enhancement

## What does this PR do?

Mailu expects users to identify using an email address; some brute-force script don't send just an username and this leads to an exception... that makes the error message and return code vary.

This PR prevents the exceptions from being thrown in the first place

```
WARNING in nginx: Invalid user 'xxxx': (builtins.ValueError) invalid email address (no "`@")"`
```

### Related issue(s)
- closes #2261
- closes #1750

Co-authored-by: Florent Daigniere <nextgens@freenetproject.org>
Co-authored-by: Florent Daigniere <nextgens@users.noreply.github.com>
master
bors[bot] 3 years ago committed by GitHub
commit fe7397bedf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -93,8 +93,8 @@ def handle_authentication(headers):
app.logger.warn(f'Received undecodable user/password from nginx: {raw_user_email!r}/{raw_password!r}')
else:
try:
user = models.User.query.get(user_email)
is_valid_user = True
user = models.User.query.get(user_email) if '@' in user_email else None
is_valid_user = user is not None
except sqlalchemy.exc.StatementError as exc:
exc = str(exc).split('\n', 1)[0]
app.logger.warn(f'Invalid user {user_email!r}: {exc}')

@ -12,7 +12,7 @@ def nginx_authentication():
"""
client_ip = flask.request.headers["Client-Ip"]
headers = flask.request.headers
if headers["Auth-Port"] == '25' and headers['Auth-Method'] == 'plain':
if headers["Auth-Port"] == '25':
response = flask.Response()
response.headers['Auth-Status'] = 'AUTH not supported'
response.headers['Auth-Error-Code'] = '502 5.5.1'

@ -5,6 +5,7 @@ from flask import current_app as app
import flask
import idna
import re
import sqlalchemy.exc
import srslib
@internal.route("/postfix/dane/<domain_name>")
@ -158,18 +159,13 @@ def postfix_sender_rate(sender):
def postfix_sender_access(sender):
""" Simply reject any sender that pretends to be from a local domain
"""
if not is_void_address(sender):
localpart, domain_name = models.Email.resolve_domain(sender)
return flask.jsonify("REJECT") if models.Domain.query.get(domain_name) else flask.abort(404)
else:
return flask.abort(404)
def is_void_address(email):
'''True if the email is void (null) email address.
'''
if email.startswith('<') and email.endswith('>'):
email = email[1:-1]
# Some MTAs use things like '<MAILER-DAEMON>' instead of '<>'; so let's
# consider void any such thing.
return '@' not in email
if '@' in sender:
if sender.startswith('<') and sender.endswith('>'):
sender = sender[1:-1]
try:
localpart, domain_name = models.Email.resolve_domain(sender)
if models.Domain.query.get(domain_name):
return flask.jsonify("REJECT")
except sqlalchemy.exc.StatementError:
pass
return flask.abort(404)

Loading…
Cancel
Save