Fix race conditions

This commit is contained in:
olcxja 2026-06-02 11:58:18 +02:00
commit b24b36adec
7 changed files with 219 additions and 130 deletions

View file

@ -86,7 +86,6 @@
async function start() {
updateLoadingStatus("loading.loading");
try {
gotoHome();
if (host != null)
{
await updateProtocolAndUrl(host);
@ -109,6 +108,7 @@
//if fails continue loading encryption may be broken
console.error(e);
}
gotoHome();
} else {
showBlahNotification("error:auth.failed.redirect.to.login");
await delay(2000);

View file

@ -468,29 +468,49 @@ async function decryptString(base64Text, passphrase) {
}
let requestMutex = Promise.resolve();
async function fetchPost(url, value) {
let response = await fetch(url, {
method: "POST",
body: value,
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
}
});
let data = await response.text();
return data;
let release;
const lock = new Promise(resolve => release = resolve);
const prevMutex = requestMutex;
requestMutex = prevMutex.then(() => lock);
await prevMutex;
try {
let response = await fetch(url, {
method: "POST",
body: value,
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
}
});
let data = await response.text();
return data;
} finally {
release();
}
}
async function fetchPostEnc(url, value) {
let nonce = await getNonce(id, passwordHash);
let response = await fetch(url, {
method: "POST",
body: await encryptWithNonce(value, passwordHash, nonce),
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
}
});
let data = await response.text();
return data;
let release;
const lock = new Promise(resolve => release = resolve);
const prevMutex = requestMutex;
requestMutex = prevMutex.then(() => lock);
await prevMutex;
try {
let nonce = await getNonce(id, passwordHash);
let response = await fetch(url, {
method: "POST",
body: await encryptWithNonce(value, passwordHash, nonce),
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
}
});
let data = await response.text();
return data;
} finally {
release();
}
}
async function fetchAsync(url) {
@ -503,15 +523,24 @@ async function fetchAsync(url) {
}
async function fetchAsyncWAuth(url) {
let response = await fetch(url, {
method: "GET",
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
}
});
let release;
const lock = new Promise(resolve => release = resolve);
const prevMutex = requestMutex;
requestMutex = prevMutex.then(() => lock);
await prevMutex;
try {
let response = await fetch(url, {
method: "GET",
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(id, passwordHash))
}
});
let data = await response.text();
return data;
let data = await response.text();
return data;
} finally {
release();
}
}
async function getServerInfo(host) {
@ -520,48 +549,64 @@ async function getServerInfo(host) {
}
async function Auth(loginUsername, loginPassword) {
let resolvedId = await fetchAsync(`${url}/nametoid?u=${loginUsername}`);
if (!resolvedId || resolvedId.trim() === "" || resolvedId.startsWith("error:")) {
return "error:invalid.username.or.password";
}
let actualId = resolvedId.split(":")[0];
let passwordHash = await hashSHA3_512(loginPassword);
let response = await fetch(`${url}/auth?id=${actualId}`, {
method: "GET",
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(actualId, passwordHash))
let release;
const lock = new Promise(resolve => release = resolve);
const prevMutex = requestMutex;
requestMutex = prevMutex.then(() => lock);
await prevMutex;
try {
let resolvedId = await fetchAsync(`${url}/nametoid?u=${loginUsername}`);
if (!resolvedId || resolvedId.trim() === "" || resolvedId.startsWith("error:")) {
return "error:invalid.username.or.password";
}
});
let actualId = resolvedId.split(":")[0];
let data = await response.text();
if (data.startsWith("success:")) {
data += "|" + actualId;
let passwordHash = await hashSHA3_512(loginPassword);
let response = await fetch(`${url}/auth?id=${actualId}`, {
method: "GET",
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(actualId, passwordHash))
}
});
let data = await response.text();
if (data.startsWith("success:")) {
data += "|" + actualId;
}
return data;
} finally {
release();
}
return data;
}
async function fetchEncrypted(request, body = "") {
let release;
const lock = new Promise(resolve => release = resolve);
const prevMutex = requestMutex;
requestMutex = prevMutex.then(() => lock);
await prevMutex;
try {
let nonce = await getNonce(id, passwordHash);
let nonce = await getNonce(id, passwordHash);
let response = await fetch(`${url}/encryptedrequest?id=${id}`, {
method: "POST",
body: await encryptWithNonce(
JSON.stringify({
string1: request,
string2: body
})
let response = await fetch(`${url}/encryptedrequest?id=${id}`, {
method: "POST",
body: await encryptWithNonce(
JSON.stringify({
string1: request,
string2: body
})
, passwordHash, nonce),
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
}
});
let data = await response.text();
return decryptString(data, passwordHash);
, passwordHash, nonce),
headers: {
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
}
});
let data = await response.text();
return await decryptString(data, passwordHash);
} finally {
release();
}
}
function power(base, exponent, mod) {