summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhmeland1999-06-11 14:29:54 +0000
committerhmeland1999-06-11 14:29:54 +0000
commit9286ef4c5f1c9689dcd72f9731fdbdf8edb8546e (patch)
tree1c24c793b53cab0f3e3c685ecb21209bb7ba08cd
parent4b2a899ffd6325fb1eb223ad6633ce0f4ca2cd08 (diff)
downloadmailman-9286ef4c5f1c9689dcd72f9731fdbdf8edb8546e.tar.gz
mailman-9286ef4c5f1c9689dcd72f9731fdbdf8edb8546e.tar.zst
mailman-9286ef4c5f1c9689dcd72f9731fdbdf8edb8546e.zip
Changes to fix the CGI cookie security flaw reported by John Morton.
SecurityManager: New functions MakeCookie() and CheckCookie(). These functions work with cookies containing cookie creation and expire time, the client's IP number, and a checksum hash of these values as well as a secret (the lists (encrypted) admin password). admin.py, admindb.py and private.py: isAuthenticated now uses these new cookie functions.
Diffstat (limited to '')
-rw-r--r--Mailman/Cgi/admin.py4
-rw-r--r--Mailman/Cgi/admindb.py4
-rw-r--r--Mailman/Cgi/private.py17
-rw-r--r--Mailman/SecurityManager.py27
4 files changed, 38 insertions, 14 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py
index 9e875d1f0..73a7b2cd9 100644
--- a/Mailman/Cgi/admin.py
+++ b/Mailman/Cgi/admin.py
@@ -50,7 +50,7 @@ def isAuthenticated(list, password=None, SECRET="SECRET"):
AddErrorMessage(doc, 'Error: Incorrect admin password.')
return 0
- token = `hash(list_name)`
+ token = list.MakeCookie()
c = Cookie.Cookie()
cookie_key = list_name + "-admin"
c[cookie_key] = token
@@ -60,7 +60,7 @@ def isAuthenticated(list, password=None, SECRET="SECRET"):
if os.environ.has_key('HTTP_COOKIE'):
c = Cookie.Cookie( os.environ['HTTP_COOKIE'] )
if c.has_key(list_name + "-admin"):
- if c[list_name + "-admin"].value == `hash(list_name)`:
+ if list.CheckCookie(c[list_name + "-admin"].value):
return 1
else:
AddErrorMessage(doc, "error decoding authorization cookie")
diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py
index 3f3e20a2e..0f76c032c 100644
--- a/Mailman/Cgi/admindb.py
+++ b/Mailman/Cgi/admindb.py
@@ -34,7 +34,7 @@ def isAuthenticated(mlist, password=None, SECRET="SECRET"):
AddErrorMessage(doc, 'Error: Incorrect admin password.')
return 0
- token = `hash(list_name)`
+ token = list.MakeCookie()
c = Cookie.Cookie()
cookie_key = list_name + "-admin"
c[cookie_key] = token
@@ -44,7 +44,7 @@ def isAuthenticated(mlist, password=None, SECRET="SECRET"):
if os.environ.has_key('HTTP_COOKIE'):
c = Cookie.Cookie( os.environ['HTTP_COOKIE'] )
if c.has_key(list_name + "-admin"):
- if c[list_name + "-admin"].value == `hash(list_name)`:
+ if list.CheckCookie(c[list_name + "-admin"].value):
return 1
else:
AddErrorMessage(doc, "error decoding authorization cookie")
diff --git a/Mailman/Cgi/private.py b/Mailman/Cgi/private.py
index 0fbdcede0..e46879371 100644
--- a/Mailman/Cgi/private.py
+++ b/Mailman/Cgi/private.py
@@ -32,9 +32,6 @@ import Mailman.mm_cfg
LogStdErr("error", "private")
-
-SECRET = "secret" # XXX used for hashing
-
PAGE = '''
<html>
<head>
@@ -82,10 +79,15 @@ def GetListobj(list_name):
return _list
def isAuthenticated(list_name):
+ try:
+ listobj = GetListobj(list_name)
+ except Errors.MMUnknownListError:
+ print "\n<H3>List", repr(list_name), "not found.</h3>"
+ raise SystemExit
if os.environ.has_key('HTTP_COOKIE'):
c = Cookie.Cookie( os.environ['HTTP_COOKIE'] )
if c.has_key(list_name):
- if c[list_name].value == `hash(list_name)`:
+ if listobj.CheckCookie(c[list_name].value):
return 1
# No corresponding cookie. OK, then check for username, password
# CGI variables
@@ -108,17 +110,12 @@ def isAuthenticated(list_name):
global login_attempted
login_attempted=1
try:
- listobj = GetListobj(list_name)
- except Errors.MMUnknownListError:
- print "\n<H3>List", repr(list_name), "not found.</h3>"
- raise SystemExit
- try:
listobj.ConfirmUserPassword( username, password)
except (Errors.MMBadUserError, Errors.MMBadPasswordError,
Errors.MMNotAMemberError):
return 0
- token = `hash(list_name)`
+ token = listobj.MakeCookie()
c = Cookie.Cookie()
c[list_name] = token
print c # Output the cookie
diff --git a/Mailman/SecurityManager.py b/Mailman/SecurityManager.py
index 6a5d0f0a8..d60a93179 100644
--- a/Mailman/SecurityManager.py
+++ b/Mailman/SecurityManager.py
@@ -20,6 +20,7 @@
import os
import string
+import time
import types
import Crypt
import Errors
@@ -67,6 +68,32 @@ class SecurityManager:
raise Errors.MMBadPasswordError
return 1
+ def MakeCookie(self):
+ client_ip = os.environ.get('REMOTE_ADDR') or '0.0.0.0'
+ issued = int(time.time())
+ expires = issued + mm_cfg.ADMIN_COOKIE_LIFE
+ secret = self.password
+ mac = hash(secret + client_ip + `issued` + `expires`)
+ return [client_ip, issued, expires, mac]
+
+ def CheckCookie(self, cookie):
+ if type(cookie) <> type([]):
+ return 0
+ if len(cookie) <> 4:
+ return 0
+ client_ip = os.environ.get('REMOTE_ADDR') or '0.0.0.0'
+ [for_ip, issued, expires, received_mac] = cookie
+ if for_ip <> client_ip:
+ return 0
+ now = time.time()
+ if not issued < now < expires:
+ return 0
+ secret = self.password
+ mac = hash(secret + client_ip + `issued` + `expires`)
+ if mac <> received_mac:
+ return 0
+ return 1
+
def ConfirmUserPassword(self, user, pw):
"""True if password is valid for site, list admin, or specific user."""
if self.ValidAdminPassword(pw):