[checkmk-commits] Check_MK Git: check_mk: Restructured cookie auth cookies ( all auth cookies will be invalid

git version control git at mathias-kettner.de
Wed Nov 21 14:35:05 CET 2012


Module: check_mk
Branch: master
Commit: 0b575ddf14222bd6fae3389bebc099fc376289c4
URL:    http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=0b575ddf14222bd6fae3389bebc099fc376289c4

Author: Lars Michelsen <lm at mathias-kettner.de>
Date:   Tue Oct 30 13:35:25 2012 +0100

Restructured cookie auth cookies (all auth cookies will be invalid
after update -> all users have to login again)

---

 ChangeLog           |    2 ++
 web/htdocs/login.py |   29 ++++++++++++++++++-----------
 web/htdocs/wato.py  |   14 +++++++++++++-
 3 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2d7a325..83f7db0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,8 @@
     * Max. number of queued connections on status sockets is configurable now
 
     Multisite:
+    * Restructured cookie auth cookies (all auth cookies will be invalid
+      after update -> all users have to login again)
     * Enable automation login with _username= and _secret=, while
       _secret is the content of var/check_mk/web/$USER/automation.secret
     * FIX: Fixed releasing of locks and livestatus connections when logging out
diff --git a/web/htdocs/login.py b/web/htdocs/login.py
index 1ca86c4..4fc70fb 100644
--- a/web/htdocs/login.py
+++ b/web/htdocs/login.py
@@ -82,25 +82,32 @@ def load_secret():
 
     return secret
 
+# Load the password serial of the user. This serial identifies the current config
+# state of the user account. If either the password is changed or the account gets
+# locked the serial is increased by WATO and all cookies get invalidated.
+def load_serial(user_id):
+    users = wato.load_users()
+    return users.get(user_id, {}).get('serial', 0)
+
 # Generates the hash to be added into the cookie value
-def generate_hash(username, now, pwhash):
+def generate_hash(username, now, serial):
     secret = load_secret()
-    return md5.md5(username + now + pwhash + secret).hexdigest()
+    return md5.md5(username + now + str(serial) + secret).hexdigest()
 
 def del_auth_cookie():
     name = site_cookie_name()
     if html.has_cookie(name):
         html.del_cookie(name)
 
-def auth_cookie_value(username, pwhash):
+def auth_cookie_value(username, serial):
     now = str(time.time())
-    return username + ':' + now + ':' + generate_hash(username, now, pwhash)
+    return username + ':' + now + ':' + generate_hash(username, now, serial)
 
-def set_auth_cookie(username, pwhash):
-    html.set_cookie(site_cookie_name(), auth_cookie_value(username, pwhash))
+def set_auth_cookie(username, serial):
+    html.set_cookie(site_cookie_name(), auth_cookie_value(username, serial))
 
 def get_cookie_value():
-    return auth_cookie_value(config.user_id, load_htpasswd()[config.user_id])
+    return auth_cookie_value(config.user_id, load_serial(config.user_id))
 
 def check_auth_cookie(cookie_name):
     username, issue_time, cookie_hash = html.cookie(cookie_name, '::').split(':', 2)
@@ -114,10 +121,10 @@ def check_auth_cookie(cookie_name):
     users = load_htpasswd()
     if not username in users:
         raise MKAuthException(_('Username is unknown'))
-    pwhash = users[username]
 
     # Validate the hash
-    if cookie_hash != generate_hash(username, issue_time, pwhash):
+    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!
@@ -126,7 +133,7 @@ def check_auth_cookie(cookie_name):
     # b) A logout is requested
     if (html.req.myfile != 'logout' or html.has_var('_ajaxid')) \
        and cookie_name == site_cookie_name():
-        set_auth_cookie(username, pwhash)
+        set_auth_cookie(username, serial)
 
     # Return the authenticated username
     return username
@@ -181,7 +188,7 @@ def do_login():
                 # a) Set the auth cookie
                 # b) Unset the login vars in further processing
                 # c) Show the real requested page (No redirect needed)
-                set_auth_cookie(username, users[username])
+                set_auth_cookie(username, load_serial(username))
 
                 # Use redirects for URLs or simply execute other handlers for
                 # mulitsite modules
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index b1b9dba..0a255a5 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -7805,13 +7805,19 @@ def mode_edit_user(phase):
             if password:
                 new_user["password"] = encrypt_password(password)
 
+        # Set initial password serial or increase existing
+        if new:
+            new_user["serial"] = 0
+        else:
+            new_user["serial"] += 1
+
         # Email address
         email = html.var("email").strip()
         regex_email = '^[-a-zäöüÄÖÜA-Z0-9_.]+@[-a-zäöüÄÖÜA-Z0-9]+(\.[a-zA-Z]+)*$'
         if email and not re.match(regex_email, email):
             raise MKUserError("email", _("'%s' is not a valid email address." % email))
         new_user["email"] = email
-        
+
         # Pager
         pager = html.var("pager").strip()
         new_user["pager"] = pager
@@ -10875,6 +10881,12 @@ def page_user_profile():
 
                     users[config.user_id]['password'] = encrypt_password(password)
 
+                    # Increase serial to invalidate old cookies
+                    if 'serial' not in users[config.user_id]:
+                        users[config.user_id]['serial'] = 1
+                    else:
+                        users[config.user_id]['serial'] += 1
+
             save_users(users)
             success = True
 



More information about the checkmk-commits mailing list