Skip to content

Commit 7ad43f2

Browse files
author
Ben Weaver
committed
Add custom logger, update unit tests.
1 parent 4f72d24 commit 7ad43f2

File tree

6 files changed

+40
-31
lines changed

6 files changed

+40
-31
lines changed

sasl/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from __future__ import absolute_import
2+
from .prelude import *
23
from .mechanism import *
34
from .auth import *
45
from .plain import *

sasl/digest_md5.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88

99
from __future__ import absolute_import
1010
import re, functools, random, struct, base64, hashlib, binascii
11-
import logging as log
12-
from . import mechanism as mech, rfc, auth
11+
from . import mechanism as mech, rfc, auth, log
1312

1413
__all__ = ('DigestMD5', 'DigestMD5Password')
1514

sasl/mechanism.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ def failure(self):
7272
def confirm(self):
7373
return self.k is None
7474

75+
def finished(self):
76+
return not(callable(self.k))
77+
7578

7679
### Registry
7780

sasl/prelude.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## Copyright (c) 2010, Coptix, Inc. All rights reserved.
2+
## See the LICENSE file for license terms and warranty disclaimer.
3+
4+
"""prelude -- extra builtins"""
5+
6+
from __future__ import absolute_import
7+
import os, logging
8+
9+
__all__ = ('log', )
10+
11+
log = logging.getLogger(os.path.basename(os.path.dirname(__file__)))
12+
log.addHandler(logging.StreamHandler())

sasl/rfc.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,12 @@ def __init__(self, kind):
275275
self.write = kind.write
276276

277277
def read(self, data, pos=0):
278-
if data[pos] != '"':
279-
return self.kind.read(data, pos)
278+
try:
279+
if data[pos] != '"':
280+
return self.kind.read(data, pos)
281+
except IndexError:
282+
raise BadToken(self, data, pos)
283+
280284
try:
281285
(quoted, new_pos) = require(quoted_string, data, pos)
282286
(value, val_pos) = require(self.kind, quoted, 0)

sasl/tests.py

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ class TestMech(object):
7676
MECH = None
7777

7878
def setUp(self):
79+
import logging
7980
self.mech = self.MECH(AUTH)
81+
log.setLevel(logging.CRITICAL)
8082

8183
def test_success(self):
8284
(sk, ck) = self.negotiate('foo@bar.com', 'baz')
@@ -88,11 +90,7 @@ def test_failure(self):
8890
self.assertFalse(self.coalesce(sk, ck))
8991

9092
def coalesce(self, value, default):
91-
"""A value of None indicates the decision about whether
92-
authentication succeeded is left up to the other end of the
93-
exchange."""
94-
95-
return default if value is None else value
93+
return default.success() if value.confirm() else value.success()
9694

9795
def negotiate(self, user, passwd):
9896
"""Normally this negotiation would take place over a network.
@@ -107,26 +105,18 @@ def negotiate(self, user, passwd):
107105
of the exchange."""
108106

109107
## Server issues a challenge.
110-
(sk, sdata) = self.mech.challenge()
108+
sk = self.mech.challenge()
111109

112110
## Client responds.
113111
with fluid.let((USER, user), (PASS, passwd)):
114-
(ck, cdata) = self.mech.respond(sdata)
115-
116-
## Server and client continue the exchange until they're
117-
## satisfied.
118-
while callable(sk) or callable(ck):
119-
if callable(sk):
120-
self.assert_(cdata is not None)
121-
(sk, sdata) = sk(cdata)
122-
else:
123-
sdata = None
124-
125-
if callable(ck):
126-
self.assert_(sdata is not None)
127-
(ck, cdata) = ck(sdata)
128-
else:
129-
cdata = None
112+
ck = self.mech.respond(sk.data)
113+
114+
while not (sk.finished() and ck.finished()):
115+
if not sk.finished():
116+
sk = sk(ck.data)
117+
118+
if not ck.finished():
119+
ck = ck(sk.data)
130120

131121
return (sk, ck)
132122

@@ -139,8 +129,8 @@ class TestDigestMD5(TestMech, unittest.TestCase):
139129
def test_challenge(self):
140130
"""Test basic expectations about a challenge."""
141131

142-
(_, data) = self.mech.challenge()
143-
challenge = dict(rfc.data(self.mech.CHALLENGE, data))
132+
state = self.mech.challenge()
133+
challenge = dict(rfc.data(self.mech.CHALLENGE, state.data))
144134

145135
## Nonce is random, so it can't be compared for equality.
146136
self.assert_(challenge.pop('nonce'))
@@ -154,10 +144,10 @@ def test_challenge(self):
154144
def test_response(self):
155145
"""Test basic expectations about a response."""
156146

157-
(_, data) = self.mech.challenge()
147+
state = self.mech.challenge()
158148
with fluid.let((USER, 'user@example.net'), (PASS, 'secret')):
159-
(_, data) = self.mech.respond(data)
160-
resp = dict(rfc.data(self.mech.RESPOND, data))
149+
rstate = self.mech.respond(state.data)
150+
resp = dict(rfc.data(self.mech.RESPOND, rstate.data))
161151

162152
self.assertNotEqual(resp['nonce'], resp['cnonce'])
163153

0 commit comments

Comments
 (0)