horazont / aiosasl Goto Github PK
View Code? Open in Web Editor NEWPure-python, protocol-agnostic SASL implementation for asyncio
License: GNU Lesser General Public License v3.0
Pure-python, protocol-agnostic SASL implementation for asyncio
License: GNU Lesser General Public License v3.0
Reported by @jomag at aioxmpp.
Following the removal of SCRAM-SHA-512(-PLUS), I request you the addition and there is SCRAM-SHA3-512(-PLUS) in the same time.
SCRAM-SHA-512(-PLUS):
SCRAM-SHA3-512(-PLUS):
A lot of projects have already SCRAM-SHA-512: https://www.google.com/search?q=SCRAM-SHA-512
Unspecified SASL mechanisms were removed in #6, but are still listed on https://pypi.org/project/aiosasl/.
RFC 5802 §5.1 states (emphasis mine):
Before sending the username to the server, the client SHOULD prepare the username using the "SASLprep" profile [RFC4013] of the "stringprep" algorithm [RFC3454] treating it as a query string (i.e., unassigned Unicode code points are allowed). If the preparation of the username fails or results in an empty string, the client SHOULD abort the authentication exchange.
We currently do not allow unassigned codepoints for the SCRAM username.
Both python-aioxmpp
and python-aioxmpp-git
packages in the AUR are broken because python-aiosasl can not be installed.
On the installation you get the following error:
==> Beginne check()...
Traceback (most recent call last):
File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/home/daniel/.local/lib/python3.10/site-packages/nose/__main__.py", line 8, in <module>
run_exit()
File "/home/daniel/.local/lib/python3.10/site-packages/nose/core.py", line 118, in __init__
unittest.TestProgram.__init__(
File "/usr/lib/python3.10/unittest/main.py", line 100, in __init__
self.parseArgs(argv)
File "/home/daniel/.local/lib/python3.10/site-packages/nose/core.py", line 179, in parseArgs
self.createTests()
File "/home/daniel/.local/lib/python3.10/site-packages/nose/core.py", line 193, in createTests
self.test = self.testLoader.loadTestsFromNames(self.testNames)
File "/home/daniel/.local/lib/python3.10/site-packages/nose/loader.py", line 481, in loadTestsFromNames
return unittest.TestLoader.loadTestsFromNames(self, names, module)
File "/usr/lib/python3.10/unittest/loader.py", line 220, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python3.10/unittest/loader.py", line 220, in <listcomp>
suites = [self.loadTestsFromName(name, module) for name in names]
File "/home/daniel/.local/lib/python3.10/site-packages/nose/loader.py", line 454, in loadTestsFromName
return LazySuite(
File "/home/daniel/.local/lib/python3.10/site-packages/nose/suite.py", line 53, in __init__
super(LazySuite, self).__init__()
File "/usr/lib/python3.10/unittest/suite.py", line 22, in __init__
self._tests = []
File "/home/daniel/.local/lib/python3.10/site-packages/nose/suite.py", line 106, in _set_tests
if isinstance(tests, collections.Callable) and not is_suite:
AttributeError: module 'collections' has no attribute 'Callable'
==> FEHLER: Ein Fehler geschah in check().
Breche ab...
-> Fehler beim Ausführen: python-aiosasl
The SASL SCRAM family registry as specified in RFC 7677 § 5.2 provides a minimum-iteration-count parameter.
We should include that parameter in our code and offer an option to enforce that parameter (enabled by default).
(A reason to turn this off could be if the alternative is fallback to PLAIN.)
pbkdf2 can take a while. No need to block other I/O or UIs on it.
Tests work Python 3.11 but not on Python 3.12.
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-8.1.1, pluggy-1.4.0
rootdir: /build/source
collected 84 items
tests/test_aiosasl.py .....FFF......F.....FFFF.............F....FF.F.... [ 59%]
F....F.... [ 71%]
tests/test_channel_binding_methods.py ......... [ 82%]
tests/test_stringprep.py .............. [ 98%]
tests/test_unicode_version.py . [100%]
=================================== FAILURES ===================================
_______________ TestSASLStateMachine.test_reject_double_initiate _______________
self = <test_aiosasl.TestSASLStateMachine testMethod=test_reject_double_initiate>
def test_reject_double_initiate(self):
run_coroutine(self.sm.initiate("foo", b"bar"))
> with self.assertRaisesRegexp(RuntimeError,
"has already been called"):
E AttributeError: 'TestSASLStateMachine' object has no attribute 'assertRaisesRegexp'. Did you mean: 'assertRaisesRegex'?
tests/test_aiosasl.py:184: AttributeError
_________ TestSASLStateMachine.test_reject_double_initiate_after_error _________
self = <test_aiosasl.TestSASLStateMachine testMethod=test_reject_double_initiate_after_error>
def test_reject_double_initiate_after_error(self):
opaque_error = object()
self.intf.initiate.side_effect = aiosasl.SASLFailure(
opaque_error
[...]
'assertRaisesRegexp'. D...
FAILED tests/test_aiosasl.py::TestSCRAM::test_reject_protocol_violation_2 - AttributeError: 'TestSCRAM' object has no attribute 'assertRaisesRegexp'. D...
FAILED tests/test_aiosasl.py::TestSCRAM::test_too_low_iteration_count - AttributeError: 'TestSCRAM' object has no attribute 'assertRaisesRegexp'. D...
FAILED tests/test_aiosasl.py::TestSCRAMPLUS::test_incorrect_nonce - AttributeError: 'TestSCRAMPLUS' object has no attribute 'assertRaisesRegexp...
FAILED tests/test_aiosasl.py::TestSCRAMPLUS::test_reject_protocol_violation - AttributeError: 'TestSCRAMPLUS' object has no attribute 'assertRaisesRegexp...
=================== 14 failed, 70 passed, 1 warning in 0.41s ===================
If SCRAM authentication failed, the server final message may be of the form e=<error_code>
, however, the payload of a fail
message is simply ignored. (side note: an invalid payload on a success
reply causes a KeyError
exception which may not be what we want). If the error message is sent by the server it may contain useful information for the user (such as the use of an unsupported channel binding mode).
The following SCRAM variants are supported by aiosasl, but not specified in any IETF document:
The only SCRAM-SHA-* specifications are: RFC7677 (-256) and RFC5802 (-1). Of those, RFC 7677 explicitly states:
Note: Members of this family MUST be explicitly registered using the "IETF Review" [RFC5226] registration procedure. Reviews MUST be requested on the KITTEN mailing list [email protected] (or a successor designated by the responsible Security Area Director).
[…]
Note to future SASL SCRAM mechanism designers: each new SASL SCRAM mechanism MUST be explicitly registered with IANA and MUST comply with the SCRAM-mechanism naming convention defined in Section 4 of [RFC5802].
So while the mechanisms outlined above adhere to the naming convention, they’re not registered with the IANA at this point in time.
This is thus a violation of the specification/unauthorized extension of the registered set of algorithms for no good reason. We should drop them to stay within the specification.
In addition, an argument can be made that it’s not our place to invent new SCRAM variants without review.
https://github.com/horazont/aiosasl/blob/devel/README.rst;
Maybe good to have in order...
Linked to:
As someone looking for SASL implementation I need to know if a library implements client, server or both.
I did not find it. I gather from source code and API that they would only allow implementing a client. I would have expected to see this information in the project description, README and documentation.
The SASL layer in ManageSieve allows variation as to how client initial data and server final responses are encoded on the protocol layer. The variants for final server responses are (with the example from RFC 5804 edited to show only the variation relevant for this issue):
C: Authenticate "DIGEST-MD5"
S: "cmVhbG09ImVsd29vZC5pbm5vc29mdC5leGFtcGxlLmNvbSIsbm9uY2U9Ik
9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGFsZ29yaXRobT1tZDUtc2Vz
cyxjaGFyc2V0PXV0Zi04"
C: "Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2
QuaW5ub3NvZnQuZXhhbXBsZS5jb20iLG5vbmNlPSJPQTZNRzl0RVFHbTJo
aCIsbmM9MDAwMDAwMDEsY25vbmNlPSJPQTZNSFhoNlZxVHJSayIsZGlnZX
N0LXVyaT0ic2lldmUvZWx3b29kLmlubm9zb2Z0LmV4YW1wbGUuY29tIixy
ZXNwb25zZT1kMzg4ZGFkOTBkNGJiZDc2MGExNTIzMjFmMjE0M2FmNyxxb3
A9YXV0aA=="
S: OK (SASL "cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZ
mZmZA==")
or equivalently
C: Authenticate "DIGEST-MD5"
S: "cmVhbG09ImVsd29vZC5pbm5vc29mdC5leGFtcGxlLmNvbSIsbm9uY2U9Ik
9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGFsZ29yaXRobT1tZDUtc2Vz
cyxjaGFyc2V0PXV0Zi04"
C: "Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2
QuaW5ub3NvZnQuZXhhbXBsZS5jb20iLG5vbmNlPSJPQTZNRzl0RVFHbTJo
aCIsbmM9MDAwMDAwMDEsY25vbmNlPSJPQTZNSFhoNlZxVHJSayIsZGlnZX
N0LXVyaT0ic2lldmUvZWx3b29kLmlubm9zb2Z0LmV4YW1wbGUuY29tIixy
ZXNwb25zZT1kMzg4ZGFkOTBkNGJiZDc2MGExNTIzMjFmMjE0M2FmNyxxb3
A9YXV0aA=="
S: "cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA=="
C: ""
S: OK
That is, the final response by the server may be encoded either as a further challenge (which expects an empty response) or in the status code of the success message. (Similarly, initial data sent by the client is equivalent to the response to an empty query; this, however, poses no problem, since we control the first message and can choose to always send client initial data were the SASL mechanism allows it).
It is impossible for a SASLInterface
implementation for the protocol to distinguish these cases correctly, without intricate knowledge of the SASL mechanism that is run. I believe that one solution for this problem is to make the SASLMechanism
implementations themselves robust against this kind of variation. The preferred solution would be to adapt the protocol used by aiosasl internally to communicate with the mechanisms (by not allowing payloads on success
messages and doing the packing/unpacking on the SASLInterface
layer) and let the mechanisms speak the expanded form of the protocol (which is then unpacked from the wire form by the SASLInterface
if necessary).
In PLAIN, preparing the password string (and all the other stuff) is the server’s job. This is, according to RFC 4616, to allow interop with other systems (RFC 4616 § 2, emphasis mine):
Upon receipt of the message, the server will verify the presented (in the message) authentication identity (authcid) and password (passwd) with the system authentication database, and it will verify that the authentication credentials permit the client to act as the (presented or derived) authorization identity (authzid). If both steps succeed, the user is authenticated.
The presented authentication identity and password strings, as well as the database authentication identity and password strings, are to be prepared before being used in the verification process. The [SASLPrep] profile of the [StringPrep] algorithm is the RECOMMENDED preparation algorithm. The SASLprep preparation algorithm is recommended to improve the likelihood that comparisons behave in an expected manner. The SASLprep preparation algorithm is not mandatory so as to allow the server to employ other preparation algorithms (including none) when appropriate. For instance, use of a different preparation algorithm may be necessary for the server to interoperate with an external system.
Thus, all prepping needs to be removed from PLAIN.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.