diff options
| author | robot-piglet <[email protected]> | 2026-07-20 12:05:30 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2026-07-20 12:32:40 +0300 |
| commit | 7d359ee1ca06fc0162483a21342845082d270924 (patch) | |
| tree | 00ea23b44c7f335499f38d854c50465d2d9e6f99 | |
| parent | f7be20305549bd27325c10f292d252cc574c1cef (diff) | |
Intermediate changes
commit_hash:dbb5d28367be7cb318f0e373533600e70075b14c
| -rw-r--r-- | contrib/python/scramp/.dist-info/METADATA | 8 | ||||
| -rw-r--r-- | contrib/python/scramp/README.md | 6 | ||||
| -rw-r--r-- | contrib/python/scramp/scramp/core.py | 22 | ||||
| -rw-r--r-- | contrib/python/scramp/ya.make | 2 | ||||
| -rw-r--r-- | util/string/strip_ut.cpp | 18 |
5 files changed, 43 insertions, 13 deletions
diff --git a/contrib/python/scramp/.dist-info/METADATA b/contrib/python/scramp/.dist-info/METADATA index 3551c560d9d..354f0631bb7 100644 --- a/contrib/python/scramp/.dist-info/METADATA +++ b/contrib/python/scramp/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: scramp -Version: 1.4.11 +Version: 1.4.12 Summary: An implementation of the SCRAM protocol. Project-URL: Homepage, https://codeberg.org/tlocke/scramp Author: The Contributors @@ -54,6 +54,7 @@ Scramp supports the following mechanisms: * [OpenSSF Scorecard](#openssf-scorecard) * [Doing A Release Of Scramp](#doing-a-release-of-scramp) * [Release Notes](#release-notes) + * [Version 1.4.12, 2026-07-05](#version-1412-2026-07-05) * [Version 1.4.11, 2026-07-04](#version-1411-2026-07-04) * [Version 1.4.10, 2026-06-27](#version-1410-2026-06-27) * [Version 1.4.9, 2026-06-19](#version-149-2026-06-19) @@ -386,6 +387,11 @@ Run `tox` to make sure all tests pass, then update the release notes, then do: ## Release Notes +### Version 1.4.12, 2026-07-05 + +- Check for invalid escape chars in username. + + ### Version 1.4.11, 2026-07-04 - Make sure all errors detected by the server get returned to the client as valid errors. diff --git a/contrib/python/scramp/README.md b/contrib/python/scramp/README.md index 63260c0f265..abd5f1ebf18 100644 --- a/contrib/python/scramp/README.md +++ b/contrib/python/scramp/README.md @@ -33,6 +33,7 @@ Scramp supports the following mechanisms: * [OpenSSF Scorecard](#openssf-scorecard) * [Doing A Release Of Scramp](#doing-a-release-of-scramp) * [Release Notes](#release-notes) + * [Version 1.4.12, 2026-07-05](#version-1412-2026-07-05) * [Version 1.4.11, 2026-07-04](#version-1411-2026-07-04) * [Version 1.4.10, 2026-06-27](#version-1410-2026-06-27) * [Version 1.4.9, 2026-06-19](#version-149-2026-06-19) @@ -365,6 +366,11 @@ Run `tox` to make sure all tests pass, then update the release notes, then do: ## Release Notes +### Version 1.4.12, 2026-07-05 + +- Check for invalid escape chars in username. + + ### Version 1.4.11, 2026-07-04 - Make sure all errors detected by the server get returned to the client as valid errors. diff --git a/contrib/python/scramp/scramp/core.py b/contrib/python/scramp/scramp/core.py index ba53424634f..3518975852f 100644 --- a/contrib/python/scramp/scramp/core.py +++ b/contrib/python/scramp/scramp/core.py @@ -445,13 +445,31 @@ def _parse_message(msg, desc, *expected_attr_sets): ) +ESCAPE_EQUALS = "=3D" +ESCAPE_COMMA = "=2C" + + +def _username_escape(username): + return username.replace("=", ESCAPE_EQUALS).replace(",", ESCAPE_COMMA) + + +def _username_unescape(username): + for i in (i for i, c in enumerate(username) if c == "="): + if username[i : i + 3] not in (ESCAPE_EQUALS, ESCAPE_COMMA): + raise ScramException( + "An '=' in a username must be followed by '3D', or '2C'", + SERVER_ERROR_INVALID_USERNAME_ENCODING, + ) + return username.replace(ESCAPE_COMMA, ",").replace(ESCAPE_EQUALS, "=") + + def _get_client_first(username, c_nonce, channel_binding, use_binding): try: prepped_u = saslprep(username) except ScramException as e: raise ScramException(e.args[0], SERVER_ERROR_INVALID_USERNAME_ENCODING) - u = prepped_u.replace("=", "=3D").replace(",", "=2C") + u = _username_escape(prepped_u) bare = ",".join((f"n={u}", f"r={c_nonce}")) _, gs2_header = _make_gs2_header(channel_binding, use_binding) @@ -538,7 +556,7 @@ def _set_client_first(client_first, s_nonce, channel_binding, use_binding): c_nonce = msg["r"] nonce = c_nonce + s_nonce - user = msg["n"].replace("=2C", ",").replace("=3D", "=") + user = _username_unescape(msg["n"]) return nonce, user, client_first_bare, upgrade_mechanism diff --git a/contrib/python/scramp/ya.make b/contrib/python/scramp/ya.make index cf5785c2ea7..5b612dfca89 100644 --- a/contrib/python/scramp/ya.make +++ b/contrib/python/scramp/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(1.4.11) +VERSION(1.4.12) LICENSE(MIT-0) diff --git a/util/string/strip_ut.cpp b/util/string/strip_ut.cpp index 1d47e21e23c..7236ca2ebf8 100644 --- a/util/string/strip_ut.cpp +++ b/util/string/strip_ut.cpp @@ -8,19 +8,19 @@ Y_UNIT_TEST_SUITE(TStripStringTest) { Y_UNIT_TEST(TestConstexprStrip) { - static constexpr std::string_view stripped = StripString<std::string_view>(" \n\t abc def \r\n "); + constexpr std::string_view stripped = StripString<std::string_view>(" \n\t abc def \r\n "); static_assert(stripped == "abc def"); - static constexpr std::string_view strippedLeft = StripStringLeft(std::string_view(" \n abc \n ")); + constexpr std::string_view strippedLeft = StripStringLeft(std::string_view(" \n abc \n ")); static_assert(strippedLeft == "abc \n "); - static constexpr std::string_view strippedRight = StripStringRight(std::string_view(" \n abc \n ")); + constexpr std::string_view strippedRight = StripStringRight(std::string_view(" \n abc \n ")); static_assert(strippedRight == " \n abc"); - static constexpr std::string_view empty = StripString<std::string_view>(" \n\t\r "); + constexpr std::string_view empty = StripString<std::string_view>(" \n\t\r "); static_assert(empty.empty()); - static constexpr std::string_view unchanged = StripString<std::string_view>("abc"); + constexpr std::string_view unchanged = StripString<std::string_view>("abc"); static_assert(unchanged == "abc"); UNIT_ASSERT_VALUES_EQUAL(stripped, "abc def"); @@ -29,13 +29,13 @@ Y_UNIT_TEST_SUITE(TStripStringTest) { } Y_UNIT_TEST(TestConstexprCustomStrip) { - static constexpr std::string_view stripped = StripString(std::string_view("//abc//"), EqualsStripAdapter('/')); + constexpr std::string_view stripped = StripString(std::string_view("//abc//"), EqualsStripAdapter('/')); static_assert(stripped == "abc"); - static constexpr std::string_view strippedLeft = StripStringLeft(std::string_view("//abc//"), EqualsStripAdapter('/')); + constexpr std::string_view strippedLeft = StripStringLeft(std::string_view("//abc//"), EqualsStripAdapter('/')); static_assert(strippedLeft == "abc//"); - static constexpr std::string_view strippedRight = StripStringRight(std::string_view("//abc//"), EqualsStripAdapter('/')); + constexpr std::string_view strippedRight = StripStringRight(std::string_view("//abc//"), EqualsStripAdapter('/')); static_assert(strippedRight == "//abc"); UNIT_ASSERT_VALUES_EQUAL(stripped, "abc"); @@ -47,7 +47,7 @@ Y_UNIT_TEST_SUITE(TStripStringTest) { TStringBuf StripRightRes; TStringBuf StripRes; }; - static constexpr TStripTest StripTests[] = { + constexpr TStripTest StripTests[] = { {" 012 ", "012 ", " 012", "012"}, {" 012", "012", " 012", "012"}, {"012\t\t", "012\t\t", "012", "012"}, |
