mirror of
https://github.com/smittix/intercept.git
synced 2026-07-08 17:48:13 -07:00
Fix agent mode issues and WiFi deep scan polling
Agent fixes:
- Fix Ctrl+C hang by running cleanup in background thread
- Add force-exit on double Ctrl+C
- Improve exception handling in output reader threads to prevent
bad file descriptor errors on shutdown
- Reduce cleanup timeouts for faster shutdown
Controller/UI fixes:
- Add URL validation for agent registration (check port, protocol)
- Show helpful message when agent is unreachable during registration
- Clarify API key field label (reserved for future use)
- Add client-side URL validation with user-friendly error messages
WiFi agent mode fixes:
- Add polling fallback for deep scan when push mode is disabled
- Polls /controller/agents/{id}/wifi/data every 2 seconds
- Detect running scans when switching to an agent
- Fix scan_mode detection (agent uses params.scan_type)
This commit is contained in:
@@ -337,6 +337,7 @@
|
||||
<div class="form-group">
|
||||
<label for="agentApiKey">API Key (optional)</label>
|
||||
<input type="text" id="agentApiKey" placeholder="shared-secret">
|
||||
<small style="color: #888; font-size: 11px;">Required if agent has push mode enabled with API key</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
@@ -455,6 +456,22 @@
|
||||
const apiKey = document.getElementById('agentApiKey').value.trim();
|
||||
const description = document.getElementById('agentDescription').value.trim();
|
||||
|
||||
// Validate URL format
|
||||
try {
|
||||
const url = new URL(baseUrl);
|
||||
if (!url.port && !baseUrl.includes(':80') && !baseUrl.includes(':443')) {
|
||||
showToast('URL should include a port (e.g., http://192.168.1.50:8020)', 'error');
|
||||
return;
|
||||
}
|
||||
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
||||
showToast('URL must start with http:// or https://', 'error');
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
showToast('Invalid URL format. Use: http://IP_ADDRESS:PORT', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/controller/agents', {
|
||||
method: 'POST',
|
||||
|
||||
+52
-23
@@ -5444,6 +5444,40 @@
|
||||
const select = document.getElementById('wifiInterfaceSelect');
|
||||
select.innerHTML = '<option value="">Loading interfaces...</option>';
|
||||
|
||||
// Check if we're in agent mode
|
||||
const isAgentMode = typeof currentAgent !== 'undefined' && currentAgent !== 'local';
|
||||
|
||||
if (isAgentMode) {
|
||||
// Fetch from agent via controller
|
||||
fetch(`/controller/agents/${currentAgent}?refresh=true`)
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Failed to fetch agent interfaces');
|
||||
return r.json();
|
||||
})
|
||||
.then(data => {
|
||||
const interfaces = data.agent?.interfaces?.wifi_interfaces || [];
|
||||
if (interfaces.length === 0) {
|
||||
select.innerHTML = '<option value="">No WiFi interfaces on agent</option>';
|
||||
showNotification('WiFi', 'No WiFi interfaces found on remote agent.');
|
||||
} else {
|
||||
select.innerHTML = interfaces.map(i => {
|
||||
let label = i.name || i;
|
||||
if (i.display_name) label = i.display_name;
|
||||
else if (i.type) label += ` (${i.type})`;
|
||||
if (i.monitor_capable) label += ' [Monitor OK]';
|
||||
return `<option value="${i.name || i}">${label}</option>`;
|
||||
}).join('');
|
||||
showNotification('WiFi', `Found ${interfaces.length} interface(s) on agent`);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to refresh agent interfaces:', err);
|
||||
select.innerHTML = '<option value="">Error loading agent interfaces</option>';
|
||||
showNotification('WiFi', 'Failed to load agent interfaces');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/wifi/interfaces')
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Failed to fetch interfaces');
|
||||
@@ -5500,6 +5534,7 @@
|
||||
}
|
||||
|
||||
const killProcesses = document.getElementById('killProcesses').checked;
|
||||
const isAgentMode = typeof currentAgent !== 'undefined' && currentAgent !== 'local';
|
||||
|
||||
// Show loading state
|
||||
const btn = document.getElementById('monitorStartBtn');
|
||||
@@ -5507,7 +5542,12 @@
|
||||
btn.textContent = 'Enabling...';
|
||||
btn.disabled = true;
|
||||
|
||||
fetch('/wifi/monitor', {
|
||||
// Use agent endpoint if in agent mode
|
||||
const endpoint = isAgentMode
|
||||
? `/controller/agents/${currentAgent}/wifi/monitor`
|
||||
: '/wifi/monitor';
|
||||
|
||||
fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ interface: iface, action: 'start', kill_processes: killProcesses })
|
||||
@@ -5519,29 +5559,13 @@
|
||||
if (data.status === 'success') {
|
||||
monitorInterface = data.monitor_interface;
|
||||
updateMonitorStatus(true);
|
||||
showInfo('Monitor mode enabled on ' + monitorInterface + ' - Ready to scan!');
|
||||
const location = isAgentMode ? ' on remote agent' : '';
|
||||
showInfo('Monitor mode enabled on ' + monitorInterface + location + ' - Ready to scan!');
|
||||
|
||||
// Refresh interface list and auto-select the monitor interface
|
||||
fetch('/wifi/interfaces')
|
||||
.then(r => r.json())
|
||||
.then(ifaceData => {
|
||||
const select = document.getElementById('wifiInterfaceSelect');
|
||||
if (ifaceData.interfaces.length > 0) {
|
||||
select.innerHTML = ifaceData.interfaces.map(i => {
|
||||
let label = i.name;
|
||||
let details = [];
|
||||
if (i.chipset) details.push(i.chipset);
|
||||
else if (i.driver) details.push(i.driver);
|
||||
if (i.mac) details.push(i.mac.substring(0, 8) + '...');
|
||||
if (details.length > 0) label += ' - ' + details.join(' | ');
|
||||
label += ` (${i.type})`;
|
||||
if (i.monitor_capable) label += ' [Monitor OK]';
|
||||
return `<option value="${i.name}" ${i.name === monitorInterface ? 'selected' : ''}>${label}</option>`;
|
||||
}).join('');
|
||||
}
|
||||
});
|
||||
refreshWifiInterfaces();
|
||||
} else {
|
||||
alert('Error: ' + data.message);
|
||||
alert('Error: ' + (data.message || 'Unknown error'));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
@@ -5554,8 +5578,13 @@
|
||||
// Disable monitor mode
|
||||
function disableMonitorMode() {
|
||||
const iface = monitorInterface || document.getElementById('wifiInterfaceSelect').value;
|
||||
const isAgentMode = typeof currentAgent !== 'undefined' && currentAgent !== 'local';
|
||||
|
||||
fetch('/wifi/monitor', {
|
||||
const endpoint = isAgentMode
|
||||
? `/controller/agents/${currentAgent}/wifi/monitor`
|
||||
: '/wifi/monitor';
|
||||
|
||||
fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ interface: iface, action: 'stop' })
|
||||
@@ -5566,7 +5595,7 @@
|
||||
updateMonitorStatus(false);
|
||||
showInfo('Monitor mode disabled');
|
||||
} else {
|
||||
alert('Error: ' + data.message);
|
||||
alert('Error: ' + (data.message || 'Unknown error'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user