From a14a7da11d7a7c83766533b634703573bfd21cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alban=20F=C3=A9ron?= Date: Fri, 14 Jul 2023 12:17:06 +0200 Subject: [PATCH] Log failed login attempts Closes #257 --- supysonic/api/__init__.py | 16 ++++++++++++---- supysonic/frontend/user.py | 6 +++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/supysonic/api/__init__.py b/supysonic/api/__init__.py index 4965d4c..fdeebf1 100644 --- a/supysonic/api/__init__.py +++ b/supysonic/api/__init__.py @@ -1,13 +1,14 @@ # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. # -# Copyright (C) 2013-2022 Alban 'spl0k' Féron +# Copyright (C) 2013-2023 Alban 'spl0k' Féron # # Distributed under terms of the GNU AGPLv3 license. API_VERSION = "1.12.0" import binascii +import logging import uuid from flask import request from flask import Blueprint @@ -20,6 +21,7 @@ from .exceptions import GenericError, Unauthorized, NotFound from .formatters import JSONFormatter, JSONPFormatter, XMLFormatter api = Blueprint("api", __name__) +logger = logging.getLogger(__name__) def api_routing(endpoint): @@ -57,12 +59,15 @@ def decode_password(password): @api.before_request def authorize(): if request.authorization: - user = UserManager.try_auth( - request.authorization.username, request.authorization.password - ) + username = request.authorization.username + user = UserManager.try_auth(username, request.authorization.password) if user is not None: request.user = user return + + logger.error( + "Failed login attempt for user %s (IP: %s)", username, request.remote_addr + ) raise Unauthorized() username = request.values["u"] @@ -71,6 +76,9 @@ def authorize(): user = UserManager.try_auth(username, password) if user is None: + logger.error( + "Failed login attempt for user %s (IP: %s)", username, request.remote_addr + ) raise Unauthorized() request.user = user diff --git a/supysonic/frontend/user.py b/supysonic/frontend/user.py index c69fe58..23db33f 100644 --- a/supysonic/frontend/user.py +++ b/supysonic/frontend/user.py @@ -1,7 +1,7 @@ # This file is part of Supysonic. # Supysonic is a Python implementation of the Subsonic server API. # -# Copyright (C) 2013-2022 Alban 'spl0k' Féron +# Copyright (C) 2013-2023 Alban 'spl0k' Féron # # Distributed under terms of the GNU AGPLv3 license. @@ -319,10 +319,14 @@ def login(): if not error: user = UserManager.try_auth(name, password) if user: + logger.info("Logged user %s (IP: %s)", name, request.remote_addr) session["userid"] = str(user.id) flash("Logged in!") return redirect(return_url) else: + logger.error( + "Failed login attempt for user %s (IP: %s)", name, request.remote_addr + ) flash("Wrong username or password") return render_template("login.html")