File: session.py

package info (click to toggle)
forgethtml 0.0.20031008-5
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 56 kB
  • ctags: 171
  • sloc: python: 492; makefile: 55
file content (138 lines) | stat: -rw-r--r-- 4,130 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""A server-side module for �sessions� in HTTP/HTTPS by
giving/getting a magic cookie from the browser, which
is simply a reference to a local data storage."""

# $Id: session.py,v 1.1 2003/01/18 05:29:16 stain Exp $
#
# Strongly inspired by PHP4's sessions.
# (c) Stian Soiland <stain@nvg.org> 2001
# Licence: LGPL
#
# Last changes:
# $Log: session.py,v $
# Revision 1.1  2003/01/18 05:29:16  stain
# First import from aapningstider.no
#
# Revision 1.1  2002/07/18 23:12:02  stain
# Akkai
#
# Revision 1.6  2002/04/08 01:58:54  stain
# I couldn't sleep and for some reason decided to change this module's
# ID-generation method. It's a bit easier then just lying in the dark
# thinking about girl problems.
#
#
# New method:
#
# Chooses 20 random characters from the readable part of the 7-bit ascii,
# ie, from chr(32) till chr(126) inclusive.
#
# This yields approximately 2**128 variations.  Actually it yields 95**20
# == 3584859224085422343574104404449462890625 ~= 2**131 variations.
#
# This of course is based on a 'perfect' random generator, which we don't
# have. Note that the basic idea is to have a ID that is hard to guess. If
# you have a system with 2**64 different sessions registered (unthinkable!
# Calculate the number!) - an attacker would need to do 2**64
#
# (??? Shouldn't this number be calculated in a bit trickier way?)
#
# connection attempts in order to retrieve an usable ID
# - and then he still wouldn't have any way to decide which ID to
#   retrieve.
#
#
# Other suggestions: (involves uglier programming)
#
# Calculate a number 2L**128 large by selecting four integers at random,
# putting them together by bitshifting 32, 64 and 96 bits and thereafter
# adding/and-ing them together.
#
# Then - use as a string. (you would probably need to do C-stuff to do
# this, bitshifting and adding letters with chr() would be STUPID), and
# THEN again, convert to base64.
#
# This method would use more processing power, look stupider and uglier,
# but would only use 4 random calls instead of 20. This could
#
#   a) Reduce total processing time if the randomizer is very CPU and/or
#      hardware intensive
#
#   b) Reduce possible patterns caused by imperfect random generators, and
#      thereby making the result 'more random'
#
# Revision 1.5  2001/04/10 00:11:08  stain
# Support for expiration (ie. sessions stored between browser
# instances)
#
# Revision 1.4  2001/04/06 19:36:38  stain
# Noe er endret.
#
# Revision 1.3  2001/03/13 23:45:07  stain
# N� virker den.
#
# 

# Todo:
#   + Maybe check that the session does not exist already


import Cookie,os,random,UserDict,pickle,time

class Session(UserDict.UserDict):
  def __init__(self, identifier=None, valid=None):
    """Initializes a new session or restores the old one.
    Identifier is used as the cookie name, and any integer
    in 'valid' is the number of seconds the cookie should
    be valid"""
    UserDict.UserDict.__init__(self)

    if(identifier):
      self.identifier = identifier
    else:
      try:
        self.identifier = os.environ['HTTP_HOST']
      except:
        self.identifier = "localhost"

    self.cookie = Cookie.SimpleCookie()
    try:
      self.cookie.load(os.environ['HTTP_COOKIE'])
      self.id = self.cookie[self.identifier].value
      self.data = pickle.load(open('/tmp/py_session_' +
                     self.identifier + '_' + self.id))
    except: # Any kind of error forces a new session!
      self.new_id()
      self.new_session()
    if(valid):
      self.cookie[self.identifier]['expires'] = valid
    print self.cookie.output()    

  def __del__(self):
    pickle.dump(self.data,
          open('/tmp/py_session_' + self.identifier +
             '_' + self.id, 'w'))

  def new_id(self):
    """Forces a new session id"""
    choices = range(32,127) # the normal 7-bits ascii letters
    key = ''
    for char in range(20): # 20 chars, aprox 2**128 bits resolution
      key = key + chr(random.choice(choices))
   
    self.id = key
    self.cookie[self.identifier] = self.id

  def new_session(self):
    """Forces a blank session (reuse ID)"""
    self.data = {}