summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2026-07-20 12:05:30 +0300
committerrobot-piglet <[email protected]>2026-07-20 12:32:40 +0300
commit7d359ee1ca06fc0162483a21342845082d270924 (patch)
tree00ea23b44c7f335499f38d854c50465d2d9e6f99
parentf7be20305549bd27325c10f292d252cc574c1cef (diff)
Intermediate changes
commit_hash:dbb5d28367be7cb318f0e373533600e70075b14c
-rw-r--r--contrib/python/scramp/.dist-info/METADATA8
-rw-r--r--contrib/python/scramp/README.md6
-rw-r--r--contrib/python/scramp/scramp/core.py22
-rw-r--r--contrib/python/scramp/ya.make2
-rw-r--r--util/string/strip_ut.cpp18
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"},