From b894dc0a87afc2c2efdfe148cfb670b84a085513 Mon Sep 17 00:00:00 2001 From: Trevor Bergeron Date: Sat, 11 Nov 2023 21:15:48 -0500 Subject: [PATCH] squashme move tests and try mypy stuff --- Makefile | 2 +- pyproject.toml | 11 ++ sopel/coretasks.py | 1 - test/coretasks/test_coretasks_sasl.py | 200 ++++++++++++++++++++++++ test/test_coretasks.py | 210 -------------------------- 5 files changed, 212 insertions(+), 212 deletions(-) diff --git a/Makefile b/Makefile index 35decee8c..a2c10f3c4 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ lint-style: flake8 lint-type: - mypy --check-untyped-defs sopel + mypy sopel .PHONY: test test_norecord test_novcr vcr_rerecord test: diff --git a/pyproject.toml b/pyproject.toml index aeb62999e..9dcac62b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,17 @@ sopel-plugins = "sopel.cli.plugins:main" [project.entry-points.pytest11] pytest-sopel = "sopel.tests.pytest_plugin" +[tool.mypy] +check_untyped_defs = true + +[[tool.mypy.overrides]] +module = 'scramp' +ignore_errors = true + +[[tool.mypy.overrides]] +module = 'asn1crypto' +ignore_errors = true + [tool.pytest.ini_options] # NOTE: sopel/ is included here to include dynamically-generated tests testpaths = ["test", "sopel"] diff --git a/sopel/coretasks.py b/sopel/coretasks.py index dbee7fec0..a5f681216 100644 --- a/sopel/coretasks.py +++ b/sopel/coretasks.py @@ -101,7 +101,6 @@ def _handle_sasl_capability( auth_target = bot.settings.core.auth_target is_required = 'sasl' in (auth_method, server_auth_method) - LOGGER.critical("FOO. BAR!") if not is_required: # not required: we are fine, available or not return plugin.CapabilityNegotiation.DONE diff --git a/test/coretasks/test_coretasks_sasl.py b/test/coretasks/test_coretasks_sasl.py index 39da87b22..91b28dad1 100644 --- a/test/coretasks/test_coretasks_sasl.py +++ b/test/coretasks/test_coretasks_sasl.py @@ -1,14 +1,17 @@ """Test behavior of SASL by ``sopel.coretasks``""" from __future__ import annotations +from base64 import b64decode, b64encode from typing import TYPE_CHECKING import pytest +from scramp import ScramMechanism from sopel import coretasks from sopel.tests import rawlist if TYPE_CHECKING: + from sopel.bot import Sopel from sopel.config import Config from sopel.tests.factories import BotFactory, ConfigFactory @@ -344,3 +347,200 @@ def test_sasl_nak(botfactory: BotFactory, tmpconfig) -> None: 'CAP END', 'QUIT :Error negotiating capabilities.', ) + + +def test_sasl_bad_method(mockbot: Sopel): + """Verify the bot behaves when configured with an unsupported SASL method.""" + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "SCRAM-MD4" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + assert mockbot.backend.message_sent == rawlist( + "CAP REQ :sasl", + "CAP END", + ) + # with pytest.raises(Exception): # ASDF TODO + mockbot.on_message("AUTHENTICATE +") + + +def test_sasl_plain_auth(mockbot: Sopel): + """Verify the bot performs SASL PLAIN auth correctly.""" + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "PLAIN" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + assert mockbot.backend.message_sent == rawlist( + "CAP REQ :sasl", + "AUTHENTICATE PLAIN", + ) + mockbot.on_message("AUTHENTICATE +") + assert ( + len(mockbot.backend.message_sent) == 3 + and mockbot.backend.message_sent[-1] + == rawlist("AUTHENTICATE VGVzdEJvdABUZXN0Qm90AGh1bnRlcjI=")[0] + ) + mockbot.on_message( + "900 TestBot test!test@test TestBot :You are now logged in as TestBot" + ) + mockbot.on_message("903 TestBot :SASL authentication succeeded") + assert ( + len(mockbot.backend.message_sent) == 4 + and mockbot.backend.message_sent[-1] == rawlist("CAP END")[0] + ) + + +def test_sasl_scram_sha_256_auth(mockbot: Sopel): + """Verify the bot performs SASL SCRAM-SHA-256 auth correctly.""" + mech = ScramMechanism() + salt, stored_key, server_key, iter_count = mech.make_auth_info( + "hunter2", iteration_count=5000 + ) + scram_server = mech.make_server( + lambda x: (salt, stored_key, server_key, iter_count) + ) + + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "SCRAM-SHA-256" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + assert mockbot.backend.message_sent == rawlist( + "CAP REQ :sasl", + "AUTHENTICATE SCRAM-SHA-256", + ) + mockbot.on_message("AUTHENTICATE +") + + scram_server.set_client_first( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message( + "AUTHENTICATE " + + b64encode(scram_server.get_server_first().encode("utf-8")).decode("utf-8") + ) + scram_server.set_client_final( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message( + "AUTHENTICATE " + + b64encode(scram_server.get_server_final().encode("utf-8")).decode("utf-8") + ) + assert ( + len(mockbot.backend.message_sent) == 5 + and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE +")[0] + ) + + mockbot.on_message( + "900 TestBot test!test@test TestBot :You are now logged in as TestBot" + ) + mockbot.on_message("903 TestBot :SASL authentication succeeded") + assert ( + len(mockbot.backend.message_sent) == 6 + and mockbot.backend.message_sent[-1] == rawlist("CAP END")[0] + ) + + +def test_sasl_scram_sha_256_nonsense_server_first(mockbot: Sopel): + """Verify the bot handles a nonsense SCRAM-SHA-256 server_first correctly.""" + mech = ScramMechanism() + salt, stored_key, server_key, iter_count = mech.make_auth_info( + "hunter2", iteration_count=5000 + ) + scram_server = mech.make_server( + lambda x: (salt, stored_key, server_key, iter_count) + ) + + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "SCRAM-SHA-256" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + mockbot.on_message("AUTHENTICATE +") + + scram_server.set_client_first( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message("AUTHENTICATE " + b64encode(b"junk").decode("utf-8")) + assert ( + len(mockbot.backend.message_sent) == 4 + and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] + ) + + +def test_sasl_scram_sha_256_nonsense_server_final(mockbot: Sopel): + """Verify the bot handles a nonsense SCRAM-SHA-256 server_final correctly.""" + mech = ScramMechanism() + salt, stored_key, server_key, iter_count = mech.make_auth_info( + "hunter2", iteration_count=5000 + ) + scram_server = mech.make_server( + lambda x: (salt, stored_key, server_key, iter_count) + ) + + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "SCRAM-SHA-256" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + mockbot.on_message("AUTHENTICATE +") + + scram_server.set_client_first( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message( + "AUTHENTICATE " + + b64encode(scram_server.get_server_first().encode("utf-8")).decode("utf-8") + ) + scram_server.set_client_final( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message("AUTHENTICATE " + b64encode(b"junk").decode("utf-8")) + assert ( + len(mockbot.backend.message_sent) == 5 + and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] + ) + + +def test_sasl_scram_sha_256_error_server_first(mockbot: Sopel): + """Verify the bot handles an error SCRAM-SHA-256 server_first correctly.""" + + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "SCRAM-SHA-256" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + mockbot.on_message("AUTHENTICATE +") + + mockbot.on_message("AUTHENTICATE " + b64encode(b"e=some-error").decode("utf-8")) + assert ( + len(mockbot.backend.message_sent) == 4 + and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] + ) + + +def test_sasl_scram_sha_256_error_server_final(mockbot: Sopel): + """Verify the bot handles an error SCRAM-SHA-256 server_final correctly.""" + mech = ScramMechanism() + salt, stored_key, server_key, iter_count = mech.make_auth_info( + "hunter2", iteration_count=5000 + ) + scram_server = mech.make_server( + lambda x: (salt, stored_key, server_key, iter_count) + ) + + mockbot.settings.core.auth_method = "sasl" + mockbot.settings.core.auth_target = "SCRAM-SHA-256" + mockbot.on_message("CAP * LS :sasl") + mockbot.on_message("CAP TestBot ACK :sasl") + mockbot.on_message("AUTHENTICATE +") + + scram_server.set_client_first( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message( + "AUTHENTICATE " + + b64encode(scram_server.get_server_first().encode("utf-8")).decode("utf-8") + ) + scram_server.set_client_final( + b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") + ) + mockbot.on_message("AUTHENTICATE " + b64encode(b"e=some-error").decode("utf-8")) + assert ( + len(mockbot.backend.message_sent) == 5 + and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] + ) diff --git a/test/test_coretasks.py b/test/test_coretasks.py index 8d0efae40..0680309fb 100644 --- a/test/test_coretasks.py +++ b/test/test_coretasks.py @@ -1,13 +1,10 @@ """coretasks.py tests""" from __future__ import annotations -from base64 import b64decode, b64encode from datetime import datetime, timezone import logging -from typing import TYPE_CHECKING import pytest -from scramp import ScramMechanism from sopel import coretasks from sopel.irc import isupport @@ -15,9 +12,6 @@ from sopel.tests import rawlist from sopel.tools import Identifier -if TYPE_CHECKING: - from sopel.bot import Sopel - TMP_CONFIG = """ [core] @@ -509,210 +503,6 @@ def test_handle_rpl_myinfo(mockbot): assert mockbot.myinfo.version == 'example-1.2.3' -def test_sasl_plain_token_generation(): - """Make sure SASL PLAIN tokens match the expected format.""" - assert ( - coretasks._make_sasl_plain_token('sopel', 'sasliscool') == - 'sopel\x00sopel\x00sasliscool') - - -def test_sasl_bad_method(mockbot: Sopel): - """Verify the bot behaves when configured with an unsupported SASL method.""" - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "SCRAM-MD4" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - assert mockbot.backend.message_sent == rawlist( - "CAP REQ :sasl", - "CAP END", - ) - #with pytest.raises(Exception): - mockbot.on_message("AUTHENTICATE +") - - -def test_sasl_plain_auth(mockbot: Sopel): - """Verify the bot performs SASL PLAIN auth correctly.""" - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "PLAIN" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - assert mockbot.backend.message_sent == rawlist( - "CAP REQ :sasl", - "AUTHENTICATE PLAIN", - ) - mockbot.on_message("AUTHENTICATE +") - assert ( - len(mockbot.backend.message_sent) == 3 - and mockbot.backend.message_sent[-1] - == rawlist("AUTHENTICATE VGVzdEJvdABUZXN0Qm90AGh1bnRlcjI=")[0] - ) - mockbot.on_message( - "900 TestBot test!test@test TestBot :You are now logged in as TestBot" - ) - mockbot.on_message("903 TestBot :SASL authentication succeeded") - assert ( - len(mockbot.backend.message_sent) == 4 - and mockbot.backend.message_sent[-1] == rawlist("CAP END")[0] - ) - - -def test_sasl_scram_sha_256_auth(mockbot: Sopel): - """Verify the bot performs SASL SCRAM-SHA-256 auth correctly.""" - mech = ScramMechanism() - salt, stored_key, server_key, iter_count = mech.make_auth_info( - "hunter2", iteration_count=5000 - ) - scram_server = mech.make_server( - lambda x: (salt, stored_key, server_key, iter_count) - ) - - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "SCRAM-SHA-256" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - assert mockbot.backend.message_sent == rawlist( - "CAP REQ :sasl", - "AUTHENTICATE SCRAM-SHA-256", - ) - mockbot.on_message("AUTHENTICATE +") - - scram_server.set_client_first( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message( - "AUTHENTICATE " - + b64encode(scram_server.get_server_first().encode("utf-8")).decode("utf-8") - ) - scram_server.set_client_final( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message( - "AUTHENTICATE " - + b64encode(scram_server.get_server_final().encode("utf-8")).decode("utf-8") - ) - assert ( - len(mockbot.backend.message_sent) == 5 - and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE +")[0] - ) - - mockbot.on_message( - "900 TestBot test!test@test TestBot :You are now logged in as TestBot" - ) - mockbot.on_message("903 TestBot :SASL authentication succeeded") - assert ( - len(mockbot.backend.message_sent) == 6 - and mockbot.backend.message_sent[-1] == rawlist("CAP END")[0] - ) - - -def test_sasl_scram_sha_256_nonsense_server_first(mockbot: Sopel): - """Verify the bot handles a nonsense SCRAM-SHA-256 server_first correctly.""" - mech = ScramMechanism() - salt, stored_key, server_key, iter_count = mech.make_auth_info( - "hunter2", iteration_count=5000 - ) - scram_server = mech.make_server( - lambda x: (salt, stored_key, server_key, iter_count) - ) - - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "SCRAM-SHA-256" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - mockbot.on_message("AUTHENTICATE +") - - scram_server.set_client_first( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message("AUTHENTICATE " + b64encode(b"junk").decode("utf-8")) - assert ( - len(mockbot.backend.message_sent) == 4 - and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] - ) - - -def test_sasl_scram_sha_256_nonsense_server_final(mockbot: Sopel): - """Verify the bot handles a nonsense SCRAM-SHA-256 server_final correctly.""" - mech = ScramMechanism() - salt, stored_key, server_key, iter_count = mech.make_auth_info( - "hunter2", iteration_count=5000 - ) - scram_server = mech.make_server( - lambda x: (salt, stored_key, server_key, iter_count) - ) - - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "SCRAM-SHA-256" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - mockbot.on_message("AUTHENTICATE +") - - scram_server.set_client_first( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message( - "AUTHENTICATE " - + b64encode(scram_server.get_server_first().encode("utf-8")).decode("utf-8") - ) - scram_server.set_client_final( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message("AUTHENTICATE " + b64encode(b"junk").decode("utf-8")) - assert ( - len(mockbot.backend.message_sent) == 5 - and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] - ) - - -def test_sasl_scram_sha_256_error_server_first(mockbot: Sopel): - """Verify the bot handles an error SCRAM-SHA-256 server_first correctly.""" - - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "SCRAM-SHA-256" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - mockbot.on_message("AUTHENTICATE +") - - mockbot.on_message("AUTHENTICATE " + b64encode(b"e=some-error").decode("utf-8")) - assert ( - len(mockbot.backend.message_sent) == 4 - and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] - ) - - -def test_sasl_scram_sha_256_error_server_final(mockbot: Sopel): - """Verify the bot handles an error SCRAM-SHA-256 server_final correctly.""" - mech = ScramMechanism() - salt, stored_key, server_key, iter_count = mech.make_auth_info( - "hunter2", iteration_count=5000 - ) - scram_server = mech.make_server( - lambda x: (salt, stored_key, server_key, iter_count) - ) - - mockbot.settings.core.auth_method = "sasl" - mockbot.settings.core.auth_target = "SCRAM-SHA-256" - mockbot.on_message("CAP * LS :sasl") - mockbot.on_message("CAP TestBot ACK :sasl") - mockbot.on_message("AUTHENTICATE +") - - scram_server.set_client_first( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message( - "AUTHENTICATE " - + b64encode(scram_server.get_server_first().encode("utf-8")).decode("utf-8") - ) - scram_server.set_client_final( - b64decode(mockbot.backend.message_sent[-1].split(b" ")[-1]).decode("utf-8") - ) - mockbot.on_message("AUTHENTICATE " + b64encode(b"e=some-error").decode("utf-8")) - assert ( - len(mockbot.backend.message_sent) == 5 - and mockbot.backend.message_sent[-1] == rawlist("AUTHENTICATE *")[0] - ) - - def test_recv_chghost(mockbot, ircfactory): """Ensure that CHGHOST messages are correctly handled.""" irc = ircfactory(mockbot)