Module: check_mk
Branch: master
Commit: f5d8f70e0eb84c4e813fbbabce7b1c383d5aadef
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f5d8f70e0eb84c…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Sun Feb 7 22:35:17 2016 +0100
#3171 FIX Logout in one site will log out of all sites sharing the same auth.secret
Site that share the file <tt>etc/auth.secret</tt> also share the same login.
A user logging in in one of these sites is automatically logged in in all
others. But logging out did only work when the logout was done on the same
site as the login. Now you can log in at one site and log out at the other.
Note: Also <tt>omd cp</tt> creates sites with the same secret.
---
.bugs/2389 | 7 +++++--
.werks/3171 | 13 +++++++++++++
ChangeLog | 1 +
web/htdocs/login.py | 54 +++++++++++++++++++++++++++++++++++----------------
4 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/.bugs/2389 b/.bugs/2389
index f57e5ed..f8093a3 100644
--- a/.bugs/2389
+++ b/.bugs/2389
@@ -1,10 +1,13 @@
Title: Logout problem after site copy
Component: multisite
-State: open
+Class: bug
+State: done
Date: 2015-10-14 14:56:27
Targetversion: 1.2.8
-Class: bug
If one monitoring sites is copied with omd cp, the logout will not work.
After the successful login in one of the sites you can use the other one.
If you do a logout in one sites you are automatically logged in again.
+
+2016-02-07 22:32:51: changed state open -> done
+We now delete all cookies that provide a valid login to our site.
diff --git a/.werks/3171 b/.werks/3171
new file mode 100644
index 0000000..f92ae4c
--- /dev/null
+++ b/.werks/3171
@@ -0,0 +1,13 @@
+Title: Logout in one site will log out of all sites sharing the same auth.secret
+Level: 1
+Component: multisite
+Compatible: compat
+Version: 1.2.7i4
+Date: 1454880775
+Class: fix
+
+Site that share the file <tt>etc/auth.secret</tt> also share the same login.
+A user logging in in one of these sites is automatically logged in in all
+others. But logging out did only work when the logout was done on the same
+site as the login. Now you can log in at one site and log out at the other.
+Note: Also <tt>omd cp</tt> creates sites with the same secret.
diff --git a/ChangeLog b/ChangeLog
index ea88bf5..9cb7829 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -309,6 +309,7 @@
* 3041 FIX: Fixed deselecting view checkbox options like "Always show
checkboxes" in dashboard embedded views
* 3046 FIX: Acknowledging all incompatible werks when creating new sites
* 2931 FIX: Do not load bookmarks, reports, view, etc. of non-existing users anymore
+ * 3171 FIX: Logout in one site will log out of all sites sharing the same
auth.secret...
WATO:
* 2442 WATO remove host: improved cleanup of obsolete host files...
diff --git a/web/htdocs/login.py b/web/htdocs/login.py
index 94d4da1..658a3ef 100644
--- a/web/htdocs/login.py
+++ b/web/htdocs/login.py
@@ -81,10 +81,17 @@ def generate_hash(username, now, serial):
secret = load_secret()
return md5(username.encode("utf-8") + now + str(serial) +
secret).hexdigest()
+
def del_auth_cookie():
- name = site_cookie_name()
- if html.has_cookie(name):
- html.del_cookie(name)
+ # Note: in distributed setups a cookie issued by one site is accepted by
+ # others with the same auth.secret and user serial numbers. When a users
+ # logs out then we need to delete all cookies that are accepted by us -
+ # not just the one that we have issued.
+ for cookie_name in html.get_cookie_names():
+ if cookie_name.startswith("auth_"):
+ if auth_cookie_is_valid(cookie_name):
+ html.del_cookie(cookie_name)
+
def auth_cookie_value(username, serial):
now = str(time.time())
@@ -101,34 +108,47 @@ def renew_cookie(cookie_name, username, serial):
and cookie_name == site_cookie_name():
set_auth_cookie(username, serial)
+
def check_auth_cookie(cookie_name):
+ username, issue_time, cookie_hash = parse_auth_cookie(cookie_name)
+ serial = check_parsed_auth_cookie(username, issue_time, cookie_hash)
+
+ # Once reached this the cookie is a good one. Renew it!
+ renew_cookie(cookie_name, username, serial)
+
+ if html.myfile != 'user_change_pw':
+ result = userdb.need_to_change_pw(username)
+ if result:
+ html.http_redirect('user_change_pw.py?_origtarget=%s&reason=%s' %
(html.urlencode(html.makeuri([])), result))
+
+ # Return the authenticated username
+ return username
+
+
+def parse_auth_cookie(cookie_name):
username, issue_time, cookie_hash = html.cookie(cookie_name,
'::').split(':', 2)
username = username.decode("utf-8")
+ return username, issue_time, cookie_hash
- # FIXME: Ablauf-Zeit des Cookies testen
- #max_cookie_age = 10
- #if float(issue_time) < time.time() - max_cookie_age:
- # del_auth_cookie()
- # return ''
+def check_parsed_auth_cookie(username, issue_time, cookie_hash):
if not userdb.user_exists(username):
raise MKAuthException(_('Username is unknown'))
- # Validate the hash
serial = load_serial(username)
if cookie_hash != generate_hash(username, issue_time, serial):
raise MKAuthException(_('Invalid credentials'))
- # Once reached this the cookie is a good one. Renew it!
- renew_cookie(cookie_name, username, serial)
+ return serial
- if html.myfile != 'user_change_pw':
- result = userdb.need_to_change_pw(username)
- if result:
- html.http_redirect('user_change_pw.py?_origtarget=%s&reason=%s' %
(html.urlencode(html.makeuri([])), result))
- # Return the authenticated username
- return username
+def auth_cookie_is_valid(cookie_name):
+ try:
+ check_parsed_auth_cookie(*parse_auth_cookie(cookie_name))
+ return True
+ except MKAuthException:
+ return False
+
def check_auth_automation():
secret = html.var("_secret").strip()