Ejemplo n.º 1
0
    def __init__(self, header_val):
        data = parse_http_dict(header_val)
        self.realm = data.get('realm')
        self.username = data.get('username')
        self.nonce = data.get('nonce')
        self.uri = data.get('uri')
        self.method = data.get('method')
        self.response = data.get('response')
        self.algorithm = data.get('algorithm', 'MD5').upper()
        self.cnonce = data.get('cnonce')
        self.opaque = data.get('opaque')
        self.qop = data.get('qop', '').lower()
        self.nonce_count = data.get('nc')

        if self.algorithm not in self.valid_algorithms:
            raise HTTPSimpleResponse(httplib.BAD_REQUEST, 'Unsupported digest algorithm')

        if not (self.username and self.realm and self.nonce and self.uri and self.response):
            raise HTTPSimpleResponse(httplib.BAD_REQUEST, 'Digest algorithm required fields missing')

        if self.qop:
            if self.qop not in self.valid_qops:
                raise HTTPSimpleResponse(httplib.BAD_REQUEST, 'Unsupported digest qop')
            if not (self.cnonce and self.nonce_count):
                raise HTTPSimpleResponse(httplib.BAD_REQUEST, 'qop present, but cnonce and nonce_count absent')
        else:
            if self.cnonce or self.nonce_count:
                raise HTTPSimpleResponse(httplib.BAD_REQUEST, 'qop missing')
Ejemplo n.º 2
0
    def __init__(self, header_val):
        data = parse_http_dict(header_val)
        self.realm = data.get('realm')
        self.username = data.get('username')
        self.nonce = data.get('nonce')
        self.uri = data.get('uri')
        self.method = data.get('method')
        self.response = data.get('response')
        self.algorithm = data.get('algorithm', 'MD5').upper()
        self.cnonce = data.get('cnonce')
        self.opaque = data.get('opaque')
        self.qop = data.get('qop', '').lower()
        self.nonce_count = data.get('nc')

        if self.algorithm not in self.valid_algorithms:
            raise HTTPSimpleResponse(httplib.BAD_REQUEST,
                                     'Unsupported digest algorithm')

        if not (self.username and self.realm and self.nonce and self.uri
                and self.response):
            raise HTTPSimpleResponse(
                httplib.BAD_REQUEST,
                'Digest algorithm required fields missing')

        if self.qop:
            if self.qop not in self.valid_qops:
                raise HTTPSimpleResponse(httplib.BAD_REQUEST,
                                         'Unsupported digest qop')
            if not (self.cnonce and self.nonce_count):
                raise HTTPSimpleResponse(
                    httplib.BAD_REQUEST,
                    'qop present, but cnonce and nonce_count absent')
        else:
            if self.cnonce or self.nonce_count:
                raise HTTPSimpleResponse(httplib.BAD_REQUEST, 'qop missing')
Ejemplo n.º 3
0
 def test_digest_auth(self):
     'Test HTTP Digest auth'
     from calibre.srv.http_request import normalize_header_name
     from calibre.srv.utils import parse_http_dict
     r = router()
     with TestServer(r.dispatch) as server:
         r.auth_controller.log = server.log
         def test(conn, path, headers={}, status=httplib.OK, body=b'', request_body=b''):
             conn.request('GET', path, request_body, headers)
             r = conn.getresponse()
             self.ae(r.status, status)
             self.ae(r.read(), body)
             return {normalize_header_name(k):v for k, v in r.getheaders()}
         conn = server.connect()
         test(conn, '/open', body=b'open')
         auth = parse_http_dict(test(conn, '/closed', status=httplib.UNAUTHORIZED)['WWW-Authenticate'])
         self.ae(auth[b'Digest realm'], bytes(REALM)), self.ae(auth[b'algorithm'], b'MD5'), self.ae(auth[b'qop'], b'auth')
         self.assertNotIn('stale', auth)
         self.ae(urlopen(server).read(), b'closed')
Ejemplo n.º 4
0
    def test_digest_auth(self):  # {{{
        'Test HTTP Digest auth'
        from calibre.srv.http_request import normalize_header_name
        from calibre.srv.utils import parse_http_dict
        r = router()
        with TestServer(r.dispatch) as server:
            r.auth_controller.log = server.log

            def test(conn,
                     path,
                     headers={},
                     status=httplib.OK,
                     body=b'',
                     request_body=b''):
                conn.request('GET', path, request_body, headers)
                r = conn.getresponse()
                self.ae(r.status, status)
                self.ae(r.read(), body)
                return {normalize_header_name(k): v for k, v in r.getheaders()}

            conn = server.connect()
            test(conn, '/open', body=b'open')
            auth = parse_http_dict(
                test(conn, '/closed', status=httplib.UNAUTHORIZED)
                ['WWW-Authenticate'].partition(b' ')[2])
            nonce = auth['nonce']
            auth = parse_http_dict(
                test(conn, '/closed', status=httplib.UNAUTHORIZED)
                ['WWW-Authenticate'].partition(b' ')[2])
            self.assertNotEqual(nonce, auth['nonce'], 'nonce was re-used')
            self.ae(auth[b'realm'], bytes(REALM)), self.ae(
                auth[b'algorithm'], b'MD5'), self.ae(auth[b'qop'], b'auth')
            self.assertNotIn('stale', auth)
            args = auth.copy()
            args['un'], args['pw'], args[
                'uri'] = 'testuser', 'testpw', '/closed'

            def ok_test(conn, dh, **args):
                args['body'] = args.get('body', b'closed')
                return test(conn,
                            '/closed',
                            headers={'Authorization': dh},
                            **args)

            ok_test(conn, digest(**args))
            # Check that server ignores repeated nc values
            ok_test(conn, digest(**args))

            warnings = []
            server.loop.log.warn = lambda *args, **kwargs: warnings.append(
                ' '.join(args))
            # Check stale nonces
            orig, r.auth_controller.max_age_seconds = r.auth_controller.max_age_seconds, -1
            auth = parse_http_dict(
                test(conn,
                     '/closed',
                     headers={'Authorization': digest(**args)},
                     status=httplib.UNAUTHORIZED)
                ['WWW-Authenticate'].partition(b' ')[2])
            self.assertIn('stale', auth)
            r.auth_controller.max_age_seconds = orig
            ok_test(conn, digest(**args))

            def fail_test(conn, modify, **kw):
                kw['body'] = kw.get('body', b'')
                kw['status'] = kw.get('status', httplib.UNAUTHORIZED)
                args['modify'] = modify
                return test(conn,
                            '/closed',
                            headers={'Authorization': digest(**args)},
                            **kw)

            # Check modified nonce fails
            fail_test(conn, lambda da: setattr(da, 'nonce', 'xyz'))
            fail_test(conn, lambda da: setattr(da, 'nonce', 'x' + da.nonce))

            # Check mismatched uri fails
            fail_test(conn, lambda da: setattr(da, 'uri', '/'))
            fail_test(conn, lambda da: setattr(da, 'uri', '/closed2'))
            fail_test(conn, lambda da: setattr(da, 'uri', '/closed/2'))

            # Check that incorrect user/password fails
            fail_test(conn, lambda da: setattr(da, 'pw', '/'))
            fail_test(conn, lambda da: setattr(da, 'username', '/'))
            fail_test(conn, lambda da: setattr(da, 'username', ''))
            fail_test(conn, lambda da: setattr(da, 'pw', ''))
            fail_test(
                conn, lambda da:
                (setattr(da, 'pw', ''), setattr(da, 'username', '')))

            # Check against python's stdlib
            self.ae(urlopen(server).read(), b'closed')

            # Check using curl
            curl = find_executable('curl')
            if curl:

                def docurl(data, *args):
                    cmd = [curl] + list(args) + [
                        'http://localhost:%d/closed' % server.address[1]
                    ]
                    p = subprocess.Popen(cmd,
                                         stdout=subprocess.PIPE,
                                         stderr=open(os.devnull, 'wb'))
                    x = p.stdout.read()
                    p.wait()
                    self.ae(x, data)

                docurl(b'')
                docurl(b'', '--digest', '--user', 'xxxx:testpw')
                docurl(b'', '--digest', '--user', 'testuser:xtestpw')
                docurl(b'closed', '--digest', '--user', 'testuser:testpw')
Ejemplo n.º 5
0
    def test_digest_auth(self):  # {{{
        'Test HTTP Digest auth'
        from calibre.srv.http_request import normalize_header_name
        from calibre.srv.utils import parse_http_dict
        r = router()
        with TestServer(r.dispatch) as server:
            r.auth_controller.log = server.log

            def test(conn, path, headers={}, status=httplib.OK, body=b'', request_body=b''):
                conn.request('GET', path, request_body, headers)
                r = conn.getresponse()
                self.ae(r.status, status)
                self.ae(r.read(), body)
                return {normalize_header_name(k):v for k, v in r.getheaders()}
            conn = server.connect()
            test(conn, '/open', body=b'open')
            auth = parse_http_dict(test(conn, '/closed', status=httplib.UNAUTHORIZED)['WWW-Authenticate'].partition(b' ')[2])
            nonce = auth['nonce']
            auth = parse_http_dict(test(conn, '/closed', status=httplib.UNAUTHORIZED)['WWW-Authenticate'].partition(b' ')[2])
            self.assertNotEqual(nonce, auth['nonce'], 'nonce was re-used')
            self.ae(auth[b'realm'], bytes(REALM)), self.ae(auth[b'algorithm'], b'MD5'), self.ae(auth[b'qop'], b'auth')
            self.assertNotIn('stale', auth)
            args = auth.copy()
            args['un'], args['pw'], args['uri'] = 'testuser', 'testpw', '/closed'

            def ok_test(conn, dh, **args):
                args['body'] = args.get('body', b'closed')
                return test(conn, '/closed', headers={'Authorization':dh}, **args)

            ok_test(conn, digest(**args))
            # Check that server ignores repeated nc values
            ok_test(conn, digest(**args))

            warnings = []
            server.loop.log.warn = lambda *args, **kwargs: warnings.append(' '.join(args))
            # Check stale nonces
            orig, r.auth_controller.max_age_seconds = r.auth_controller.max_age_seconds, -1
            auth = parse_http_dict(test(conn, '/closed', headers={
                'Authorization':digest(**args)},status=httplib.UNAUTHORIZED)['WWW-Authenticate'].partition(b' ')[2])
            self.assertIn('stale', auth)
            r.auth_controller.max_age_seconds = orig
            ok_test(conn, digest(**args))

            def fail_test(conn, modify, **kw):
                kw['body'] = kw.get('body', b'')
                kw['status'] = kw.get('status', httplib.UNAUTHORIZED)
                args['modify'] = modify
                return test(conn, '/closed', headers={'Authorization':digest(**args)}, **kw)

            # Check modified nonce fails
            fail_test(conn, lambda da:setattr(da, 'nonce', 'xyz'))
            fail_test(conn, lambda da:setattr(da, 'nonce', 'x' + da.nonce))

            # Check mismatched uri fails
            fail_test(conn, lambda da:setattr(da, 'uri', '/'))
            fail_test(conn, lambda da:setattr(da, 'uri', '/closed2'))
            fail_test(conn, lambda da:setattr(da, 'uri', '/closed/2'))

            # Check that incorrect user/password fails
            fail_test(conn, lambda da:setattr(da, 'pw', '/'))
            fail_test(conn, lambda da:setattr(da, 'username', '/'))
            fail_test(conn, lambda da:setattr(da, 'username', ''))
            fail_test(conn, lambda da:setattr(da, 'pw', ''))
            fail_test(conn, lambda da:(setattr(da, 'pw', ''), setattr(da, 'username', '')))

            # Check against python's stdlib
            self.ae(urlopen(server).read(), b'closed')

            # Check using curl
            curl = find_executable('curl')
            if curl:
                def docurl(data, *args):
                    cmd = [curl] + list(args) + ['http://localhost:%d/closed' % server.address[1]]
                    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'))
                    x = p.stdout.read()
                    p.wait()
                    self.ae(x, data)
                docurl(b'')
                docurl(b'', '--digest', '--user', 'xxxx:testpw')
                docurl(b'', '--digest', '--user', 'testuser:xtestpw')
                docurl(b'closed', '--digest', '--user', 'testuser:testpw')