From nobody Tue Apr 23 10:15:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of ovirt.org designates 66.187.230.42 as permitted sender) client-ip=66.187.230.42; envelope-from=kimchi-devel-bounces@ovirt.org; helo=lists.ovirt.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of ovirt.org designates 66.187.230.42 as permitted sender) smtp.mailfrom=kimchi-devel-bounces@ovirt.org; Return-Path: Received: from lists.ovirt.org (lists.phx.ovirt.org [66.187.230.42]) by mx.zohomail.com with SMTPS id 1486154090463445.75773617253367; Fri, 3 Feb 2017 12:34:50 -0800 (PST) Received: from lists.phx.ovirt.org (localhost [127.0.0.1]) by lists.ovirt.org (Postfix) with ESMTP id B302E820533; Fri, 3 Feb 2017 20:34:47 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lists.ovirt.org (Postfix) with ESMTPS id A3E0A8204CC for ; Fri, 3 Feb 2017 20:34:33 +0000 (UTC) Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v13KXo7T056254 for ; Fri, 3 Feb 2017 15:34:33 -0500 Received: from e24smtp04.br.ibm.com (e24smtp04.br.ibm.com [32.104.18.25]) by mx0a-001b2d01.pphosted.com with ESMTP id 28cyk3js0m-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Fri, 03 Feb 2017 15:34:32 -0500 Received: from localhost by e24smtp04.br.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 3 Feb 2017 18:34:30 -0200 Received: from d24dlp02.br.ibm.com (9.18.248.206) by e24smtp04.br.ibm.com (10.172.0.140) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 3 Feb 2017 18:34:27 -0200 Received: from d24relay03.br.ibm.com (d24relay03.br.ibm.com [9.18.232.225]) by d24dlp02.br.ibm.com (Postfix) with ESMTP id C29091DC0054 for ; Fri, 3 Feb 2017 15:34:27 -0500 (EST) Received: from d24av01.br.ibm.com (d24av01.br.ibm.com [9.8.31.91]) by d24relay03.br.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v13KYQk235520660 for ; Fri, 3 Feb 2017 18:34:26 -0200 Received: from d24av01.br.ibm.com (localhost [127.0.0.1]) by d24av01.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v13KYQgB012627 for ; Fri, 3 Feb 2017 18:34:26 -0200 Received: from localhost.localdomain ([9.85.129.92]) by d24av01.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v13KYNFG012569 for ; Fri, 3 Feb 2017 18:34:24 -0200 X-Original-To: kimchi-devel@ovirt.org From: ramonn@linux.vnet.ibm.com To: Kimchi Devel Date: Fri, 3 Feb 2017 18:34:15 -0200 X-Mailer: git-send-email 2.10.1 (Apple Git-78) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17020320-0028-0000-0000-000001921D31 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17020320-0029-0000-0000-0000148E496B Message-Id: <20170203203415.30625-1-ramonn@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-02-03_13:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1702030192 Subject: [Kimchi-devel] [PATCH v6] [Wok] Bug fix #147: Block authentication request after too many failures X-BeenThere: kimchi-devel@ovirt.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: kimchi-devel-bounces@ovirt.org Errors-To: kimchi-devel-bounces@ovirt.org X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Ramon Medeiros To prevent brute force attack, creates a mechanism to allow 3 tries first. After that, a timeout will start and will be added 30 seconds for each failed try in a row. Signed-off-by: Ramon Medeiros --- Changes: v6: Change message v5: Friendly error message Set maximum tries to 3 v4: Use API.json for input validation v3: Improve error handling on login page v2: Set timeout by user, ip and session id. This will avoid trouble with users using the same ip, like NAT. src/wok/API.json | 25 +++++++++++++++++- src/wok/i18n.py | 6 ++++- src/wok/root.py | 69 +++++++++++++++++++++++++++++++++++++++++---= ---- ui/js/src/wok.login.js | 19 ++++++++----- ui/pages/i18n.json.tmpl | 5 +++- ui/pages/login.html.tmpl | 6 ++--- 6 files changed, 107 insertions(+), 23 deletions(-) diff --git a/src/wok/API.json b/src/wok/API.json index 8965db9..3f7bfd7 100644 --- a/src/wok/API.json +++ b/src/wok/API.json @@ -2,5 +2,28 @@ "$schema": "http://json-schema.org/draft-03/schema#", "title": "Wok API", "description": "Json schema for Wok API", - "type": "object" + "type": "object", + "properties": { + "wokroot_login": { + "type": "object", + "properties": { + "username": { + "description": "Username", + "required": true, + "type": "string", + "minLength": 1, + "error": "WOKAUTH0003E" + }, + "password": { + "description": "Password", + "required": true, + "type": "string", + "minLength": 1, + "error": "WOKAUTH0006E" + } + }, + "additionalProperties": false, + "error": "WOKAUTH0007E" + } + } } diff --git a/src/wok/i18n.py b/src/wok/i18n.py index 935c9c1..4a21d43 100644 --- a/src/wok/i18n.py +++ b/src/wok/i18n.py @@ -40,8 +40,12 @@ messages =3D { =20 "WOKAUTH0001E": _("Authentication failed for user '%(username)s'. [Err= or code: %(code)s]"), "WOKAUTH0002E": _("You are not authorized to access Wok. Please, login= first."), - "WOKAUTH0003E": _("Specify %(item)s to login into Wok."), + "WOKAUTH0003E": _("Specify username to login into Wok."), + "WOKAUTH0004E": _("You have failed to login in too much attempts. Plea= se, wait for %(seconds)s seconds to try again."), "WOKAUTH0005E": _("Invalid LDAP configuration: %(item)s : %(value)s"), + "WOKAUTH0006E": _("Specify password to login into Wok."), + "WOKAUTH0007E": _("You need to specify username and password to login = into Wok."), + "WOKAUTH0008E": _("The username or password you entered is incorrect. = Please try again"), =20 "WOKLOG0001E": _("Invalid filter parameter. Filter parameters allowed:= %(filters)s"), "WOKLOG0002E": _("Creation of log file failed: %(err)s"), diff --git a/src/wok/root.py b/src/wok/root.py index 080b7f0..f813ed2 100644 --- a/src/wok/root.py +++ b/src/wok/root.py @@ -1,7 +1,7 @@ # # Project Wok # -# Copyright IBM Corp, 2015-2016 +# Copyright IBM Corp, 2015-2017 # # Code derived from Project Kimchi # @@ -21,7 +21,9 @@ =20 import cherrypy import json +import re import os +import time from distutils.version import LooseVersion =20 from wok import auth @@ -30,8 +32,8 @@ from wok.i18n import messages from wok.config import paths as wok_paths from wok.control import sub_nodes from wok.control.base import Resource -from wok.control.utils import parse_request -from wok.exception import MissingParameter +from wok.control.utils import parse_request, validate_params +from wok.exception import OperationFailed, UnauthorizedError, WokException from wok.reqlogger import log_request =20 =20 @@ -48,7 +50,8 @@ class Root(Resource): super(Root, self).__init__(model) self._handled_error =3D ['error_page.400', 'error_page.404', 'error_page.405', 'error_page.406', - 'error_page.415', 'error_page.500'] + 'error_page.415', 'error_page.500', + 'error_page.403', 'error_page.401'] =20 if not dev_env: self._cp_config =3D dict([(key, self.error_production_handler) @@ -146,6 +149,7 @@ class WokRoot(Root): self.domain =3D 'wok' self.messages =3D messages self.extends =3D None + self.failed_logins =3D {} =20 # set user log messages and make sure all parameters are present self.log_map =3D ROOT_REQUESTS @@ -153,24 +157,71 @@ class WokRoot(Root): =20 @cherrypy.expose def login(self, *args): + def _raise_timeout(user_id): + length =3D self.failed_logins[user_ip_sid]["count"] + timeout =3D (length - 2) * 30 + details =3D e =3D UnauthorizedError("WOKAUTH0004E", + {"seconds": timeout}) + log_request(code, params, details, method, 403) + raise cherrypy.HTTPError(403, e.message) details =3D None method =3D 'POST' code =3D self.getRequestMessage(method, 'login') =20 try: params =3D parse_request() + validate_params(params, self, "login") username =3D params['username'] password =3D params['password'] - except KeyError, item: - details =3D e =3D MissingParameter('WOKAUTH0003E', {'item': st= r(item)}) - log_request(code, params, details, method, 400) - raise cherrypy.HTTPError(400, e.message) + except WokException, e: + details =3D e =3D OperationFailed("WOKAUTH0008E") + status =3D e.getHttpStatusCode() + raise cherrypy.HTTPError(401, e.message) + + # get authentication info + remote_ip =3D cherrypy.request.remote.ip + session_id =3D str(cherrypy.session.originalid) + user_ip_sid =3D re.escape(username + remote_ip + session_id) + + # check for repetly + count =3D self.failed_logins.get(user_ip_sid, {"count": 0}).get("c= ount") + if count >=3D 3: + + # verify if timeout is still valid + last_try =3D self.failed_logins[user_ip_sid]["time"] + if time.time() < (last_try + ((count - 2) * 30)): + _raise_timeout(user_ip_sid) + else: + self.failed_logins.pop(user_ip_sid) =20 try: status =3D 200 user_info =3D auth.login(username, password) + + # user logged sucessfuly: reset counters + if self.failed_logins.get(user_ip_sid) !=3D None: + self.failed_logins.pop(user_ip_sid) except cherrypy.HTTPError, e: - status =3D e.status + + # store time and prevent too much tries + if self.failed_logins.get(user_ip_sid) =3D=3D None: + self.failed_logins[user_ip_sid] =3D {"time": time.time(), + "ip": remote_ip, + "session_id": session_i= d, + "username": username, + "count": 1} + else: + # tries take more than 30 seconds between each one: do not + # increase count + if (time.time() - + self.failed_logins[user_ip_sid]["time"]) < 30: + + self.failed_logins[user_ip_sid]["time"] =3D time.time() + self.failed_logins[user_ip_sid]["count"] +=3D 1 + + # more than 3 fails: raise error + if self.failed_logins[user_ip_sid]["count"] >=3D 3: + _raise_timeout(user_ip_sid) raise finally: log_request(code, params, details, method, status) diff --git a/ui/js/src/wok.login.js b/ui/js/src/wok.login.js index 666a339..9e2a392 100644 --- a/ui/js/src/wok.login.js +++ b/ui/js/src/wok.login.js @@ -19,6 +19,10 @@ */ wok.login_main =3D function() { "use strict"; + var i18n; + wok.getI18n(function(i18nObj){ + i18n =3D i18nObj; + }, false, "i18n.json", true); =20 // verify if language is available var selectedLanguage =3D wok.lang.get(); @@ -50,7 +54,8 @@ wok.login_main =3D function() { var query =3D window.location.search; var error =3D /.*error=3D(.*?)(&|$)/g.exec(query); if (error && error[1] =3D=3D=3D "sessionTimeout") { - $("#messSession").show(); + $("#errorArea").html(i18n["WOKAUT0001E"]); + $("#errorArea").show(); } =20 var userNameBox =3D $('#username'); @@ -82,13 +87,13 @@ wok.login_main =3D function() { window.location.replace(window.location.pathname.replace(/\/+l= ogin.html/, '') + next_url); }, function(jqXHR, textStatus, errorThrown) { if (jqXHR.responseText =3D=3D "") { - $("#messUserPass").hide(); - $("#missServer").show(); - } else { - $("#missServer").hide(); - $("#messUserPass").show(); + $("#errorArea").html(i18n["WOKAUT0002E"]); + $("#errorArea").show(); + } else if ((jqXHR.responseJSON !=3D undefined) && + ! (jqXHR.responseJSON["reason"] =3D=3D undefined)) { + $("#errorArea").html(jqXHR.responseJSON["reason"]); + $("#errorArea").show(); } - $("#messSession").hide(); $("#logging").hide(); $("#login").show(); }); diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl index ba29532..4329ad0 100644 --- a/ui/pages/i18n.json.tmpl +++ b/ui/pages/i18n.json.tmpl @@ -1,7 +1,7 @@ #* * Project Wok * - * Copyright IBM Corp, 2014-2016 + * Copyright IBM Corp, 2014-2017 * * Code derived from Project Kimchi * @@ -39,6 +39,9 @@ =20 "WOKHOST6001M": "$_("Max:")", =20 + "WOKAUT0001E": "$_("Session timeout, please re-login.")", + "WOKAUT0002E": "$_("Server unreachable")", + "WOKSETT0001M": "$_("Application")", "WOKSETT0002M": "$_("User")", "WOKSETT0003M": "$_("Request")", diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl index f5a4b2d..6f967cf 100644 --- a/ui/pages/login.html.tmpl +++ b/ui/pages/login.html.tmpl @@ -1,7 +1,7 @@ #* * Project Wok * - * Copyright IBM Corp, 2014-2016 + * Copyright IBM Corp, 2014-2017 * * Code derived from Project Kimchi * @@ -104,9 +104,7 @@
-
$_("The username or password you entered is incorr= ect. Please try again.")
-
$_("Session timeout, please re-login.")
-
$_("Server unreachable.")
+
--=20 2.10.1 (Apple Git-78) _______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel