Skip to content

Commit

Permalink
additional test spot-checking
Browse files Browse the repository at this point in the history
  • Loading branch information
glyph committed Feb 14, 2023
1 parent 554f874 commit 7412c5b
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 21 deletions.
8 changes: 5 additions & 3 deletions src/twisted/conch/test/test_tap.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

from twisted.application.internet import StreamServerEndpointService
from twisted.cred import error
from twisted.cred.checkers import ICredentialsChecker
from twisted.cred.credentials import ISSHPrivateKey, IUsernamePassword, UsernamePassword
from twisted.internet.defer import Deferred
from twisted.python.reflect import requireModule
from twisted.trial.unittest import TestCase

Expand Down Expand Up @@ -119,18 +121,18 @@ def test_authFailure(self):
checker.requestAvatarId(invalid), error.UnauthorizedLogin
)

def test_authSuccess(self):
def test_authSuccess(self) -> Deferred[None]:
"""
The checker created by the C{--auth} command-line option returns a
L{Deferred} that returns the avatar id when presented with credentials
that are known to that checker.
"""
self.options.parseOptions(["--auth", "file:" + self.filename])
checker = self.options["credCheckers"][-1]
checker: ICredentialsChecker = self.options["credCheckers"][-1]
correct = UsernamePassword(*self.usernamePassword)
d = checker.requestAvatarId(correct)

def checkSuccess(username):
def checkSuccess(username: bytes) -> None:
self.assertEqual(username, correct.username)

return d.addCallback(checkSuccess)
Expand Down
37 changes: 19 additions & 18 deletions src/twisted/cred/checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,28 @@


import os
from typing import Any, Tuple, Union

from zope.interface import Attribute, Interface, implementer

from twisted.cred import credentials, error
from twisted.internet import defer
from twisted.internet.defer import Deferred
from twisted.logger import Logger
from twisted.python import failure

# A note on anonymity - We do not want None as the value for anonymous
# because it is too easy to accidentally return it. We do not want the
# empty string, because it is too easy to mistype a password file. For
# example, an .htpasswd file may contain the lines: ['hello:asdf',
# 'world:asdf', 'goodbye', ':world']. This misconfiguration will have an
# ill effect in any case, but accidentally granting anonymous access is a
# worse failure mode than simply granting access to an untypeable
# username. We do not want an instance of 'object', because that would
# create potential problems with persistence.

ANONYMOUS: Tuple[()] = ()


class ICredentialsChecker(Interface):
"""
Expand All @@ -29,35 +43,22 @@ class ICredentialsChecker(Interface):
"may check."
)

def requestAvatarId(credentials):
def requestAvatarId(credentials: Any) -> Deferred[Union[bytes, Tuple[()]]]:
"""
Validate credentials and produce an avatar ID.
@param credentials: something which implements one of the interfaces in
C{credentialInterfaces}.
C{credentialInterfaces}.
@return: a L{Deferred} which will fire with a L{bytes} that identifies
an avatar, an empty tuple to specify an authenticated anonymous user
(provided as L{twisted.cred.checkers.ANONYMOUS}) or fail with
L{UnauthorizedLogin}. Alternatively, return the result itself.
an avatar, an empty tuple to specify an authenticated anonymous
user (provided as L{twisted.cred.checkers.ANONYMOUS}) or fail with
L{UnauthorizedLogin}. Alternatively, return the result itself.
@see: L{twisted.cred.credentials}
"""


# A note on anonymity - We do not want None as the value for anonymous
# because it is too easy to accidentally return it. We do not want the
# empty string, because it is too easy to mistype a password file. For
# example, an .htpasswd file may contain the lines: ['hello:asdf',
# 'world:asdf', 'goodbye', ':world']. This misconfiguration will have an
# ill effect in any case, but accidentally granting anonymous access is a
# worse failure mode than simply granting access to an untypeable
# username. We do not want an instance of 'object', because that would
# create potential problems with persistence.

ANONYMOUS = ()


@implementer(ICredentialsChecker)
class AllowAnonymousAccess:
"""
Expand Down

0 comments on commit 7412c5b

Please sign in to comment.