コード例 #1
0
ファイル: __init__.py プロジェクト: socialplanning/WSSEAuth
 def __init__(self, app, user_dict, required = False, json=True):
     self.app = app
     self.user_dict = user_dict
     self.nonces_by_time = Fifo()
     self.nonces_set = set()
     self.required = required
     self.json = json
コード例 #2
0
ファイル: __init__.py プロジェクト: socialplanning/WSSEAuth
class WSSEAuthMiddleware:
    def __init__(self, app, user_dict, required = False, json=True):
        self.app = app
        self.user_dict = user_dict
        self.nonces_by_time = Fifo()
        self.nonces_set = set()
        self.required = required
        self.json = json
        
    def _fail(self, start_response):
        status = "401 Authorization Required"
        headers = [('Content-type', 'text/plain'), ('WWW-Authenticate', 'WSSE realm="wsse", profile="UsernameToken"')]
        start_response(status, headers)
        if self.json:
            return [dumps({'status' : 'rejected', 'reason' : 'Bad WSSE Auth'})]
        else:
            return ['Bad WSSE Auth']
            
    def __call__(self, environ, start_response):
        #parse nonce, created, username out of ...
        #check validity of wsse info

        if environ.get('HTTP_AUTHORIZATION', None) != 'WSSE profile="UsernameToken"':
            if self.required:
                #print "no http_auth", environ
                return self._fail(start_response)
            else:
                return self.app(environ, start_response)

        header = environ.get('HTTP_X_WSSE', None)
        if not header:
            #print "no header"
            return self._fail(start_response)            
        
        wsse_re = re.compile('UsernameToken Username="******"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"')
        match = wsse_re.match(header)
        if not match:
            #print "Bad format"
            return self._fail(start_response) #bad format

        username = match.group(1)
        password = self.user_dict.get(username.lower())
        if not password:
            #print "no user %s password" % username
            return self._fail(start_response)
        digest = match.group(2)
        nonce = match.group(3)
        created = match.group(4)

        if nonce in self.nonces_set:
            #print "already used this nonce"
            return self._fail(start_response)

        created_date = parse_w3dtf(created)
        five_minutes_ago = datetime.now() - timedelta(0, 300, 0)
        if created_date < five_minutes_ago:
            #print "too old"
            return self._fail(start_response) #too old

        self.nonces_set.add(nonce)

        self.nonces_by_time.append((created_date, nonce))

        #remove old nonces
        while not self.nonces_by_time.empty() and self.nonces_by_time.top()[0] < five_minutes_ago:
            created_date, nonce = self.nonces_by_time.pop()
            self.nonces_set.remove(nonce)

        key = "%s%s%s" % (nonce, created, password)        
        if not digest == sha(key).digest().encode("base64").strip():
            #print "did not match"
            return self._fail(start_response)

        environ['REMOTE_USER'] = username
        environ['AUTHENTICATION_METHOD'] = 'WSSE'
        return self.app(environ, start_response)
コード例 #3
0
ファイル: test_fifo.py プロジェクト: socialplanning/WSSEAuth
def test_fifo():
    fifo = Fifo()

    assert fifo.empty()
    fifo.append('morx')
    assert not fifo.empty()
    assert fifo.top() == 'morx'
    assert fifo.pop() == 'morx'

    assert fifo.empty()

    #---

    fifo.append('foo')
    fifo.append('bar')

    assert fifo.top() == 'foo'
    assert fifo.pop() == 'foo'
    assert not fifo.empty()
    assert fifo.pop() == 'bar'
    assert fifo.empty()

    #---

    fifo.append('foo')
    fifo.append('bar')

    assert fifo.top() == 'foo'
    assert fifo.pop() == 'foo'
    assert not fifo.empty()

    fifo.append('baz')

    assert fifo.pop() == 'bar'
    assert not fifo.empty()
    assert fifo.pop() == 'baz'
    assert fifo.empty()