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)
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
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)
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)
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)
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
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
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
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
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)
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
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
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()))
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}))
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
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)
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)
def extract_ssid(args): cookie_str = args['headers'].get('Cookie') cookie = BaseCookie(cookie_str) ssid = cookie.get('SSID', None) return ssid
def _BaseCookie__parse_string(self, str, patt=_CookiePattern): BaseCookie._BaseCookie__parse_string(self, str, patt=patt)