NSLOOKUP v0.1

This commit is contained in:
Jokob-sk
2024-01-26 09:23:55 +11:00
parent f40f99aac9
commit d18a59944b
10 changed files with 542 additions and 36 deletions

View File

@@ -56,9 +56,8 @@ Looking forward to your contributions if you decide to share your work with the
> - [WatchYourLAN](https://github.com/aceberg/WatchYourLAN) - Lightweight network IP scanner with web GUI (Open source) > - [WatchYourLAN](https://github.com/aceberg/WatchYourLAN) - Lightweight network IP scanner with web GUI (Open source)
> - [Fing](https://www.fing.com/) - Network scanner app for your Internet security (Commercial, Phone App, Proprietary hardware) > - [Fing](https://www.fing.com/) - Network scanner app for your Internet security (Commercial, Phone App, Proprietary hardware)
## ❤ Support me ## ❤ Support me for...
Get:
- Regular updates to keep your data and family safe 🔄 - Regular updates to keep your data and family safe 🔄
- Better and more functionality - Better and more functionality
- I don't get burned out and the app survives longer🔥🤯 - I don't get burned out and the app survives longer🔥🤯

View File

@@ -239,6 +239,8 @@ function main () {
// get visible columns // get visible columns
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'&parameter=Front_Devices_Columns_Visible&skipcache', function(data) { $.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'&parameter=Front_Devices_Columns_Visible&skipcache', function(data) {
handle_locked_DB(data)
// save which columns are in the Devices page visible // save which columns are in the Devices page visible
tableColumnVisible = numberArrayFromString(data); tableColumnVisible = numberArrayFromString(data);
@@ -250,6 +252,8 @@ function main () {
// get the custom order specified by the user // get the custom order specified by the user
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'&parameter=Front_Devices_Columns_Order&skipcache', function(data) { $.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'&parameter=Front_Devices_Columns_Order&skipcache', function(data) {
handle_locked_DB(data)
// save the columns order in the Devices page // save the columns order in the Devices page
tableColumnOrder = numberArrayFromString(data); tableColumnOrder = numberArrayFromString(data);

View File

@@ -346,10 +346,27 @@ function sanitize(data)
return data.replace(/(\r\n|\n|\r)/gm,"").replace(/[^\x00-\x7F]/g, "") return data.replace(/(\r\n|\n|\r)/gm,"").replace(/[^\x00-\x7F]/g, "")
} }
// -----------------------------------------------------------------------------
// Check and handle locked database
function handle_locked_DB(data)
{
if(data.includes('database is locked'))
{
console.log(data)
showSpinner()
setTimeout(function() {
location.reload();
}, 5000);
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function numberArrayFromString(data) function numberArrayFromString(data)
{ {
console.log(data)
data = JSON.parse(sanitize(data)); data = JSON.parse(sanitize(data));
return data.replace(/\[|\]/g, '').split(',').map(Number); return data.replace(/\[|\]/g, '').split(',').map(Number);
} }

View File

@@ -816,6 +816,8 @@ function saveSelectedColumns () {
function initializeSelectedColumns () { function initializeSelectedColumns () {
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+colDefaultOrderTxt+'&parameter=Front_Devices_Columns_Visible', function(data) { $.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+colDefaultOrderTxt+'&parameter=Front_Devices_Columns_Visible', function(data) {
handle_locked_DB(data)
tableColumnShow = numberArrayFromString(data); tableColumnShow = numberArrayFromString(data);
for(i=0; i < tableColumnShow.length; i++) for(i=0; i < tableColumnShow.length; i++)

View File

@@ -25,6 +25,8 @@ CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
LOG_FILE = os.path.join(CUR_PATH, 'script.log') LOG_FILE = os.path.join(CUR_PATH, 'script.log')
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
pluginName = 'DBCLNP'
def main(): def main():
parser = argparse.ArgumentParser(description='DB cleanup tasks') parser = argparse.ArgumentParser(description='DB cleanup tasks')
@@ -40,13 +42,13 @@ def main():
DAYS_TO_KEEP_EVENTS = int(values.daystokeepevents.split('=')[1]) DAYS_TO_KEEP_EVENTS = int(values.daystokeepevents.split('=')[1])
PHOLUS_DAYS_DATA = int(values.pholuskeepdays.split('=')[1]) PHOLUS_DAYS_DATA = int(values.pholuskeepdays.split('=')[1])
mylog('verbose', ['[DBCLNP] In script']) mylog('verbose', [f'[{pluginName}] In script'])
# Execute cleanup/upkeep # Execute cleanup/upkeep
cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST) cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST)
mylog('verbose', ['[DBCLNP] Cleanup complete file ']) mylog('verbose', [f'[{pluginName}] Cleanup complete'])
return 0 return 0
@@ -58,25 +60,25 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
Cleaning out old records from the tables that don't need to keep all data. Cleaning out old records from the tables that don't need to keep all data.
""" """
mylog('verbose', ['[DBCLNP] Upkeep Database:' ]) mylog('verbose', [f'[{pluginName}] Upkeep Database:' ])
# Connect to the PiAlert SQLite database # Connect to the PiAlert SQLite database
conn = sqlite3.connect(dbPath) conn = sqlite3.connect(dbPath)
cursor = conn.cursor() cursor = conn.cursor()
# Cleanup Online History # Cleanup Online History
mylog('verbose', ['[DBCLNP] Online_History: Delete all but keep latest 150 entries']) mylog('verbose', [f'[{pluginName}] Online_History: Delete all but keep latest 150 entries'])
cursor.execute ("""DELETE from Online_History where "Index" not in ( cursor.execute ("""DELETE from Online_History where "Index" not in (
SELECT "Index" from Online_History SELECT "Index" from Online_History
order by Scan_Date desc limit 150)""") order by Scan_Date desc limit 150)""")
mylog('verbose', ['[DBCLNP] Optimize Database']) mylog('verbose', [f'[{pluginName}] Optimize Database'])
# Cleanup Events # Cleanup Events
mylog('verbose', [f'[DBCLNP] Events: Delete all older than {str(DAYS_TO_KEEP_EVENTS)} days (DAYS_TO_KEEP_EVENTS setting)']) mylog('verbose', [f'[{pluginName}] Events: Delete all older than {str(DAYS_TO_KEEP_EVENTS)} days (DAYS_TO_KEEP_EVENTS setting)'])
cursor.execute (f"""DELETE FROM Events cursor.execute (f"""DELETE FROM Events
WHERE eve_DateTime <= date('now', '-{str(DAYS_TO_KEEP_EVENTS)} day')""") WHERE eve_DateTime <= date('now', '-{str(DAYS_TO_KEEP_EVENTS)} day')""")
# Trim Plugins_History entries to less than PLUGINS_KEEP_HIST setting per unique "Plugin" column entry # Trim Plugins_History entries to less than PLUGINS_KEEP_HIST setting per unique "Plugin" column entry
mylog('verbose', [f'[DBCLNP] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)']) mylog('verbose', [f'[{pluginName}] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)'])
# Build the SQL query to delete entries that exceed the limit per unique "Plugin" column entry # Build the SQL query to delete entries that exceed the limit per unique "Plugin" column entry
delete_query = f"""DELETE FROM Plugins_History delete_query = f"""DELETE FROM Plugins_History
@@ -97,7 +99,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
histCount = get_setting_value('DBCLNP_NOTIFI_HIST') histCount = get_setting_value('DBCLNP_NOTIFI_HIST')
mylog('verbose', [f'[DBCLNP] Plugins_History: Trim Notifications entries to less than {histCount}']) mylog('verbose', [f'[{pluginName}] Plugins_History: Trim Notifications entries to less than {histCount}'])
# Build the SQL query to delete entries # Build the SQL query to delete entries
delete_query = f"""DELETE FROM Notifications delete_query = f"""DELETE FROM Notifications
@@ -115,20 +117,20 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
# Cleanup Pholus_Scan # Cleanup Pholus_Scan
if PHOLUS_DAYS_DATA != 0: if PHOLUS_DAYS_DATA != 0:
mylog('verbose', ['[DBCLNP] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)']) mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)'])
# todo: improvement possibility: keep at least N per mac # todo: improvement possibility: keep at least N per mac
cursor.execute (f"""DELETE FROM Pholus_Scan cursor.execute (f"""DELETE FROM Pholus_Scan
WHERE Time <= date('now', '-{str(PHOLUS_DAYS_DATA)} day')""") WHERE Time <= date('now', '-{str(PHOLUS_DAYS_DATA)} day')""")
# Cleanup New Devices # Cleanup New Devices
if HRS_TO_KEEP_NEWDEV != 0: if HRS_TO_KEEP_NEWDEV != 0:
mylog('verbose', [f'[DBCLNP] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)']) mylog('verbose', [f'[{pluginName}] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)'])
cursor.execute (f"""DELETE FROM Devices cursor.execute (f"""DELETE FROM Devices
WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '+{str(HRS_TO_KEEP_NEWDEV)} hour')""") WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '+{str(HRS_TO_KEEP_NEWDEV)} hour')""")
# De-dupe (de-duplicate) from the Plugins_Objects table # De-dupe (de-duplicate) from the Plugins_Objects table
# TODO This shouldn't be necessary - probably a concurrency bug somewhere in the code :( # TODO This shouldn't be necessary - probably a concurrency bug somewhere in the code :(
mylog('verbose', ['[DBCLNP] Plugins_Objects: Delete all duplicates']) mylog('verbose', [f'[{pluginName}] Plugins_Objects: Delete all duplicates'])
cursor.execute(""" cursor.execute("""
DELETE FROM Plugins_Objects DELETE FROM Plugins_Objects
WHERE rowid > ( WHERE rowid > (
@@ -141,7 +143,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
""") """)
# De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table # De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table
mylog('verbose', ['[DBCLNP] Pholus_Scan: Delete all duplicates']) mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all duplicates'])
cursor.execute ("""DELETE FROM Pholus_Scan cursor.execute ("""DELETE FROM Pholus_Scan
WHERE rowid > ( WHERE rowid > (
SELECT MIN(rowid) FROM Pholus_Scan p2 SELECT MIN(rowid) FROM Pholus_Scan p2
@@ -153,7 +155,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
conn.commit() conn.commit()
# Shrink DB # Shrink DB
mylog('verbose', ['[DBCLNP] Shrink Database']) mylog('verbose', [f'[{pluginName}] Shrink Database'])
cursor.execute ("VACUUM;") cursor.execute ("VACUUM;")
# Close the database connection # Close the database connection

View File

@@ -0,0 +1,7 @@
## Overview
Plugin for device name discovery via the [nslookup](https://linux.die.net/man/1/nslookup) network utility.
### Usage
- Check the Settings page for details.

View File

@@ -0,0 +1,321 @@
{
"code_name": "nslookup_scan",
"unique_prefix": "NSLOOKUP",
"plugin_type": "other",
"enabled": true,
"data_source": "script",
"show_ui": true,
"localized": ["display_name", "description", "icon"],
"display_name": [
{
"language_code": "en_us",
"string": "NSLOOKUP (Name discovery)"
}
],
"icon": [
{
"language_code": "en_us",
"string": "<i class=\"fa-solid fa-search\"></i>"
}
],
"description": [
{
"language_code": "en_us",
"string": "A plugin to discover device names."
}
],
"params" : [
{
"name" : "ips",
"type" : "sql",
"value" : "SELECT dev_LastIP from DEVICES order by dev_MAC",
"timeoutMultiplier" : true
}
],
"settings": [
{
"function": "RUN",
"events": ["run"],
"type": "text.select",
"default_value":"on_new_device",
"options": ["disabled", "on_new_device", "once", "schedule", "always_after_scan"],
"localized": ["name", "description"],
"name" :[{
"language_code":"en_us",
"string" : "When to run"
},
{
"language_code":"es_es",
"string" : "Cuándo ejecutar"
},
{
"language_code":"de_de",
"string" : "Wann laufen"
}],
"description": [{
"language_code":"en_us",
"string" : "When the plugin should be executed. If enabled this will execute the scan until there are no <code>(unknown)</code> or <code>(name not found)</code> devices. Setting this to <code>on_new_device</code> or a daily <code>schedule</code> is recommended."
}]
},
{
"function": "CMD",
"type": "readonly",
"default_value": "python3 /home/pi/pialert/front/plugins/nslookup_scan/nslookup.py",
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Command"
},
{
"language_code": "es_es",
"string": "Comando"
},
{
"language_code": "de_de",
"string": "Befehl"
}
],
"description": [
{
"language_code": "en_us",
"string": "Command to run. This can not be changed"
},
{
"language_code": "es_es",
"string": "Comando a ejecutar. Esto no se puede cambiar"
},
{
"language_code": "de_de",
"string": "Befehl zum Ausführen. Dies kann nicht geändert werden"
}
]
},
{
"function": "RUN_SCHD",
"type": "text",
"default_value":"*/30 * * * *",
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Schedule"
},
{
"language_code":"es_es",
"string" : "Schedule"
},
{
"language_code":"de_de",
"string" : "Schedule"
}],
"description": [{
"language_code":"en_us",
"string" : "Only enabled if you select <code>schedule</code> in the <a href=\"#NSLOOKUP_RUN\"><code>NSLOOKUP_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format (e.g. validate at <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). For example entering <code>0 4 * * *</code> will run the scan after 4 am in the <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> you set above</a>. Will be run NEXT time the time passes."
},
{
"language_code":"es_es",
"string" : "Solo está habilitado si selecciona <code>schedule</code> en la configuración <a href=\"#NSLOOKUP_RUN\"><code>NSLOOKUP_RUN</code></a>. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). Por ejemplo, ingresar <code>0 4 * * *</code> ejecutará el escaneo después de las 4 a.m. en el <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</ código> que configuró arriba</a>. Se ejecutará la PRÓXIMA vez que pase el tiempo."
},
{
"language_code":"de_de",
"string" : "Nur aktiviert, wenn Sie <code>schedule</code> in der <a href=\"#NSLOOKUP_RUN\"><code>NSLOOKUP_RUN</code>-Einstellung</a> auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). Wenn Sie beispielsweise <code>0 4 * * *</code> eingeben, wird der Scan nach 4 Uhr morgens in der <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</ ausgeführt. Code> den Sie oben festgelegt haben</a>. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht."
}]
},
{
"function": "RUN_TIMEOUT",
"type": "integer",
"default_value": 10,
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Run timeout"
},
{
"language_code": "es_es",
"string": "Tiempo límite de ejecución"
},
{
"language_code": "de_de",
"string": "Zeitüberschreitung"
}
],
"description": [
{
"language_code": "en_us",
"string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
},
{
"language_code": "es_es",
"string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela."
},
{
"language_code": "de_de",
"string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen."
}
]
}
],
"database_column_definitions":
[
{
"column": "Object_PrimaryID",
"css_classes": "col-sm-2",
"show": true,
"type": "device_name_mac",
"default_value": "",
"options": [],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "MAC"
},
{
"language_code": "es_es",
"string": "MAC"
}
]
},
{
"column": "Object_SecondaryID",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value": "",
"options": [],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "IP"
},
{
"language_code": "es_es",
"string": "IP"
}
]
},
{
"column": "Watched_Value1",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value": "",
"options": [],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "Server"
}
]
},
{
"column": "Watched_Value2",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value": "",
"options": [],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "Name"
}
]
},
{
"column": "DateTimeCreated",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value": "",
"options": [],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "Created"
},
{
"language_code": "es_es",
"string": "Creado"
}
]
},
{
"column": "DateTimeChanged",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value": "",
"options": [],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "Changed"
},
{
"language_code": "es_es",
"string": "Cambiado"
}
]
},
{
"column": "Status",
"css_classes": "col-sm-1",
"show": true,
"type": "replace",
"default_value": "",
"options": [
{
"equals": "watched-not-changed",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
},
{
"equals": "watched-changed",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
},
{
"equals": "new",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
},
{
"equals": "missing-in-last-scan",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-question'></i></div>"
}
],
"localized": [
"name"
],
"name": [
{
"language_code": "en_us",
"string": "Status"
},
{
"language_code": "es_es",
"string": "Estado"
}
]
}
]
}

View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python
# test script by running:
# tbc
import os
import pathlib
import argparse
import subprocess
import sys
import hashlib
import csv
import sqlite3
import re
from io import StringIO
from datetime import datetime
sys.path.append("/home/pi/pialert/front/plugins")
sys.path.append('/home/pi/pialert/pialert')
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
from logger import mylog, append_line_to_file
from helper import timeNowTZ, get_setting_value
from const import logPath, pialertPath, fullDbPath
from database import DB
from device import Device_obj
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
LOG_FILE = os.path.join(CUR_PATH, 'script.log')
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
pluginName = 'NSLOOKUP'
def main():
mylog('verbose', [f'[{pluginName}] In script'])
timeout = get_setting_value('NSLOOKUP_RUN_TIMEOUT')
# Create a database connection
db = DB() # instance of class DB
db.open()
# Initialize the Plugin obj output file
plugin_objects = Plugin_Objects(RESULT_FILE)
# Create a Device_obj instance
device_handler = Device_obj(db)
# Retrieve devices
unknown_devices = device_handler.getUnknown()
for device in unknown_devices:
domain_name, dns_server = execute_nslookup(device['dev_LastIP'], timeout)
if domain_name != '':
plugin_objects.add_object(
# "MAC", "IP", "Server", "Name"
primaryId = device['dev_MAC'],
secondaryId = device['dev_LastIP'],
watched1 = dns_server,
watched2 = domain_name,
watched3 = '',
watched4 = '',
extra = '',
foreignKey = device['dev_MAC'])
plugin_objects.write_result_file()
mylog('verbose', [f'[{pluginName}] Script finished'])
return 0
#===============================================================================
# Execute scan
#===============================================================================
def execute_nslookup (ip, timeout):
"""
Execute the NSLOOKUP command on IP.
"""
nslookup_args = ['nslookup', ip]
# Execute command
output = ""
try:
# try runnning a subprocess with a forced (timeout) in case the subprocess hangs
output = subprocess.check_output (nslookup_args, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(timeout), text=True)
domain_name = ''
dns_server = ''
# Parse output using regular expressions
domain_pattern = re.compile(r'Name:\s+(.+)')
server_pattern = re.compile(r'Server:\s+(.+)')
domain_match = domain_pattern.search(output.stdout)
server_match = server_pattern.search(output.stdout)
if domain_match:
domain_name = domain_match.group(1)
mylog('verbose', [f'[{pluginName}] Domain Name: {domain_name}'])
if server_match:
dns_server = server_match.group(1)
mylog('verbose', [f'[{pluginName}] DNS Server: {dns_server}'])
return domain_name, dns_server
except subprocess.CalledProcessError as e:
# An error occured, handle it
mylog('verbose', [f'[{pluginName}]', e.output])
mylog('verbose', [f'[{pluginName}] ⚠ ERROR - check logs'])
except subprocess.TimeoutExpired as timeErr:
mylog('verbose', [f'[{pluginName}] TIMEOUT - the process forcefully terminated as timeout reached'])
if output == "": # check if the subprocess failed
mylog('verbose', [f'[{pluginName}] Scan: FAIL - check logs'])
else:
mylog('verbose', [f'[{pluginName}] Scan: SUCCESS'])
return '', ''
#===============================================================================
# BEGIN
#===============================================================================
if __name__ == '__main__':
main()

View File

@@ -23,6 +23,7 @@ LOG_FILE = os.path.join(CUR_PATH, 'script.log')
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
fullPholusPath = os.path.join(CUR_PATH, 'pholus/pholus3.py') fullPholusPath = os.path.join(CUR_PATH, 'pholus/pholus3.py')
pluginName = 'PHOLUS'
def main(): def main():
# sample # sample
@@ -40,13 +41,13 @@ def main():
plugin_objects = Plugin_Objects(RESULT_FILE) plugin_objects = Plugin_Objects(RESULT_FILE)
# Print a message to indicate that the script is starting. # Print a message to indicate that the script is starting.
mylog('verbose',['[PHOLUS] In script']) mylog('verbose',[f'[{pluginName}] In script'])
# Assuming 'values' is a dictionary or object that contains a key 'userSubnets' # Assuming 'values' is a dictionary or object that contains a key 'userSubnets'
# which holds a list of user-submitted subnets. # which holds a list of user-submitted subnets.
# Printing the userSubnets list to check its content. # Printing the userSubnets list to check its content.
mylog('verbose',['[PHOLUS] Subnets: ', values.userSubnets]) mylog('verbose',[f'[{pluginName}] Subnets: ', values.userSubnets])
mylog('verbose',['[PHOLUS] len Subnets: ', len(values.userSubnets)]) mylog('verbose',[f'[{pluginName}] len Subnets: ', len(values.userSubnets)])
# Extract the base64-encoded subnet information from the first element of the userSubnets list. # Extract the base64-encoded subnet information from the first element of the userSubnets list.
# The format of the element is assumed to be like 'userSubnets=b<base64-encoded-data>'. # The format of the element is assumed to be like 'userSubnets=b<base64-encoded-data>'.
@@ -54,14 +55,14 @@ def main():
timeoutSec = values.timeoutSec[0].split('=')[1] timeoutSec = values.timeoutSec[0].split('=')[1]
# Printing the extracted base64-encoded subnet information. # Printing the extracted base64-encoded subnet information.
mylog('verbose', [f'[PHOLUS] { userSubnetsParamBase64 }']) mylog('verbose', [f'[{pluginName}] { userSubnetsParamBase64 }'])
mylog('verbose', [f'[PHOLUS] { timeoutSec }']) mylog('verbose', [f'[{pluginName}] { timeoutSec }'])
# Decode the base64-encoded subnet information to get the actual subnet information in ASCII format. # Decode the base64-encoded subnet information to get the actual subnet information in ASCII format.
userSubnetsParam = base64.b64decode(userSubnetsParamBase64).decode('ascii') userSubnetsParam = base64.b64decode(userSubnetsParamBase64).decode('ascii')
# Print the decoded subnet information. # Print the decoded subnet information.
mylog('verbose', [f'[PHOLUS] userSubnetsParam { userSubnetsParam } ']) mylog('verbose', [f'[{pluginName}] userSubnetsParam { userSubnetsParam } '])
# Check if the decoded subnet information contains multiple subnets separated by commas. # Check if the decoded subnet information contains multiple subnets separated by commas.
# If it does, split the string into a list of individual subnets. # If it does, split the string into a list of individual subnets.
@@ -99,16 +100,15 @@ def execute_pholus_scan(userSubnets, timeoutSec):
timeoutPerSubnet = float(timeoutSec) / len(userSubnets) timeoutPerSubnet = float(timeoutSec) / len(userSubnets)
mylog('verbose', [f'[PHOLUS] { timeoutPerSubnet } ']) mylog('verbose', [f'[{pluginName}] { timeoutPerSubnet } '])
# scan each interface # scan each interface
for interface in userSubnets: for interface in userSubnets:
temp = interface.split("--interface=") temp = interface.split("--interface=")
if len(temp) != 2: if len(temp) != 2:
mylog('none', ["[PHOLUS] Skip scan (need interface in format '192.168.1.0/24 --inteface=eth0'), got: ", interface]) mylog('verbose', [f'[{pluginName}] Skip scan (need interface in format "192.168.1.0/24 --inteface=eth0"), got: ', interface])
return return
mask = temp[0].strip() mask = temp[0].strip()
@@ -116,14 +116,14 @@ def execute_pholus_scan(userSubnets, timeoutSec):
pholus_output_list = execute_pholus_on_interface (interface, timeoutPerSubnet, mask) pholus_output_list = execute_pholus_on_interface (interface, timeoutPerSubnet, mask)
mylog('verbose', [f'[PHOLUS] { pholus_output_list } ']) mylog('verbose', [f'[{pluginName}] { pholus_output_list } '])
result_list += pholus_output_list result_list += pholus_output_list
mylog('verbose', ["[PHOLUS] Pholus output number of entries:", len(result_list)]) mylog('verbose', [f'[{pluginName}] Pholus output number of entries:', len(result_list)])
mylog('verbose', ["[PHOLUS] List:", result_list]) mylog('verbose', [f'[{pluginName}] List:', result_list])
return result_list return result_list
@@ -132,8 +132,8 @@ def execute_pholus_on_interface(interface, timeoutSec, mask):
# logging & updating app state # logging & updating app state
mylog('verbose', ['[PHOLUS] Scan: Pholus for ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min)']) mylog('verbose', [f'[{pluginName}] Scan: Pholus for ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min)'])
mylog('verbose', ["[PHOLUS] Pholus scan on [interface] ", interface, " [mask] " , mask]) mylog('verbose', [f'[{pluginName}] Pholus scan on [interface] ', interface, ' [mask] ' , mask])
# the scan always lasts 2x as long, so the desired user time from settings needs to be halved # the scan always lasts 2x as long, so the desired user time from settings needs to be halved
adjustedTimeout = str(round(int(timeoutSec) / 2, 0)) adjustedTimeout = str(round(int(timeoutSec) / 2, 0))
@@ -149,15 +149,15 @@ def execute_pholus_on_interface(interface, timeoutSec, mask):
output = subprocess.check_output (pholus_args, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(timeoutSec + 30)) output = subprocess.check_output (pholus_args, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(timeoutSec + 30))
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
# An error occured, handle it # An error occured, handle it
mylog('none', ['[PHOLUS]', e.output]) mylog('verbose', [f'[{pluginName}]', e.output])
mylog('none', ["[PHOLUS] ⚠ ERROR - Pholus Scan - check logs"]) mylog('verbose', [f'[{pluginName}] ⚠ ERROR - Pholus Scan - check logs'])
except subprocess.TimeoutExpired as timeErr: except subprocess.TimeoutExpired as timeErr:
mylog('none', ['[PHOLUS] Pholus TIMEOUT - the process forcefully terminated as timeout reached']) mylog('verbose', [f'[{pluginName}] Pholus TIMEOUT - the process forcefully terminated as timeout reached'])
if output == "": # check if the subprocess failed if output == "": # check if the subprocess failed
mylog('none', ['[PHOLUS] Scan: Pholus FAIL - check logs']) mylog('verbose', [f'[{pluginName}] Scan: Pholus FAIL - check logs'])
else: else:
mylog('verbose', ['[PHOLUS] Scan: Pholus SUCCESS']) mylog('verbose', [f'[{pluginName}] Scan: Pholus SUCCESS'])
# check the last run output # check the last run output
f = open(logPath + '/pialert_pholus_lastrun.log', 'r+') f = open(logPath + '/pialert_pholus_lastrun.log', 'r+')

View File

@@ -8,8 +8,28 @@ from logger import mylog, print_log
from const import vendorsPath from const import vendorsPath
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Device object handling (WIP)
#-------------------------------------------------------------------------------
class Device_obj:
def __init__(self, db):
self.db = db
# Get all
def getAll(self):
self.db.sql.execute("""
SELECT * FROM Devices
""")
return self.db.sql.fetchall()
# Get all with unknown names
def getUnknown(self):
self.db.sql.execute("""
SELECT * FROM Devices WHERE dev_Name in ("(unknown)", "(name not found)", "" )
""")
return self.db.sql.fetchall()
#-------------------------------------------------------------------------------
def save_scanned_devices (db): def save_scanned_devices (db):
sql = db.sql #TO-DO sql = db.sql #TO-DO