1
0
mirror of https://github.com/Mailu/Mailu.git synced 2024-12-16 10:59:53 +02:00
Mailu/core/admin/mailu/internal/views/auth.py

98 lines
4.4 KiB
Python
Raw Normal View History

from mailu import models, utils
from mailu.internal import internal, nginx
from flask import current_app as app
import flask
import flask_login
import base64
2019-12-06 10:35:21 +02:00
@internal.route("/auth/email")
def nginx_authentication():
""" Main authentication endpoint for Nginx email server
"""
client_ip = flask.request.headers["Client-Ip"]
2021-09-23 18:40:49 +02:00
if utils.limiter.should_rate_limit_ip(client_ip):
status, code = nginx.get_status(flask.request.headers['Auth-Protocol'], 'ratelimit')
response = flask.Response()
2021-09-23 18:40:49 +02:00
response.headers['Auth-Status'] = status
response.headers['Auth-Error-Code'] = code
if int(flask.request.headers['Auth-Login-Attempt']) < 10:
response.headers['Auth-Wait'] = '3'
return response
headers = nginx.handle_authentication(flask.request.headers)
response = flask.Response()
for key, value in headers.items():
response.headers[key] = str(value)
2021-09-23 18:40:49 +02:00
is_valid_user = False
2021-10-16 09:36:49 +02:00
if response.headers.get("Auth-User-Exists"):
2021-09-23 18:40:49 +02:00
username = response.headers["Auth-User"]
if utils.limiter.should_rate_limit_user(username, client_ip):
# FIXME could be done before handle_authentication()
status, code = nginx.get_status(flask.request.headers['Auth-Protocol'], 'ratelimit')
response = flask.Response()
response.headers['Auth-Status'] = status
response.headers['Auth-Error-Code'] = code
if int(flask.request.headers['Auth-Login-Attempt']) < 10:
response.headers['Auth-Wait'] = '3'
return response
is_valid_user = True
2021-10-16 09:39:34 +02:00
if headers.get('Auth-Status') != 'OK':
2021-09-23 18:40:49 +02:00
utils.limiter.rate_limit_user(username, client_ip) if is_valid_user else rate_limit_ip(client_ip)
2021-10-16 09:39:34 +02:00
elif headers["Auth-Status"] == "OK":
2021-09-23 18:40:49 +02:00
utils.limiter.exempt_ip_from_ratelimits(client_ip)
return response
@internal.route("/auth/admin")
def admin_authentication():
""" Fails if the user is not an authenticated admin.
"""
if (not flask_login.current_user.is_anonymous
and flask_login.current_user.global_admin
and flask_login.current_user.enabled):
return ""
return flask.abort(403)
2021-02-06 18:23:05 +02:00
@internal.route("/auth/user")
def user_authentication():
""" Fails if the user is not authenticated.
"""
if (not flask_login.current_user.is_anonymous
and flask_login.current_user.enabled):
response = flask.Response()
response.headers["X-User"] = models.IdnaEmail.process_bind_param(flask_login, flask_login.current_user.get_id(), "")
2021-02-06 18:23:05 +02:00
response.headers["X-User-Token"] = models.User.get_temp_token(flask_login.current_user.get_id())
return response
return flask.abort(403)
@internal.route("/auth/basic")
def basic_authentication():
""" Tries to authenticate using the Authorization header.
"""
2021-10-16 09:36:49 +02:00
client_ip = flask.request.headers.get('X-Real-IP', flask.request.remote_addr)
2021-09-23 18:40:49 +02:00
if utils.limiter.should_rate_limit_ip(client_ip):
response = flask.Response(status=401)
response.headers["WWW-Authenticate"] = 'Basic realm="Authentication rate limit from one source exceeded"'
response.headers['Retry-After'] = '60'
return response
authorization = flask.request.headers.get("Authorization")
if authorization and authorization.startswith("Basic "):
encoded = authorization.replace("Basic ", "")
2021-07-14 09:25:04 +02:00
user_email, password = base64.b64decode(encoded).split(b":", 1)
2021-09-23 18:40:49 +02:00
user_email = user_email.decode("utf8")
if utils.limiter.should_rate_limit_user(user_email, client_ip):
response = flask.Response(status=401)
response.headers["WWW-Authenticate"] = 'Basic realm="Authentication rate limit for this username exceeded"'
response.headers['Retry-After'] = '60'
return response
user = models.User.query.get(user_email)
2021-10-16 10:39:43 +02:00
if user and nginx.check_credentials(user, password.decode('utf-8'), client_ip, "web"):
response = flask.Response()
response.headers["X-User"] = models.IdnaEmail.process_bind_param(flask_login, user.email, "")
2021-09-23 18:40:49 +02:00
utils.limiter.exempt_ip_from_ratelimits(client_ip)
return response
2021-09-23 18:40:49 +02:00
utils.limiter.rate_limit_user(user_email, client_ip) if user else utils.limiter.rate_limit_ip(client_ip)
response = flask.Response(status=401)
response.headers["WWW-Authenticate"] = 'Basic realm="Login Required"'
return response