Esempio n. 1
0
def test_loose_cookies_types(loop: Any) -> None:
    req = ClientRequest("get", URL("http://python.org"), loop=loop)
    morsel = Morsel()
    morsel.set(key="string", val="Another string", coded_val="really")

    accepted_types = [
        [("str", BaseCookie())],
        [("str", morsel)],
        [
            ("str", "str"),
        ],
        {
            "str": BaseCookie()
        },
        {
            "str": morsel
        },
        {
            "str": "str"
        },
        SimpleCookie(),
    ]

    for loose_cookies_type in accepted_types:
        req.update_cookies(cookies=loose_cookies_type)
Esempio n. 2
0
    def _login(self):
        self.getPage('/login', method='POST', body='login=admin&password=admin')

        cookie = BaseCookie()
        cookie.load(self.cookies[0][1])

        return cookie['session_id'].value
    def do_request(self, req, status, expect_errors):
        """
        Override webtest.TestApp's method so that we do real HTTP requests
        instead of WSGI calls.
        """
        headers = {}
        if self.cookies:
            c = BaseCookie()
            for name, value in self.cookies.items():
                c[name] = value
            hc = '; '.join(
                ['='.join([key, value]) for key, value in c.items()])
            req.headers['Cookie'] = hc

        res = self._do_httplib_request(req)
        if req.path_qs == '/kill' and res.status_int == 200:
            return res

        # Set these attributes for consistency with webtest.
        res.request = req
        res.test_app = self

        if not expect_errors:
            self._check_status(res.status_int, res)
            self._check_errors(res)
        res.cookies_set = {}

        if self.cookies:
            # merge cookies back in
            self.cookiejar.extract_cookies(ResponseCookieAdapter(res),
                                           RequestCookieAdapter(req))

        return res
Esempio n. 4
0
async def test_loose_cookies_types() -> None:
    jar = CookieJar()

    accepted_types = [
        [('str', BaseCookie())],
        [('str', Morsel())],
        [('str', 'str'), ],
        {'str': BaseCookie()},
        {'str': Morsel()},
        {'str': 'str'},
        SimpleCookie(),
    ]

    for loose_cookies_type in accepted_types:
        jar.update_cookies(cookies=loose_cookies_type)
Esempio n. 5
0
async def test_loose_cookies_types() -> None:
    jar = CookieJar()

    accepted_types = [
        [("str", BaseCookie())],
        [("str", Morsel())],
        [
            ("str", "str"),
        ],
        {"str": BaseCookie()},
        {"str": Morsel()},
        {"str": "str"},
        SimpleCookie(),
    ]

    for loose_cookies_type in accepted_types:
        jar.update_cookies(cookies=loose_cookies_type)
Esempio n. 6
0
def test_loose_cookies_types(loop) -> None:
    req = ClientRequest('get', URL('http://python.org'), loop=loop)
    morsel = Morsel()
    morsel.set(key='string', val='Another string', coded_val='really')

    accepted_types = [
        [('str', BaseCookie())],
        [('str', morsel)],
        [('str', 'str'), ],
        {'str': BaseCookie()},
        {'str': morsel},
        {'str': 'str'},
        SimpleCookie(),
    ]

    for loose_cookies_type in accepted_types:
        req.update_cookies(cookies=loose_cookies_type)
Esempio n. 7
0
    def filter_cookies(
        self, request_url: URL = URL()
    ) -> Union["BaseCookie[str]", "SimpleCookie[str]"]:
        """Returns this jar's cookies filtered by their attributes."""
        self._do_expiration()
        if not isinstance(request_url, URL):
            warnings.warn(
                "The method accepts yarl.URL instances only, got {}".format(
                    type(request_url)
                ),
                DeprecationWarning,
            )
            request_url = URL(request_url)
        filtered: Union["SimpleCookie[str]", "BaseCookie[str]"] = (
            SimpleCookie() if self._quote_cookie else BaseCookie()
        )
        hostname = request_url.raw_host or ""
        request_origin = URL()
        with contextlib.suppress(ValueError):
            request_origin = request_url.origin()

        is_not_secure = (
            request_url.scheme not in ("https", "wss")
            and request_origin not in self._treat_as_secure_origin
        )

        for cookie in self:
            name = cookie.key
            domain = cookie["domain"]

            # Send shared cookies
            if not domain:
                filtered[name] = cookie.value
                continue

            if not self._unsafe and is_ip_address(hostname):
                continue

            if (domain, name) in self._host_only_cookies:
                if domain != hostname:
                    continue
            elif not self._is_domain_match(domain, hostname):
                continue

            if not self._is_path_match(request_url.path, cookie["path"]):
                continue

            if is_not_secure and cookie["secure"]:
                continue

            # It's critical we use the Morsel so the coded_value
            # (based on cookie version) is preserved
            mrsl_val = cast("Morsel[str]", cookie.get(cookie.key, Morsel()))
            mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)
            filtered[name] = mrsl_val

        return filtered
Esempio n. 8
0
 def _get_session_id(self, environ):
     cookies = BaseCookie(environ.get('HTTP_COOKIE', None))
     session_id = cookies['session'].value if 'session' in cookies else None
     if not session_id:
         while True:
             session_id = str(uuid4())
             if not self.cache.get('session/' + session_id):
                 break
     return session_id
Esempio n. 9
0
 def get_cookie(self, name):
     """Get auth cookie."""
     cookies = self.headers.get('Cookie')
     if cookies:
         authcookie = BaseCookie(cookies).get(name)
         if authcookie:
             return authcookie.value
         else:
             return None
     else:
         return None
Esempio n. 10
0
 def check_session(self):
     self.user = None
     cookie = self.headers['cookie']
     if cookie is None:
         return
     ssid_cookie = BaseCookie(cookie).get(session.SESS_KEY)
     if ssid_cookie is None:
         return
     ssid = ssid_cookie.value
     user_data = session.validate(ssid)
     self.user = user_data
Esempio n. 11
0
    def logged_in(response, session_cookie_name):
        # This doesn't work because sessions are now created for guests.

        cookie_text = response.headers.get("set-cookie", None)
        if not cookie_text:
            return False
        cookies = BaseCookie()
        cookies.load(cookie_text)
        morsel = cookies.get(session_cookie_name, None)
        value = morsel and morsel.value

        # Cannot test to see if secure cookie can be parsed as JSON.
        if value:
            try:
                value = json.loads(value)
            except json.decoder.JSONDecodeError:
                print(
                    "Unable to parse value of cookie `%s` as JSON: %s." % (
                        session_cookie_name, repr(value)))

        return bool(value)
Esempio n. 12
0
    def do_request(self, req, status, expect_errors):
        """
        Override webtest.TestApp's method so that we do real HTTP requests
        instead of WSGI calls.
        """
        headers = {}
        if self.cookies:
            c = BaseCookie()
            for name, value in self.cookies.items():
                c[name] = value
            hc = '; '.join(['='.join([m.key, m.value]) for m in c.values()])
            req.headers['Cookie'] = hc

        res = self._do_httplib_request(req)
        # Set these attributes for consistency with webtest.
        res.request = req
        res.test_app = self

        if not expect_errors:
            self._check_status(res.status_int, res)
            self._check_errors(res)
        res.cookies_set = {}

        for header in res.headers.getall('set-cookie'):
            try:
                c = BaseCookie(header)
            except CookieError as e:
                raise CookieError(
                    "Could not parse cookie header %r: %s" % (header, e))
            for key, morsel in c.items():
                self.cookies[key] = morsel.value
                res.cookies_set[key] = morsel.value
        return res
Esempio n. 13
0
 def check():
     if 'cookie' not in r.headers:
         return False
     bc = BaseCookie(r.headers['cookie'])
     if 'SESSION' not in bc:
         return False
     sess = bc['SESSION'].value
     log.debug('SESSION = ' + sess)
     if sess in SESSIONS:
         log.debug('SESSION IS OK')
         r.user = SESSIONS[sess]
         return True
     return False
Esempio n. 14
0
    def unset_cookie(self, name):
        """Remove a cookie from those that are being sent with the response"""
        name = isomorphic_decode(name)
        cookies = self.headers.get("Set-Cookie")
        parser = BaseCookie()
        for cookie in cookies:
            parser.load(isomorphic_decode(cookie))

        if name in parser.keys():
            del self.headers["Set-Cookie"]
            for m in parser.values():
                if m.key != name:
                    self.headers.append(("Set-Cookie", m.OutputString()))
Esempio n. 15
0
    def __init__(self, user: User, log: BoundLoggerLazyProxy,
                 options: Dict[str, Any]):
        self.user = user
        self.log = log
        self.jupyter_base = options.get("nb_url", "/nb/")
        self.jupyter_url = Configuration.environment_url + self.jupyter_base

        self.xsrftoken = "".join(
            random.choices(string.ascii_uppercase + string.digits, k=16))
        self.jupyter_options_form = options.get("jupyter_options_form", {})

        self.headers = {
            "Authorization": "Bearer " + user.token,
            "x-xsrftoken": self.xsrftoken,
        }

        self.session = ClientSession(headers=self.headers)
        self.session.cookie_jar.update_cookies(
            BaseCookie({"_xsrf": self.xsrftoken}))
Esempio n. 16
0
    def filter_cookies(
        self, request_url: URL = URL()
    ) -> Union["BaseCookie[str]", "SimpleCookie[str]"]:
        """Returns this jar's cookies filtered by their attributes."""
        self._do_expiration()
        request_url = URL(request_url)
        filtered: Union["SimpleCookie[str]", "BaseCookie[str]"] = (
            SimpleCookie() if self._quote_cookie else BaseCookie())
        hostname = request_url.raw_host or ""
        is_not_secure = request_url.scheme not in ("https", "wss")

        for cookie in self:
            name = cookie.key
            domain = cookie["domain"]

            # Send shared cookies
            if not domain:
                filtered[name] = cookie.value
                continue

            if not self._unsafe and is_ip_address(hostname):
                continue

            if (domain, name) in self._host_only_cookies:
                if domain != hostname:
                    continue
            elif not self._is_domain_match(domain, hostname):
                continue

            if not self._is_path_match(request_url.path, cookie["path"]):
                continue

            if is_not_secure and cookie["secure"]:
                continue

            # It's critical we use the Morsel so the coded_value
            # (based on cookie version) is preserved
            mrsl_val = cast("Morsel[str]", cookie.get(cookie.key, Morsel()))
            mrsl_val.set(cookie.key, cookie.value, cookie.coded_value)
            filtered[name] = mrsl_val

        return filtered
Esempio n. 17
0
    async def handleRequest(self, reader, writer):
        # connection id, for debugging
        connid = self.nextConnId
        self.nextConnId += 1

        logger.debug(f'{connid}: new incoming connection')
        # simple HTTP parsing, yes this is a terrible idea.
        l = await reader.readline()
        if l == bytes():
            raise BadRequest(f'{connid}: unexpected eof')
        l = l.rstrip(b'\r\n')
        try:
            method, rawPath, proto = l.split(b' ')
            logger.debug(f'{connid}: got {method} {rawPath} {proto}')
        except ValueError:
            logger.error(f'{connid}: cannot split line {l}')
            raise
        reqUrl = furl(rawPath.decode('utf-8'))

        headers = CIMultiDict()
        while True:
            if len(headers) > 100:
                raise BadRequest('too many headers')

            l = await reader.readline()
            if l == bytes():
                raise BadRequest(f'{connid}: unexpected eof in headers')
            l = l.rstrip(b'\r\n')
            logger.debug(f'{connid}: got header line {l!r}')
            # end of headers?
            if l == bytes():
                break
            try:
                key, value = l.decode('utf-8').split(':', 1)
                headers.add(key.strip(), value.strip())
            except ValueError:
                logger.error(f'cannot parse {l}')

        logger.debug(f'{connid}: {rawPath} {method} got headers {headers}')

        route = None
        try:
            netloc = headers['host']
            reqUrl = reqUrl.set(scheme='http', netloc=netloc)
            logger.debug(f'got request url {reqUrl}')
            routeKey = None
            for d in self.domain:
                m = parse(d, reqUrl.netloc)
                if m is not None:
                    routeKey = RouteKey(key=m['key'], user=m['user'])
                    logger.debug(f'{connid}: got route key {routeKey}')
                    break
            route = self.routes[routeKey]
        except (KeyError, ValueError):
            logger.info(f'{connid}: cannot find route for {reqUrl}')
            self.status['noroute'] += 1
            # error is written to client later

        # is this a non-forwarded request?
        segments = reqUrl.path.segments
        if len(segments) > 0 and segments[0] == '_conductor':
            if segments[1] == 'auth':
                logger.info(f'authorization request for {reqUrl.netloc}')
                try:
                    nextLoc = reqUrl.query.params['next'].encode('utf-8')
                except KeyError:
                    nextLoc = b'/'
                writer.write(b'\r\n'.join([
                    b'HTTP/1.0 302 Found', b'Location: ' + nextLoc,
                    b'Set-Cookie: authorization=' +
                    segments[2].encode('utf-8') + b'; HttpOnly; Path=/',
                    b'Cache-Control: no-store', b'',
                    b'Follow the white rabbit.'
                ]))
            elif segments[1] == 'status':
                writer.write(
                    b'HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n'
                )
                self.status['routesTotal'] = len(self.routes)
                writer.write(
                    json.dumps(self.status, ensure_ascii=True).encode('ascii'))
            else:
                writer.write(
                    b'HTTP/1.0 404 Not Found\r\nContent-Type: plain/text\r\n\r\nNot found'
                )
            writer.close()
            return

        if not route:
            writer.write(
                b'HTTP/1.0 404 Not Found\r\nConnection: close\r\n\r\n')
            writer.close()
            return

        # check authorization
        cookies = BaseCookie()
        try:
            cookies.load(headers['Cookie'])
        except KeyError:
            # will be rejected later
            pass
        authorized = False
        for c in cookies.values():
            # Only hashed authorization is available to server.
            if c.key == 'authorization' and self.hashKey(
                    c.value) == route.auth:
                authorized = True
                break
        try:
            # do not forward auth cookie to the application, so it can’t leak it.
            del cookies['authorization']
            headers['Cookie'] = cookies.output(header='', sep='')
        except KeyError:
            # nonexistent cookie is fine
            pass

        if not authorized:
            logger.info(
                f'{connid}-{reqUrl}: not authorized, cookies sent {cookies.values()}'
            )
            writer.write(
                b'HTTP/1.0 403 Unauthorized\r\nContent-Type: plain/text\r\nConnection: close\r\n\r\nUnauthorized'
            )
            writer.close()
            self.status['unauthorized'] += 1
            return

        # try opening the socket
        try:
            start = time.time()
            sockreader, sockwriter = await asyncio.open_unix_connection(
                path=route.socket)
            end = time.time()
            logger.debug(f'opening socket took {end-start}s')
        except (ConnectionRefusedError, FileNotFoundError, PermissionError):
            logger.info(f'{connid}-{reqUrl}: route {routeKey} is broken')
            writer.write(
                b'HTTP/1.0 502 Bad Gateway\r\nConnection: close\r\n\r\n')
            writer.close()
            self.status['broken'] += 1
            return

        # some headers are fixed
        # not parsing body, so we cannot handle more than one request per connection
        # XXX: this is super-inefficient
        if 'Upgrade' not in headers or headers['Upgrade'].lower(
        ) != 'websocket':
            headers['Connection'] = 'close'

        # write http banner plus headers
        sockwriter.write(method + b' ' + rawPath + b' ' + proto + b'\r\n')
        for k, v in headers.items():
            sockwriter.write(f'{k}: {v}\r\n'.encode('utf-8'))
        sockwriter.write(b'\r\n')

        async def beforeABClose(result):
            if result == 0:
                # no response received from client
                logger.info(
                    f'{connid}-{reqUrl}: route {routeKey} got no result from server'
                )
                writer.write(
                    b'HTTP/1.0 502 Bad Gateway\r\nConnection: close\r\n\r\n')

        await proxy((sockreader, sockwriter, 'sock'), (reader, writer, 'web'),
                    logger=logger,
                    logPrefix=connid,
                    beforeABClose=beforeABClose)
Esempio n. 18
0
    def wsgi_app(self, environ, start_response):
        ctx = self.request_context(environ)
        ctx.push()

        req = ctx.request
        charset = req.charset

        session = ctx.session
        inner_ctx = ctx
        should_proxy = self.get_logged_in(session) 

        environ['flask_protector_app.verify_login'] = partial(self.verify_login, session=session)
        environ['flask_protector_app.set_logged_in'] = partial(self.set_logged_in, session)
        environ['flask_protector_app.get_logged_in'] = partial(self.get_logged_in, session)
        environ['flask_protector_app.get_logged_in_as'] = partial(self.get_logged_in_as, session)

        new_environ = environ.copy()

        if should_proxy:
            if 'HTTP_COOKIE' in new_environ:
                # Scrub the environment of any trace of the protector's cookie,
                # because otherwise the inner app will see it and probably try
                # to send Set-Cookie headers to refresh the session, effectively undoing
                # any changes the protector wants to make to it.
                
                parsed_cookie = BaseCookie()
                parsed_cookie.load(environ['HTTP_COOKIE']) # TODO encoding?
                del parsed_cookie[self.session_cookie_name]
                stringified_cookie = str(parsed_cookie).partition('Set-Cookie: ')[2]
                if stringified_cookie:
                    new_environ['HTTP_COOKIE'] = stringified_cookie
                else:
                    del new_environ['HTTP_COOKIE']

            inner_ctx = type(ctx)(
                self.wrapped_app,
                environ=new_environ,
                request=self.wrapped_app.request_class(new_environ)
            )
        
        error = None
        try:
            response = None
            try:
                if should_proxy:
                   inner_ctx.push()
                if not should_proxy:
                    response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:
                error = sys.exc_info()[1]
                raise
            if response is not None:
                return response(new_environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            if should_proxy:
                result = self.wrapped_app.wsgi_app(new_environ, start_response)
                inner_ctx.auto_pop(error)
                return result
            ctx.auto_pop(error)
Esempio n. 19
0
def extract_ssid(args):
    cookie_str = args['headers'].get('Cookie')
    cookie = BaseCookie(cookie_str)
    ssid = cookie.get('SSID', None)
    return ssid
Esempio n. 20
0
 def _BaseCookie__parse_string(self, str, patt=_CookiePattern):
     BaseCookie._BaseCookie__parse_string(self, str, patt=patt)