1
# Copyright (C) 2001-2003 by the Free Software Foundation, Inc.
3
# This program is free software; you can redistribute it and/or
4
# modify it under the terms of the GNU General Public License
5
# as published by the Free Software Foundation; either version 2
6
# of the License, or (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
"""Unit tests for Mailman/SecurityManager.py
30
# Don't use cStringIO because we're going to inherit
31
from StringIO import StringIO
33
from Mailman import mm_cfg
34
from Mailman import Utils
35
from Mailman import Errors
37
from TestBase import TestBase
41
def password(plaintext):
42
return sha.new(plaintext).hexdigest()
46
class TestSecurityManager(TestBase):
47
def test_init_vars(self):
49
eq(self._mlist.mod_password, None)
50
eq(self._mlist.passwords, {})
52
def test_auth_context_info_authuser(self):
54
self.assertRaises(TypeError, mlist.AuthContextInfo, mm_cfg.AuthUser)
56
mlist.addNewMember('aperson@dom.ain', password='xxXXxx')
58
mlist.AuthContextInfo(mm_cfg.AuthUser, 'aperson@dom.ain'),
59
('_xtest+user+aperson--at--dom.ain', 'xxXXxx'))
61
def test_auth_context_moderator(self):
63
mlist.mod_password = 'yyYYyy'
65
mlist.AuthContextInfo(mm_cfg.AuthListModerator),
66
('_xtest+moderator', 'yyYYyy'))
68
def test_auth_context_admin(self):
70
mlist.password = 'zzZZzz'
72
mlist.AuthContextInfo(mm_cfg.AuthListAdmin),
73
('_xtest+admin', 'zzZZzz'))
75
def test_auth_context_site(self):
77
mlist.password = 'aaAAaa'
79
mlist.AuthContextInfo(mm_cfg.AuthSiteAdmin),
80
('_xtest+admin', 'aaAAaa'))
82
def test_auth_context_huh(self):
84
self._mlist.AuthContextInfo('foo'),
89
class TestAuthenticate(TestBase):
92
Utils.set_global_password('bbBBbb', siteadmin=1)
93
Utils.set_global_password('ccCCcc', siteadmin=0)
97
os.unlink(mm_cfg.SITE_PW_FILE)
99
if e.errno <> errno.ENOENT: raise
101
os.unlink(mm_cfg.LISTCREATOR_PW_FILE)
103
if e.errno <> errno.ENOENT: raise
104
TestBase.tearDown(self)
106
def test_auth_creator(self):
107
self.assertEqual(self._mlist.Authenticate(
108
[mm_cfg.AuthCreator], 'ccCCcc'), mm_cfg.AuthCreator)
110
def test_auth_creator_unauth(self):
111
self.assertEqual(self._mlist.Authenticate(
112
[mm_cfg.AuthCreator], 'xxxxxx'), mm_cfg.UnAuthorized)
114
def test_auth_site_admin(self):
115
self.assertEqual(self._mlist.Authenticate(
116
[mm_cfg.AuthSiteAdmin], 'bbBBbb'), mm_cfg.AuthSiteAdmin)
118
def test_auth_site_admin_unauth(self):
119
self.assertEqual(self._mlist.Authenticate(
120
[mm_cfg.AuthSiteAdmin], 'xxxxxx'), mm_cfg.UnAuthorized)
122
def test_list_admin(self):
123
self._mlist.password = password('ttTTtt')
124
self.assertEqual(self._mlist.Authenticate(
125
[mm_cfg.AuthListAdmin], 'ttTTtt'), mm_cfg.AuthListAdmin)
127
def test_list_admin_unauth(self):
128
self._mlist.password = password('ttTTtt')
129
self.assertEqual(self._mlist.Authenticate(
130
[mm_cfg.AuthListAdmin], 'xxxxxx'), mm_cfg.UnAuthorized)
132
def test_list_admin_upgrade(self):
133
eq = self.assertEqual
135
mlist.password = md5.new('ssSSss').digest()
136
eq(mlist.Authenticate(
137
[mm_cfg.AuthListAdmin], 'ssSSss'), mm_cfg.AuthListAdmin)
138
eq(mlist.password, password('ssSSss'))
139
# Test crypt upgrades if crypt is supported
141
mlist.password = crypt.crypt('rrRRrr', 'zc')
142
eq(self._mlist.Authenticate(
143
[mm_cfg.AuthListAdmin], 'rrRRrr'), mm_cfg.AuthListAdmin)
144
eq(mlist.password, password('rrRRrr'))
146
def test_list_admin_oldstyle_unauth(self):
147
eq = self.assertEqual
149
mlist.password = md5.new('ssSSss').digest()
150
eq(mlist.Authenticate(
151
[mm_cfg.AuthListAdmin], 'xxxxxx'), mm_cfg.UnAuthorized)
152
eq(mlist.password, md5.new('ssSSss').digest())
153
# Test crypt upgrades if crypt is supported
155
mlist.password = crypted = crypt.crypt('rrRRrr', 'zc')
156
eq(self._mlist.Authenticate(
157
[mm_cfg.AuthListAdmin], 'xxxxxx'), mm_cfg.UnAuthorized)
158
eq(mlist.password, crypted)
160
def test_list_moderator(self):
161
self._mlist.mod_password = password('mmMMmm')
162
self.assertEqual(self._mlist.Authenticate(
163
[mm_cfg.AuthListModerator], 'mmMMmm'), mm_cfg.AuthListModerator)
167
mlist.addNewMember('aperson@dom.ain', password='nosrepa')
168
self.assertEqual(mlist.Authenticate(
169
[mm_cfg.AuthUser], 'nosrepa', 'aperson@dom.ain'), mm_cfg.AuthUser)
171
def test_wrong_user(self):
173
mlist.addNewMember('aperson@dom.ain', password='nosrepa')
174
self.assertRaises(Errors.NotAMemberError, mlist.Authenticate,
175
[mm_cfg.AuthUser], 'nosrepa', 'bperson@dom.ain')
177
def test_no_user(self):
179
mlist.addNewMember('aperson@dom.ain', password='nosrepa')
180
self.assertRaises(AttributeError, mlist.Authenticate,
181
[mm_cfg.AuthUser], 'nosrepa')
183
def test_user_unauth(self):
185
mlist.addNewMember('aperson@dom.ain', password='nosrepa')
186
self.assertEqual(mlist.Authenticate(
187
[mm_cfg.AuthUser], 'xxxxxx', 'aperson@dom.ain'),
190
def test_value_error(self):
191
self.assertRaises(ValueError, self._mlist.Authenticate,
192
['spooge'], 'xxxxxx', 'zperson@dom.ain')
196
class StripperIO(StringIO):
197
HEAD = 'Set-Cookie: '
199
if s.startswith(self.HEAD):
200
s = s[len(self.HEAD):]
201
StringIO.write(self, s)
204
class TestWebAuthenticate(TestBase):
207
Utils.set_global_password('bbBBbb', siteadmin=1)
208
Utils.set_global_password('ccCCcc', siteadmin=0)
210
mlist.mod_password = password('abcdefg')
211
mlist.addNewMember('aperson@dom.ain', password='qqQQqq')
212
# Set up the cookie data
214
print >> sfp, mlist.MakeCookie(mm_cfg.AuthSiteAdmin)
215
# AuthCreator isn't handled in AuthContextInfo()
216
print >> sfp, mlist.MakeCookie(mm_cfg.AuthListAdmin)
217
print >> sfp, mlist.MakeCookie(mm_cfg.AuthListModerator)
218
print >> sfp, mlist.MakeCookie(mm_cfg.AuthUser, 'aperson@dom.ain')
219
# Strip off the "Set-Cookie: " prefix
220
cookie = sfp.getvalue()
221
os.environ['HTTP_COOKIE'] = cookie
225
os.unlink(mm_cfg.SITE_PW_FILE)
227
if e.errno <> errno.ENOENT: raise
229
os.unlink(mm_cfg.LISTCREATOR_PW_FILE)
231
if e.errno <> errno.ENOENT: raise
232
del os.environ['HTTP_COOKIE']
233
TestBase.tearDown(self)
235
def test_auth_site_admin(self):
236
self.assertEqual(self._mlist.WebAuthenticate(
237
[mm_cfg.AuthSiteAdmin], 'xxxxxx'), 1)
239
def test_list_admin(self):
240
self.assertEqual(self._mlist.WebAuthenticate(
241
[mm_cfg.AuthListAdmin], 'xxxxxx'), 1)
243
def test_list_moderator(self):
244
self.assertEqual(self._mlist.WebAuthenticate(
245
[mm_cfg.AuthListModerator], 'xxxxxx'), 1)
248
self.assertEqual(self._mlist.WebAuthenticate(
249
[mm_cfg.AuthUser], 'xxxxxx'), 1)
251
def test_not_a_user(self):
252
self._mlist.removeMember('aperson@dom.ain')
253
self.assertEqual(self._mlist.WebAuthenticate(
254
[mm_cfg.AuthUser], 'xxxxxx', 'aperson@dom.ain'), 0)
258
# TBD: Tests for MakeCookie(), ZapCookie(), CheckCookie() -- although the
259
# latter is implicitly tested by testing WebAuthenticate() above.
264
suite = unittest.TestSuite()
265
suite.addTest(unittest.makeSuite(TestSecurityManager))
266
suite.addTest(unittest.makeSuite(TestAuthenticate))
267
suite.addTest(unittest.makeSuite(TestWebAuthenticate))
272
if __name__ == '__main__':
273
unittest.main(defaultTest='suite')