Update of /cvsroot/tmda/tmda/contrib/cgi
In directory sc8-pr-cvs1:/tmp/cvs-serv20148
Modified Files:
Session.py
Log Message:
Major change:
Session.py now takes care of authenticating password forms and calling
seteuid/setegid.
Bugfix:
Importing order had to be re-arranged since effective user is not known when
the script begins execution.
CGI_SESSION_PREFIX defined in a constant now since Defaults is loaded AFTER the
value is needed.
REMOTE_ADDR is tested to prevent session hijacking.
Session now saves UID, GID, MiscUID, MiscGID, and HOME to keep from having to
look these variables up all the time.
Minor change:
Merged Clean() into Save() to minimize user changes.
Index: Session.py
===================================================================
RCS file: /cvsroot/tmda/tmda/contrib/cgi/Session.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Session.py 23 Nov 2002 06:16:05 -0000 1.1
+++ Session.py 25 Nov 2002 17:02:23 -0000 1.2
@@ -29,24 +29,31 @@
import re
import string
import time
-
-os.environ["HOME"] = pwd.getpwuid(os.geteuid())[5]
+import Authenticate
try:
- import paths
+ import paths
except ImportError:
- pass
-
-from TMDA import Defaults
+ pass
Rands = random.Random()
+# Constants
+CGI_SESSION_PREFIX = "/tmp/TMDASess."
+
class Session:
"""Sessioning tool for use in CGI.
-Resurrect an old session by passing a form with the session ID (SID) into the
+Resurrect an old session by passing a form with the session ID (SID) into the
constructor. An empty object will be created if the session has expired. A new
-session will be created if the form does not specify an SID.
+session will be created if the form does not specify a (valid) SID.
+
+Instantiating a session will check Form["user"] and Form["password"] if they
+exist to establish Session["UID"]. To check the validity of a session, test
+Session.has_key("UID") before any action that might reveal sensative
+information.
+
+Once a session is validated, the module will switch EUID to Session["UID"].
The session's SID is saved as member SID.
@@ -57,41 +64,81 @@
A.Save()
print "http://some/url?SID=%s" % A.SID
-The Save() member saves the session's current values on disk."""
+The Save() member saves the session's current values on disk, but can only be
+called once a validated session has been established. Writes are done as
+CGI_USER, as specified in Defaults."""
def __init__(self, Form):
"Reload an existing SID or create a new one."
+
+ global Defaults
- # Existing session?
- if Form.has_key("SID"):
+ # Existing, valid looking session?
+ if Form.has_key("SID") and \
+ re.compile("^[a-zA-Z0-9]{8}$").search(Form["SID"].value):
self.SID = Form["SID"].value
- # Valid looking session ID?
- if re.compile("^[a-zA-Z0-9]{8}$").search(self.SID):
- try:
- F = open(Defaults.CGI_SESSION_PREFIX + self.SID)
- self.Vars = pickle.load(F)
- F.close()
- self.Clean()
- return
- except:
- pass
- # Invalid ID
- else: raise ValueError
+ # Resurrect session
+ try:
+ F = open(CGI_SESSION_PREFIX + self.SID)
+ self.Vars = pickle.load(F)
+ F.close()
+ os.environ["HOME"] = self.Vars["HOME"]
+
+ # Now that we know who we are, get our defaults
+ from TMDA import Defaults
+
+ # Make sure the session has not been hijacked
+ if os.environ["REMOTE_ADDR"] == self.Vars["IP"]: return
+ except: # Failed to resurrect session, fall through to make new SID
+ pass
+
# New session
SessionChars = string.ascii_letters + string.digits
self.SID = ""
for i in range(8):
self.SID += SessionChars[Rands.randrange(len(SessionChars))]
self.Vars = {}
- self.Clean()
- def Clean(self):
- "This member is called automatically. You should not need to call it."
+ # Validate the new session?
+ try:
+ if Authenticate.CheckPassword(Form):
+ self.Vars["User"] = Form["user"].value
+ PasswordRecord = pwd.getpwnam(self.Vars["User"])
+ self.Vars["UID"] = PasswordRecord[2]
+ self.Vars["GID"] = PasswordRecord[3]
+ self.Vars["HOME"] = PasswordRecord[5]
+ os.environ["HOME"] = self.Vars["HOME"]
+ self.Vars["IP"] = os.environ["REMOTE_ADDR"]
+
+ # Now that we know who we are, get our defaults
+ from TMDA import Defaults
+
+ # Get misc user info
+ PasswordRecord = pwd.getpwnam(Defaults.CGI_USER)
+ self.Vars["MiscUID"] = PasswordRecord[2]
+ self.Vars["MiscGID"] = PasswordRecord[3]
+
+ self.Save() # Save session & set user
+ except:
+ return
+
+ def Save(self):
+ """Save all session variables to disk and change user. Possibly clean up
+old sessions."""
+ # Change to CGI_USER
+ try:
+ os.seteuid(self.Vars["MiscUID"])
+ os.setegid(self.Vars["MiscGID"])
+ except: pass
+ F = open(CGI_SESSION_PREFIX + self.SID, "w")
+ pickle.dump(self.Vars, F)
+ F.close()
+
# Clean up?
if Rands.random() < Defaults.CGI_CLEANUP_ODDS:
# Go through all sessions and check a-times
- Sessions = glob.glob(Defaults.CGI_SESSION_PREFIX + "*")
+ Sessions = glob.glob(CGI_SESSION_PREFIX + "*")
for Session in Sessions:
try: # these commands could fail if another thread cleans simultaneously
Stats = os.stat(Session)
@@ -99,12 +146,14 @@
if Stats[7] + Defaults.CGI_SESSION_EXP < time.time():
os.remove(Session)
except: pass
-
- def Save(self):
- "Save all session variables to disk."
- F = open(Defaults.CGI_SESSION_PREFIX + self.SID, "w")
- pickle.dump(self.Vars, F)
- F.close()
+
+ # Change back to regular user
+ try:
+ os.seteuid(0)
+ os.setegid(0)
+ os.setegid(self.Vars["GID"])
+ os.seteuid(self.Vars["UID"])
+ except: pass
def __contains__(self, a): return a in self.Vars
def countOf(self): return len(self.Vars)
_______________________________________
tmda-cvs mailing list
http://tmda.net/lists/listinfo/tmda-cvs