~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to twisted/test/test_cred.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-17 14:52:35 UTC
  • mfrom: (1.1.5 upstream) (2.1.2 etch)
  • Revision ID: james.westby@ubuntu.com-20070117145235-btmig6qfmqfen0om
Tags: 2.5.0-0ubuntu1
New upstream version, compatible with python2.5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
 
# See LICENSE for details.
4
 
 
5
 
 
6
 
"""
7
 
Tests for twisted.cred.
8
 
"""
9
 
 
10
 
import sys, warnings
11
 
from twisted.trial import unittest
12
 
from types import *
13
 
from twisted.internet import app
14
 
from twisted.cred import authorizer, identity, perspective, service, util
15
 
 
16
 
 
17
 
class ForeignObject:
18
 
    "A strange object which shouldn't rightly be accepted by anything."
19
 
 
20
 
    def __init__(self, s=None):
21
 
        self.desc = s
22
 
        self.__setattr__ = self.x__setattr__
23
 
 
24
 
    def x__setattr__(self, key, value):
25
 
        raise TypeError, "I am read-only."
26
 
 
27
 
    def __repr__(self):
28
 
        s = "<ForeignObject at %s: %s>" % (id(self), self.desc)
29
 
        return s
30
 
 
31
 
    def __str__(self):
32
 
        raise TypeError,\
33
 
              'I do not have a meaningful string representation'\
34
 
              'like "%s".' % (self.desc,)
35
 
 
36
 
    def __hash__(self):
37
 
        raise TypeError, "unhashable type"
38
 
 
39
 
 
40
 
# Service
41
 
AppForServiceTest = app.Application
42
 
 
43
 
class OldCredTestCase(unittest.TestCase):
44
 
    def setUpClass(self):
45
 
        warnings.filterwarnings('ignore', 'cred|authorizers|identities', DeprecationWarning)
46
 
 
47
 
    def tearDownClass(self):
48
 
        warnings.filterwarnings('default', 'cred|authorizers|identities', DeprecationWarning)
49
 
 
50
 
class ServiceTestCase(OldCredTestCase):
51
 
    App = AppForServiceTest
52
 
 
53
 
    def setUp(self):
54
 
        self.service = service.Service("test service", authorizer=authorizer.Authorizer())
55
 
 
56
 
    def testConstruction(self):
57
 
        appl = self.App("test app for service-test")
58
 
        auth = authorizer.Authorizer()
59
 
        parent = app.MultiService("test")
60
 
        service.Service("test service")
61
 
        service.Service("test service", authorizer=auth)
62
 
        service.Service("test service", parent)
63
 
 
64
 
    def testParent(self):
65
 
        parent = app.MultiService("test")
66
 
        auth = authorizer.Authorizer(parent)
67
 
        s = service.Service("test service", parent, authorizer=auth)
68
 
        self.assertEqual(s.authorizer.getServiceNamed(s.getServiceName()),
69
 
                         s)
70
 
        parent2 = app.MultiService("test")
71
 
        s.disownServiceParent()
72
 
        s.setServiceParent(parent2)
73
 
        self.assertEqual(s.authorizer.getServiceNamed(s.getServiceName()),
74
 
                         s)
75
 
 
76
 
 
77
 
    def testConstruction_serviceName(self):
78
 
        """serviceName is frequently used as a key, thus it is expected
79
 
        to be hashable."""
80
 
 
81
 
        self.assertRaises(TypeError, service.Service,
82
 
                          ForeignObject("Not a Name"))
83
 
 
84
 
    def testsetServiceParent(self):
85
 
        parent = app.MultiService("test")
86
 
        self.service.setServiceParent(parent)
87
 
        self.assert_(self.service.serviceParent is parent)
88
 
 
89
 
##    def testsetApplication_invalid(self):
90
 
##        "setApplication should not accept bogus argument."
91
 
 
92
 
##        self.assertRaises(TypeError, self.service.setApplication,
93
 
##                          ForeignObject("Not an Application"))
94
 
 
95
 
##    def testsetApplication_again(self):
96
 
##        "setApplication should bail if already set."
97
 
 
98
 
##        app1 = self.App("test app for service-test")
99
 
##        app2 = self.App("another app?")
100
 
##        self.service.setApplication(app1)
101
 
##        self.assertRaises(RuntimeError, self.service.setApplication,
102
 
##                          app2)
103
 
 
104
 
    def testgetPerspective(self):
105
 
        self.pname = pname = "perspective for service-test"
106
 
        self.p = p = perspective.Perspective(pname)
107
 
        self.service.addPerspective(p)
108
 
        d = self.service.getPerspectiveRequest(pname)
109
 
        d.addCallback(self._checkPerspective)
110
 
 
111
 
    def _checkPerspective(self, q):
112
 
        self.assertEquals(self.p, q)
113
 
        self.assertEquals(self.pname, q.getPerspectiveName())
114
 
        del self.p
115
 
        del self.pname
116
 
 
117
 
    def testGetSetPerspetiveSanity(self):
118
 
        # XXX OBSOLETE
119
 
        pname = "perspective for service-test"
120
 
        p = perspective.Perspective(pname)
121
 
        self.service.addPerspective(p)
122
 
        q = self.service.getPerspectiveNamed(pname)
123
 
        self.assertEqual(pname, q.getPerspectiveName())
124
 
        self.assertEqual(p,q)
125
 
 
126
 
    def testaddPerspective_invalid(self):
127
 
        self.assertRaises(TypeError, self.service.addPerspective,
128
 
                          ForeignObject("Not a Perspective"))
129
 
 
130
 
    def testgetPerspectiveNamed_invalid(self):
131
 
        # XXX OBSOLETE
132
 
        self.assertRaises(KeyError, self.service.getPerspectiveNamed,
133
 
                          "NoSuchPerspectiveNameAsThis")
134
 
 
135
 
    def testgetServiceName(self):
136
 
        self.assert_(self.service.getServiceName())
137
 
 
138
 
    def testgetServiceName_hashable(self):
139
 
        d = {}
140
 
        d[self.service.getServiceName()] = "value keyed to serviceName"
141
 
 
142
 
    def testgetServiceType(self):
143
 
        self.assert_(isinstance(self.service.getServiceType(),
144
 
                                StringType),
145
 
                     "ServiceType claimed to be a string, but isn't now.")
146
 
 
147
 
 
148
 
# Perspectives
149
 
 
150
 
AppForPerspectiveTest = app.Application
151
 
ServiceForPerspectiveTest = service.Service
152
 
IdentityForPerspectiveTest = identity.Identity
153
 
 
154
 
class PerspectiveTestCase(OldCredTestCase):
155
 
    App = AppForPerspectiveTest
156
 
    Service = ServiceForPerspectiveTest
157
 
    def Identity(self, n):
158
 
        return self.auth.createIdentity(n)
159
 
 
160
 
 
161
 
    def setUp(self):
162
 
        self.app = self.App("app for perspective-test")
163
 
        self.auth = authorizer.DefaultAuthorizer()
164
 
        self.service = self.Service("service for perspective-test",
165
 
                                    authorizer=self.auth)
166
 
        self.perspective = perspective.Perspective("test perspective")
167
 
        self.perspective.setService(self.service)
168
 
 
169
 
    def testConstruction(self):
170
 
        perspective.Perspective("test perspective")
171
 
        perspective.Perspective("test perspective", "testIdentityName")
172
 
 
173
 
    def testConstruction_invalidPerspectiveName(self):
174
 
        self.assertRaises(TypeError, perspective.Perspective,
175
 
                          ForeignObject("Not a perspectiveName"),
176
 
                          self.service)
177
 
 
178
 
    def testConstruction_invalidService(self):
179
 
        self.assertRaises(TypeError, perspective.Perspective,
180
 
                          "test perspective",
181
 
                          ForeignObject("Not a Service"))
182
 
 
183
 
    def testConstruction_invalidIdentityName(self):
184
 
        self.assertRaises(TypeError, perspective.Perspective,
185
 
                          "test perspective", self.service,
186
 
                          ForeignObject("Not an idenityName"))
187
 
 
188
 
    def testsetIdentityName(self):
189
 
        self.perspective.setIdentityName("saneIdentityName")
190
 
        self.assertEqual(self.perspective.identityName,
191
 
                         "saneIdentityName")
192
 
 
193
 
    def testsetIdentityName_invalid(self):
194
 
        self.assertRaises(TypeError,
195
 
                          self.perspective.setIdentityName,
196
 
                          ForeignObject("unusable identityName"))
197
 
 
198
 
    def testsetIdentity(self):
199
 
        i = self.Identity("id test name")
200
 
        self.perspective.setIdentity(i)
201
 
        self.assertEqual(self.perspective.identityName, "id test name")
202
 
 
203
 
    def test_identityWithNoPassword(self):
204
 
        i = self.Identity("id test name")
205
 
        i.setPassword("")
206
 
        pwrq = i.verifyPassword("foo", "bar")
207
 
        pwrq.addErrback(self._identityWithNoPassword_fail)
208
 
 
209
 
    def _identityWithNoPassword_fail(self, msg):
210
 
        # "Identity with no password did not authenticate."
211
 
        pass
212
 
 
213
 
    def test_identityWithNoPassword_plain(self):
214
 
        i = self.Identity("id test name")
215
 
        pwrq = i.verifyPlainPassword("foo")
216
 
        pwrq.addErrback(self._identityWithNoPassword_plain_fail)
217
 
 
218
 
    def _identityWithNoPassword_plain_fail(self, msg):
219
 
        # "Identity with no password did not authenticate (plaintext): %s"
220
 
        pass
221
 
 
222
 
    def testsetIdentity_invalid(self):
223
 
        self.assertRaises(TypeError,
224
 
                          self.perspective.setIdentity,
225
 
                          ForeignObject("not an Identity"))
226
 
 
227
 
    def testmakeIdentity(self):
228
 
        self.ident = ident = self.perspective.makeIdentity("password")
229
 
        # simple password verification
230
 
        pwrq = ident.verifyPlainPassword("password")
231
 
        pwrq.addCallbacks(self._testmakeIdentity_1, self._testmakeIdentity_1fail)
232
 
 
233
 
    def _testmakeIdentity_1fail(self, msg):
234
 
        try:
235
 
            self.fail("Identity did not verify with plain password: %s" % msg)
236
 
        except self.failureException, e:
237
 
            self.error = sys.exc_info()
238
 
            raise
239
 
 
240
 
    def _testmakeIdentity_1(self, msg):
241
 
        # complex password verification
242
 
        ident = self.ident
243
 
        challenge = ident.challenge()
244
 
        hashedPassword = util.respond(challenge, "password")
245
 
        pwrq = ident.verifyPassword(challenge, hashedPassword)
246
 
        pwrq.addCallback(self._testmakeIdentity_2)
247
 
        pwrq.addErrback(self._testmakeIdentity_2fail)
248
 
 
249
 
    def _testmakeIdentity_2fail(self, msg):
250
 
        try:
251
 
            self.fail("Identity did not verify with hashed password: %s" % msg)
252
 
        except self.failureException, e:
253
 
            self.error = sys.exc_info()
254
 
            raise
255
 
 
256
 
    def _testmakeIdentity_2(self, msg):
257
 
        d = self.perspective.getIdentityRequest()
258
 
        d.addCallback(self._gotIdentity)
259
 
 
260
 
    def _gotIdentity(self, ident):
261
 
        self.assertEquals(self.ident, ident)
262
 
        del self.ident
263
 
 
264
 
    def testmakeIdentity_invalid(self):
265
 
        self.assertRaises(TypeError, self.perspective.makeIdentity,
266
 
                          ForeignObject("Illegal Passkey"))
267
 
 
268
 
    def testgetService(self):
269
 
        s = self.perspective.getService()
270
 
        self.assert_(s is self.service)
271
 
 
272
 
class FunctionsTestCase(OldCredTestCase):
273
 
    def test_challenge(self):
274
 
        self.assert_(identity.challenge())
275
 
 
276
 
AppForIdentityTest = AppForPerspectiveTest
277
 
 
278
 
ServiceForIdentityTest = ServiceForPerspectiveTest
279
 
 
280
 
class PerspectiveForIdentityTest(perspective.Perspective):
281
 
    def __init__(self, n, service):
282
 
        perspective.Perspective.__init__(self, n)
283
 
        self.setService(service)
284
 
 
285
 
class IdentityTestCase(OldCredTestCase):
286
 
    App = AppForIdentityTest
287
 
    Service = ServiceForIdentityTest
288
 
    Perspective = PerspectiveForIdentityTest
289
 
 
290
 
    def setUp(self):
291
 
        self.auth = authorizer.DefaultAuthorizer()
292
 
        self.ident = identity.Identity("test identity", authorizer=self.auth)
293
 
 
294
 
    def testConstruction(self):
295
 
        identity.Identity("test name", authorizer=self.auth)
296
 
 
297
 
    def test_addKeyByString(self):
298
 
        self.ident.addKeyByString("one", "two")
299
 
        self.assert_(("one", "two") in self.ident.getAllKeys())
300
 
 
301
 
    def test_addKeyForPerspective(self):
302
 
        service = self.Service("one", authorizer=self.auth)
303
 
        perspective = self.Perspective("two", service)
304
 
 
305
 
        self.ident.addKeyForPerspective(perspective)
306
 
        self.assert_(("one", "two") in self.ident.getAllKeys())
307
 
 
308
 
    def test_getAllKeys(self):
309
 
        self.assert_(len(self.ident.getAllKeys()) == 0)
310
 
 
311
 
        service = self.Service("one", authorizer=self.auth)
312
 
 
313
 
        for n in ("p1","p2","p3"):
314
 
            perspective = self.Perspective(n, service)
315
 
            self.ident.addKeyForPerspective(perspective)
316
 
 
317
 
        keys = self.ident.getAllKeys()
318
 
 
319
 
        self.assertEqual(len(keys), 3)
320
 
 
321
 
        for n in ("p1","p2","p3"):
322
 
            self.assert_(("one", n) in keys)
323
 
 
324
 
    def test_removeKey(self):
325
 
        self.ident.addKeyByString("one", "two")
326
 
        self.ident.removeKey("one", "two")
327
 
        self.assert_(len(self.ident.getAllKeys()) == 0)
328
 
 
329
 
    def test_removeKey_invalid(self):
330
 
        self.assertRaises(KeyError, self.ident.removeKey,
331
 
                          "never","was")
332
 
 
333
 
    def test_setPassword_invalid(self):
334
 
        self.assertRaises(TypeError, self.ident.setPassword,
335
 
                          ForeignObject("not a valid passphrase"))
336
 
 
337
 
    def test_verifyPassword(self):
338
 
        self.ident.setPassword("passphrase")
339
 
 
340
 
        self._test_verifyPassword_worked = 0
341
 
        pwrq = self.ident.verifyPassword("wr", "ong")
342
 
        pwrq.addCallback(self._test_verifyPassword_false_pos)
343
 
        pwrq.addErrback(self._test_verifyPassword_correct_neg)
344
 
        # the following test actually needs the identity in testing
345
 
        # to have sync password checking..
346
 
        self.assert_(self._test_verifyPassword_worked)
347
 
 
348
 
    def _test_verifyPassword_false_pos(self, msg):
349
 
        self.fail("Identity accepted invalid hashed password")
350
 
 
351
 
    def _test_verifyPassword_correct_neg(self, msg):
352
 
        self.assert_(self._test_verifyPassword_worked==0)
353
 
        self._test_verifyPassword_worked = 1
354
 
 
355
 
    def test_verifyPlainPassword(self):
356
 
        self.ident.setPassword("passphrase")
357
 
 
358
 
        self._test_verifyPlainPassword_worked = 0
359
 
 
360
 
        pwrq1 = self.ident.verifyPlainPassword("passphrase")
361
 
        pwrq1.addErrback(self._test_verifyPlainPassword_fail)
362
 
        pwrq1.addCallback(self._test_verifyPlainPassword_ok)
363
 
        self.assert_(self._test_verifyPlainPassword_worked==1)
364
 
 
365
 
        pwrq2 = self.ident.verifyPlainPassword("wrongphrase")
366
 
        pwrq2.addCallback(self._test_verifyPlainPassword_false_pos)
367
 
        pwrq2.addErrback(self._test_verifyPlainPassword_correct_neg)
368
 
        self.assert_(self._test_verifyPlainPassword_worked==2)
369
 
 
370
 
    def _test_verifyPlainPassword_fail(self, msg):
371
 
        self.fail("Identity did not verify with plain password")
372
 
 
373
 
    def _test_verifyPlainPassword_ok(self, msg):
374
 
        self.assert_(self._test_verifyPlainPassword_worked==0)
375
 
        self._test_verifyPlainPassword_worked = 1
376
 
 
377
 
    def _test_verifyPlainPassword_false_pos(self, msg):
378
 
        self.fail("Identity accepted invalid plain password")
379
 
 
380
 
    def _test_verifyPlainPassword_correct_neg(self, msg):
381
 
        self.assert_(self._test_verifyPlainPassword_worked==1)
382
 
        self._test_verifyPlainPassword_worked = 2
383
 
 
384
 
 
385
 
 
386
 
class AuthorizerTestCase(OldCredTestCase):
387
 
    """TestCase for authorizer.DefaultAuthorizer."""
388
 
 
389
 
    def setUp(self):
390
 
        self.auth = authorizer.DefaultAuthorizer()
391
 
 
392
 
    def _error(self, e):
393
 
        raise RuntimeError, e
394
 
 
395
 
    def _gotIdentity(self, i):
396
 
        self.assertEquals(self.ident, i)
397
 
        del self.ident
398
 
 
399
 
    def test_addIdent(self):
400
 
        i = identity.Identity("user", self.auth)
401
 
 
402
 
        # add the identity
403
 
        self.auth.addIdentity(i)
404
 
        self.assertRaises(KeyError, self.auth.addIdentity, i)
405
 
        self.assert_(self.auth.identities.has_key("user"))
406
 
 
407
 
        # get request for identity
408
 
        self.ident = i
409
 
        d = self.auth.getIdentityRequest("user")
410
 
        d.addCallback(self._gotIdentity).addErrback(self._error)
411
 
 
412
 
        # remove identity
413
 
        self.auth.removeIdentity("user")
414
 
        self.assert_(not self.auth.identities.has_key("user"))
415
 
        self.assertRaises(KeyError, self.auth.removeIdentity, "user")
416
 
        self.assertRaises(KeyError, self.auth.removeIdentity, "otheruser")
417
 
 
418
 
    def _gotNoUser(self, err):
419
 
        pass
420
 
 
421
 
    def test_nonExistentIdent(self):
422
 
        d = self.auth.getIdentityRequest("nosuchuser")
423
 
        d.addCallback(self._error).addErrback(self._gotNoUser)