From 348790d3db5228b7c26b54556a22fe420449222c Mon Sep 17 00:00:00 2001 From: Terren <11605395+terreng@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:36:22 -0400 Subject: [PATCH] Disallow control characters in http basic auth username or password --- index.html | 4 +++- lang.js | 8 ++++++-- main.js | 32 +++++++++++++++++++++++++++++++- website/src/docs/options.md | 4 ++-- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 573e25a..ece5b8b 100644 --- a/index.html +++ b/index.html @@ -393,9 +393,11 @@
:
) character.",
- "httpAuthUsername_invalid": "Username cannot contain :
",
+ "option_httpAuthUsername_description": "Username for HTTP Basic authentication. Cannot contain a colon (:
) character or control characters.",
+ "httpAuthUsername_invalid": "Username cannot contain :
or control characters",
+ "httpAuthPassword_invalid": "Password cannot contain control characters",
"option_httpAuthPassword": "HTTP Basic auth password",
"option_httpAuthPassword_description": "Password for HTTP Basic authentication. Stored in plain text.",
"option_ipThrottling": "Maximum connections per IP address",
@@ -257,6 +258,7 @@ lang = {
"option_httpAuthUsername": "Имя пользователя HTTP Basic авторизации",
"option_httpAuthUsername_description": "Имя пользователя для HTTP Basic авторизации. Не может содержать двоеточия (:
).",
"httpAuthUsername_invalid": "Имя пользователя не может содержать :
",
+ "httpAuthPassword_invalid": "Password cannot contain control characters",
"option_httpAuthPassword": "Пароль HTTP Basic авторизации",
"option_httpAuthPassword_description": "Пароль для HTTP Basic авторизации. Хранится в чистом виде.",
"option_ipThrottling": "Предел соединений по IP адресу",
@@ -394,6 +396,7 @@ lang = {
"option_httpAuthUsername": "HTTP基本身份验证用户名",
"option_httpAuthUsername_description": "HTTP基本身份验证的用户名。不能包含冒号(:
)字符。",
"httpAuthUsername_invalid": "用户名不能包含 :
",
+ "httpAuthPassword_invalid": "Password cannot contain control characters",
"option_httpAuthPassword": "HTTP基本身份验证密码",
"option_httpAuthPassword_description": "HTTP基本身份验证的密码。以纯文本形式存储。",
"option_ipThrottling": "每个IP地址的最大连接数",
@@ -531,6 +534,7 @@ lang = {
"option_httpAuthUsername": "ベーシック認証ユーザー名",
"option_httpAuthUsername_description": "ベーシック認証のユーザー名。:
を含んでいてはいけません。",
"httpAuthUsername_invalid": "ユーザー名に:
を含めることはできません。",
+ "httpAuthPassword_invalid": "Password cannot contain control characters",
"option_httpAuthPassword": "ベーシック認証パスワード",
"option_httpAuthPassword_description": "ベーシック認証のパスワード。平文で保存されます。",
"option_ipThrottling": "IPアドレスごとの最大接続数",
diff --git a/main.js b/main.js
index e27213f..9a4f967 100644
--- a/main.js
+++ b/main.js
@@ -407,6 +407,7 @@ function addServer(editindex) {
document.querySelector("#httpAuthUsername").value = config.servers[editindex].httpAuthUsername || "";
httpAuthUsernameChange();
document.querySelector("#httpAuthPassword").value = config.servers[editindex].httpAuthPassword || "";
+ httpAuthPasswordChange();
document.querySelector("#ipThrottling").value = config.servers[editindex].ipThrottling || 10;
ipLimitChange();
@@ -457,6 +458,7 @@ function addServer(editindex) {
document.querySelector("#httpAuthUsername").value = "";
httpAuthUsernameChange();
document.querySelector("#httpAuthPassword").value = "";
+ httpAuthPasswordChange();
document.querySelector("#ipThrottling").value = 10;
ipLimitChange();
@@ -505,6 +507,17 @@ function submitAddServer() {
return;
}
+ if (!httpAuthPasswordValid()) {
+ document.querySelector("#httpAuthPassword").parentElement.nextElementSibling.style.display = "block";
+ if (!document.querySelector("#security_section").classList.contains("section_visible")) {
+ toggleSection(document.querySelector("#security_section"))
+ setTimeout(()=>document.querySelector("#httpAuthPassword").previousElementSibling.scrollIntoView({behavior: "smooth"}), 210);
+ } else {
+ document.querySelector("#httpAuthPassword").previousElementSibling.scrollIntoView({behavior: "smooth"});
+ }
+ return;
+ }
+
if (!ipLimitValid()) {
document.querySelector("#ipThrottling").parentElement.nextElementSibling.style.display = "block";
if (!document.querySelector("#security_section").classList.contains("section_visible")) {
@@ -704,8 +717,13 @@ function ipLimitChange() {
}
}
+function stringContainsControlCharacters(str) {
+ const controlCharacterPattern = /[\x00-\x1F\x7F]/;
+ return controlCharacterPattern.test(str);
+ }
+
function httpAuthUsernameValid() {
- return document.querySelector("#httpAuthUsername").value.indexOf(":") === -1;
+ return document.querySelector("#httpAuthUsername").value.indexOf(":") === -1 && !stringContainsControlCharacters(document.querySelector("#httpAuthUsername").value);
}
function httpAuthUsernameChange() {
@@ -716,6 +734,18 @@ function httpAuthUsernameChange() {
}
}
+function httpAuthPasswordValid() {
+ return !stringContainsControlCharacters(document.querySelector("#httpAuthPassword").value);
+}
+
+function httpAuthPasswordChange() {
+ if (httpAuthPasswordValid()) {
+ document.querySelector("#httpAuthPassword").parentElement.nextElementSibling.style.display = "none";
+ } else {
+ document.querySelector("#httpAuthPassword").parentElement.nextElementSibling.style.display = "block";
+ }
+}
+
function updateCurrentPath() {
if (current_path) {
document.querySelector("#path > div > span").innerText = current_path;
diff --git a/website/src/docs/options.md b/website/src/docs/options.md
index cedf613..7a7ba95 100755
--- a/website/src/docs/options.md
+++ b/website/src/docs/options.md
@@ -261,7 +261,7 @@ Require authentication using the HTTP Basic authentication protocol. Specify a u
- Type: string
- Default: -
-Username for HTTP Basic authentication. Cannot contain a colon (`:`) character.
+Username for HTTP Basic authentication. Cannot contain a colon (`:`) character or control characters.
### HTTP Basic auth password
@@ -269,7 +269,7 @@ Username for HTTP Basic authentication. Cannot contain a colon (`:`) character.
- Type: string
- Default: -
-Password for HTTP Basic authentication. Stored in plain text.
+Password for HTTP Basic authentication. Stored in plain text. Cannot contain control characters.
### Maximum connections per IP address