Beispiel #1
0
def _extractURLparts(request: IRequest) -> Tuple[str, str, int, str, str]:
    """
    Extracts and decodes URI parts from C{request}.

    All strings must be UTF8-decodable.

    @param request: A Twisted Web request.

    @raise URLDecodeError: If one of the parts could not be decoded as UTF-8.

    @return: L{tuple} of the URL scheme, the server name, the server port, the
        path info and the script name.
    """
    server_name = request.getRequestHostname()
    if hasattr(request.getHost(), "port"):
        server_port = request.getHost().port
    else:
        server_port = 0
    if (bool(request.isSecure()), server_port) not in [
        (True, 443),
        (False, 80),
        (False, 0),
        (True, 0),
    ]:
        server_name = server_name + b":" + intToBytes(server_port)

    script_name = b""
    if request.prepath:
        script_name = b"/".join(request.prepath)

        if not script_name.startswith(b"/"):
            script_name = b"/" + script_name

    path_info = b""
    if request.postpath:
        path_info = b"/".join(request.postpath)

        if not path_info.startswith(b"/"):
            path_info = b"/" + path_info

    url_scheme = "https" if request.isSecure() else "http"

    utf8Failures = []
    try:
        server_name = server_name.decode("utf-8")
    except UnicodeDecodeError:
        utf8Failures.append(("SERVER_NAME", Failure()))
    try:
        path_text = path_info.decode("utf-8")
    except UnicodeDecodeError:
        utf8Failures.append(("PATH_INFO", Failure()))
    try:
        script_text = script_name.decode("utf-8")
    except UnicodeDecodeError:
        utf8Failures.append(("SCRIPT_NAME", Failure()))

    if utf8Failures:
        raise _URLDecodeError(utf8Failures)

    return url_scheme, server_name, server_port, path_text, script_text
Beispiel #2
0
def get_request_uri(request: IRequest) -> bytes:
    """Return the full URI that was requested by the client"""
    return b"%s://%s%s" % (
        b"https" if request.isSecure() else b"http",
        _get_requested_host(request),
        # despite its name, "request.uri" is only the path and query-string.
        request.uri,
    )
Beispiel #3
0
def _get_requested_host(request: IRequest) -> bytes:
    hostname = request.getHeader(b"host")
    if hostname:
        return hostname

    # no Host header, use the address/port that the request arrived on
    host: Union[address.IPv4Address, address.IPv6Address] = request.getHost()

    hostname = host.host.encode("ascii")

    if request.isSecure() and host.port == 443:
        # default port for https
        return hostname

    if not request.isSecure() and host.port == 80:
        # default port for http
        return hostname

    return b"%s:%i" % (
        hostname,
        host.port,
    )
Beispiel #4
0
def urlFromRequest(request: IRequest) -> DecodedURL:
    sentHeader = request.getHeader(b"host")
    if sentHeader is not None:
        sentHeader = sentHeader.decode("charmap")
        if ":" in sentHeader:
            host, port = sentHeader.split(":")
            port = int(port)
        else:
            host = sentHeader
            port = None
    else:
        host = request.client.host
        port = request.client.port

    url = DecodedURL.fromText(request.uri.decode("charmap"))
    url = url.replace(
        scheme="https" if request.isSecure() else "http",
        host=host,
        port=port,
    )
    return url
Beispiel #5
0
    def procureSession(self,
                       request: IRequest,
                       forceInsecure: bool = False) -> Any:
        alreadyProcured = request.getComponent(ISession)
        if alreadyProcured is not None:
            if not forceInsecure or not request.isSecure():
                returnValue(alreadyProcured)

        if request.isSecure():
            if forceInsecure:
                tokenHeader = self._insecureTokenHeader
                cookieName: Union[str, bytes] = self._insecureCookie
                sentSecurely = False
            else:
                tokenHeader = self._secureTokenHeader
                cookieName = self._secureCookie
                sentSecurely = True
        else:
            # Have we inadvertently disclosed a secure token over an insecure
            # transport, for example, due to a buggy client?
            allPossibleSentTokens: Sequence[str] = sum(
                [
                    request.requestHeaders.getRawHeaders(header, [])
                    for header in [
                        self._secureTokenHeader,
                        self._insecureTokenHeader,
                    ]
                ],
                [],
            ) + [
                it for it in [
                    request.getCookie(cookie)
                    for cookie in [self._secureCookie, self._insecureCookie]
                ] if it
            ]
            # Does it seem like this check is expensive? It sure is! Don't want
            # to do it? Turn on your dang HTTPS!
            yield self._store.sentInsecurely(allPossibleSentTokens)
            tokenHeader = self._insecureTokenHeader
            cookieName = self._insecureCookie
            sentSecurely = False
            # Fun future feature: honeypot that does this over HTTPS, but sets
            # isSecure() to return false because it serves up a cert for the
            # wrong hostname or an invalid cert, to keep API clients honest
            # about chain validation.
        sentHeader = (request.getHeader(tokenHeader) or b"").decode("utf-8")
        sentCookie = (request.getCookie(cookieName) or b"").decode("utf-8")
        if sentHeader:
            mechanism = SessionMechanism.Header
        else:
            mechanism = SessionMechanism.Cookie
        if not (sentHeader or sentCookie):
            session = None
        else:
            try:
                session = yield self._store.loadSession(
                    sentHeader or sentCookie, sentSecurely, mechanism)
            except NoSuchSession:
                if mechanism == SessionMechanism.Header:
                    raise
                session = None
        if mechanism == SessionMechanism.Cookie and (
                session is None or session.identifier != sentCookie):
            if session is None:
                if request.startedWriting:
                    # At this point, if the mechanism is Header, we either have
                    # a valid session or we bailed after NoSuchSession above.
                    raise TooLateForCookies(
                        "You tried initializing a cookie-based session too"
                        " late in the request pipeline; the headers"
                        " were already sent.")
                if request.method != b"GET":
                    # Sessions should only ever be auto-created by GET
                    # requests; there's no way that any meaningful data
                    # manipulation could succeed (no CSRF token check could
                    # ever succeed, for example).
                    raise NoSuchSession(
                        "Can't initialize a session on a "
                        "{method} request.".format(
                            method=request.method.decode("ascii")))
                if not self._setCookieOnGET:
                    # We don't have a session ID at all, and we're not allowed
                    # by policy to set a cookie on the client.
                    raise NoSuchSession(
                        "Cannot auto-initialize a session for this request.")
                session = yield self._store.newSession(sentSecurely, mechanism)
            identifierInCookie = session.identifier
            if not isinstance(identifierInCookie, str):
                identifierInCookie = identifierInCookie.encode("ascii")
            if not isinstance(cookieName, str):
                cookieName = cookieName.decode("ascii")
            request.addCookie(
                cookieName,
                identifierInCookie,
                max_age=str(self._maxAge),
                domain=self._cookieDomain,
                path=self._cookiePath,
                secure=sentSecurely,
                httpOnly=True,
            )
        if sentSecurely or not request.isSecure():
            # Do not cache the insecure session on the secure request, thanks.
            request.setComponent(ISession, session)
        returnValue(session)