NMAP, PHOLUS, PIHOLE, DB upgrade + cleanup, docs fixes

This commit is contained in:
Jokob-sk
2023-08-31 08:10:29 +10:00
parent 7391df9f7b
commit 6dcf09a2f6
11 changed files with 219 additions and 316 deletions

View File

@@ -19,7 +19,6 @@
| Plugins_History | History of all entries from the `Plugins_Events` table | ![Screen11][screen11] |
| Plugins_Language_Strings | Language strings colelcted from the plugin `config.json` files used for string resolution in the frontend. | ![Screen12][screen12] |
| Plugins_Objects | Unique objects detected by individual plugins. | ![Screen13][screen13] |
| ScanCycles | (obsolete) Used to determine and identify different scan cycles. | ![Screen14][screen14] |
| Sessions | Used to display sessions in the charts | ![Screen15][screen15] |
| Settings | Database representation of the sum of all settings from `pialert.conf` and plugins coming from `config.json` files. | ![Screen16][screen16] |
@@ -27,16 +26,14 @@
[screen1]: /docs/img/DATABASE/CurrentScan.png
[screen2]: /docs/img/DATABASE/Devices.png
[screen4]: /docs/img/DATABASE/Events.png
[screen5]: /docs/img/DATABASE/Nmap_Scan.png
[screen4]: /docs/img/DATABASE/Events.png
[screen6]: /docs/img/DATABASE/Online_History.png
[screen7]: /docs/img/DATABASE/Parameters.png
[screen8]: /docs/img/DATABASE/Pholus_Scan.png
[screen10]: /docs/img/DATABASE/Plugins_Events.png
[screen11]: /docs/img/DATABASE/Plugins_History.png
[screen12]: /docs/img/DATABASE/Plugins_Language_Strings.png
[screen13]: /docs/img/DATABASE/Plugins_Objects.png
[screen14]: /docs/img/DATABASE/ScanCycles.png
[screen13]: /docs/img/DATABASE/Plugins_Objects.png
[screen15]: /docs/img/DATABASE/Sessions.png
[screen16]: /docs/img/DATABASE/Settings.png

View File

@@ -582,28 +582,7 @@
}
})
}
</script>
<h3><?= lang("DevDetail_Tab_NmapTableHeader");?></h3>
<div><?= lang("DevDetail_Tab_NmapTableText");?></div>
<table id="tableNmap" class="table table-bordered table-hover table-striped ">
<thead>
<tr>
<th><?= lang("DevDetail_Tab_NmapTableIndex");?></th>
<th><?= lang("DevDetail_Tab_NmapTableTime");?></th>
<th><?= lang("DevDetail_Tab_NmapTablePort");?></th>
<th><?= lang("DevDetail_Tab_NmapTableState");?></th>
<th><?= lang("DevDetail_Tab_NmapTableService");?></th>
<th><?= lang("DevDetail_Tab_NmapTableExtra");?></th>
</tr>
</thead>
<!-- Comment out tbody when trying to implement better table with datatables here -->
<tbody id="tableNmapBody">
<tr id="tableNmapPlc" class="text-center"><td colspan='7'><span><?= lang("DevDetail_Tab_NmapEmpty"); ?></span></td></tr>
</tbody>
</table>
</script>
</div>
@@ -1874,60 +1853,11 @@ function initializeTabsNew () {
if(target == "#panNmap")
{
loadNmap();
// loadNmap();
}
});
}
// -----------------------------------------------------------------------------
function loadNmap()
{
$(".deviceSpecific").remove(); // remove any previous data listed in the table
$.get('php/server/devices.php?action=getNmap&mac='+ mac, function(data) {
data = sanitize(data);
if(data != "false" && $.trim(data) != [])
{
var listData = JSON.parse(data);
var order = 1;
tableRows = "";
// for each item
listData.forEach(function (item, index) {
tableRows += '<tr class="deviceSpecific">\
<td>'+item.Index+'</td>\
<td>'+item.Time+'</td>\
<td>\
<a href="http://'+item.IP+':'+item.Port.split('/')[0]+'" target="_blank">'+item.Port+'</a>\
<a href="https://'+item.IP+':'+item.Port.split('/')[0]+'" target="_blank">\
<span style="padding-left:5px"><i class="fa fa-lock "></i></a></span>\
</td>\
<td>'+item.State+'</td>\
<td>'+item.Service+'</td>\
<td>\
<div class="input-group">\
<input class="form-control" id="port_'+item.Index+'" type="text" value="'+item.Extra+'">\
<span class="input-group-addon"><i class="fa fa-save pointer" onclick="saveNmapPort('+item.Index+')"></i></span>\
</div>\
</td>\
</tr>';
});
$("#tableNmapBody").html($("#tableNmapBody").html()+tableRows);
$("#tableNmapPlc").hide();
}
else
{
// console.log("else")
$("#tableNmapPlc").show();
$(".deviceSpecific").remove();
}
});
}
//-----------------------------------------------------------------------------------
@@ -2006,12 +1936,4 @@ function reloadTab()
}
}
//-----------------------------------------------------------------------------------
function saveNmapPort(index)
{
saveData('saveNmapPort', index, $('#port_'+index).val())
}
</script>

View File

@@ -50,9 +50,7 @@
case 'getOwners': getOwners(); break;
case 'getDeviceTypes': getDeviceTypes(); break;
case 'getGroups': getGroups(); break;
case 'getLocations': getLocations(); break;
case 'getNmap': getNmap(); break;
case 'saveNmapPort': saveNmapPort(); break;
case 'getLocations': getLocations(); break;
case 'updateNetworkLeaf': updateNetworkLeaf(); break;
case 'overwriteIconType': overwriteIconType(); break;
case 'getIcons': getIcons(); break;
@@ -1009,82 +1007,6 @@ function getLocations() {
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of Nmap entries
//------------------------------------------------------------------------------
function getNmap() {
global $db;
// SQL
$mac = $_REQUEST['mac'];
if ($mac == "Internet") // Not performing data lookup for router (improvement idea for later maybe)
{
echo "false";
return;
}
if (false === filter_var($mac , FILTER_VALIDATE_MAC)) {
throw new Exception('Invalid mac address');
}
else{
// $sql = 'SELECT * from Nmap_Scan where MAC ="'.$mac.'" ';
$sql = 'select * from (select * from Nmap_Scan INNER JOIN Devices on Nmap_Scan.MAC = Devices.dev_MAC) where MAC = "'.$mac.'" ';
// array
$tableData = array();
// execute query
$result = $db->query($sql);
while ($row = $result -> fetchArray (SQLITE3_ASSOC)){
// Push row data
$tableData[] = array( 'Index' => $row['Index'],
'MAC' => $row['MAC'],
'Port' => $row['Port'],
'Time' => $row['Time'],
'State' => $row['State'],
'Service' => $row['Service'],
'IP' => $row['dev_LastIP'],
'Extra' => $row['Extra']);
}
if(count($tableData) == 0)
{
echo "false";
} else{
// Return json
echo (json_encode ($tableData));
}
}
}
// -------------------------------------------------------------------------------------------
function saveNmapPort()
{
$portIndex = $_REQUEST['id'];
$value = $_REQUEST['value'];
if(is_integer((int)$portIndex))
{
global $db;
// sql
$sql = 'UPDATE Nmap_Scan SET "Extra" = "'. $value .'" WHERE "Index"=' . $portIndex ;
// update Data
$result = $db->query($sql);
// check result
if ($result == TRUE) {
echo 'OK';
} else {
echo 'KO';
}
}
}
// ----------------------------------------------------------------------------------------
function updateNetworkLeaf()
{

View File

@@ -500,36 +500,56 @@ Below are some general additional notes, when defining `params`:
Required attributes are:
- `"function": "<see Supported settings function values>"` - What function the setting drives or a simple unique code name
- `"type": "<text|integer|boolean|password|readonly|integer.select|text.select|text.multiselect|list|integer.checkbox|text.template>"` - The form control used for the setting displayed in the Settings page and what values are accepted.
- `"localized"` - a list of properties on the current JSON level which need to be localized
- `"name"` and `"description"` - Displayed on the Settings page. An array of localized strings. (see Localized strings below).
- (optional) `"events"` - `<test|run>` - to generate an execution button next to the input field of the setting (not fully tested)
- (optional) `"override_value"` - used to determine a user-defined override for the setting. Useful for template-based plugins, where you can choose to leave the current value or override it with the value defined in the setting. (work in progress)
- (optional) `"events": ["run", "test"]` - used to trigger the plugin. Usually used on the `RUN` setting. Not fully tested in all scenarios. Will show a play button next to the setting and then after clicking an event is generated for the backend in the `Parameters` database table to process the front-end event on the next run.
| Property | Description |
| -------- | ----------- |
| `"function"` | Specifies the function the setting drives or a simple unique code name. See Supported settings function values for options. |
| `"type"` | Specifies the form control used for the setting displayed in the Settings page and what values are accepted. Supported options include: |
| | - `text` |
| | - `integer` |
| | - `boolean` |
| | - `password` |
| | - `readonly` |
| | - `integer.select` |
| | - `text.select` |
| | - `text.multiselect` |
| | - `list` |
| | - `integer.checkbox` |
| | - `text.template` |
| `"localized"` | A list of properties on the current JSON level that need to be localized. |
| `"name"` | Displayed on the Settings page. An array of localized strings. See Localized strings below. |
| `"description"` | Displayed on the Settings page. An array of localized strings. See Localized strings below. |
| (optional) `"events"` | Specifies whether to generate an execution button next to the input field of the setting. Supported values: |
| | - `test` |
| | - `run` |
| (optional) `"override_value"` | Used to determine a user-defined override for the setting. Useful for template-based plugins, where you can choose to leave the current value or override it with the value defined in the setting. (Work in progress) |
| (optional) `"events"` | Used to trigger the plugin. Usually used on the `RUN` setting. Not fully tested in all scenarios. Will show a play button next to the setting. After clicking, an event is generated for the backend in the `Parameters` database table to process the front-end event on the next run. |
##### Supported settings `function` values
You can have any `"function": "my_custom_name"` custom name, however, the ones listed below have a specific functionality attached to them. If you use a custom name, then the setting is mostly used as an input parameter for the `params` section.
- `RUN` - (required) Specifies when the service is executed
- Supported Options:
- "disabled" - not run
- "once" - run on app start or on settings saved
- "schedule" - if included then a `RUN_SCHD` setting needs to be specified to determine what's the schedule,
- "always_after_scan" - run always after a scan is finished
- "on_new_device" - run when a new device is detected
- "before_config_save" - run before the config is marked as saved. Useful if your plugin needs to modify the `pialert.conf` file.
- `RUN_SCHD` - (required if you include the above `RUN` function) Cron-like scheduling is used if the `RUN` setting set to `schedule`
- `CMD` - (required) What command should be executed.
- `API_SQL` - (optional) Generates a `table_` + code_name + `.json` file as per [API docs](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md).
- `RUN_TIMEOUT` - (optional) Max execution time of the script. If not specified a default value of 10 seconds is used to prevent hanging.
- `WATCH` - (optional) Which database columns are watched for changes for this particular plugin. If not specified no notifications are sent.
- `REPORT_ON` - (optional) Send a notification only on these statuses. Supported options are:
- `new` means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered.
- `watched-changed` - means that selected `Watched_ValueN` columns changed
- `watched-not-changed` - reports even on events where selected `Watched_ValueN` did not change
- `missing-in-last-scan` - if object is missing compared to previous scans
| Setting | Description |
| ------- | ----------- |
| `RUN` | (required) Specifies when the service is executed. |
| | Supported Options: |
| | - "disabled" - not run |
| | - "once" - run on app start or on settings saved |
| | - "schedule" - if included, then a `RUN_SCHD` setting needs to be specified to determine the schedule |
| | - "always_after_scan" - run always after a scan is finished |
| | - "on_new_device" - run when a new device is detected |
| | - "before_config_save" - run before the config is marked as saved. Useful if your plugin needs to modify the `pialert.conf` file. |
| `RUN_SCHD` | (required if you include the above `RUN` function) Cron-like scheduling is used if the `RUN` setting is set to `schedule`. |
| `CMD` | (required) Specifies the command that should be executed. |
| `API_SQL` | (optional) Generates a `table_` + `code_name` + `.json` file as per [API docs](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md). |
| `RUN_TIMEOUT` | (optional) Specifies the maximum execution time of the script. If not specified, a default value of 10 seconds is used to prevent hanging. |
| `WATCH` | (optional) Specifies which database columns are watched for changes for this particular plugin. If not specified, no notifications are sent. |
| `REPORT_ON` | (optional) Specifies when to send a notification. Supported options are: |
| | - `new` means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. |
| | - `watched-changed` - means that selected `Watched_ValueN` columns changed |
| | - `watched-not-changed` - reports even on events where selected `Watched_ValueN` did not change |
| | - `missing-in-last-scan` - if the object is missing compared to previous scans |
> 🔎 Example:
@@ -573,18 +593,23 @@ You can have any `"function": "my_custom_name"` custom name, however, the ones l
The UI will adjust how columns are displayed in the UI based on the definition of the `database_column_definitions` object. These are the supported form controls and related functionality:
- Only columns with `"show": true` and also with at least an English translation will be shown in the UI.
- Supported types: `label`, `text`, `threshold`, `replace`, `device_ip`, `device_mac`, `url`. Check for details below, how columns behave based on the type.
- `label` makes a column display only
- `text` makes a column editable and a save icon is displayed next to it.
- See below for information on `threshold`, `replace`
- The `options` property is used in conjunction with these types:
- `threshold` - The `options` array contains objects from lowest `maximum` to highest with the corresponding `hexColor` used for the value background color if it's less than the specified `maximum`, but more than the previous one in the `options` array
- `replace` - The `options` array contains objects with an `equals` property, that is compared to the "value" and if the values are the same, the string in `replacement` is displayed in the UI instead of the actual "value"
- `device_mac` - The value is considered to be a Mac address and a link pointing to the device with the given Mac address is generated.
- `device_ip` - The value is considered to be an IP address and a link pointing to the device with the given IP is generated. The IP is checked against the last detected IP address and translated into a Mac address that is then used for the link itself.
- `device_name_mac` - The value is considered to be a MAC address and a link pointing to the device with the given IP is generated. The link label is resolved as the target device name.
- `url` - The value is considered to be a URL so a link is generated.
- `textbox_save` - An editable and saveable text box is generated that saves values in the database. Primarily intended for the `UserData` database column in the `Plugins_Objects` table.
| Supported Types | Description |
| -------------- | ----------- |
| `label` | Displays a column only. |
| `text` | Makes a column editable, and a save icon is displayed next to it. See below for information on `threshold`, `replace`. |
| | |
| `options` Property | Used in conjunction with types like `threshold`, `replace`. |
| `threshold` | The `options` array contains objects ordered from the lowest `maximum` to the highest. The corresponding `hexColor` is used for the value background color if it's less than the specified `maximum` but more than the previous one in the `options` array. |
| `replace` | The `options` array contains objects with an `equals` property, which is compared to the "value." If the values are the same, the string in `replacement` is displayed in the UI instead of the actual "value". |
| | |
| Type Definitions | |
| `device_mac` | The value is considered to be a MAC address, and a link pointing to the device with the given MAC address is generated. |
| `device_ip` | The value is considered to be an IP address. A link pointing to the device with the given IP is generated. The IP is checked against the last detected IP address and translated into a MAC address, which is then used for the link itself. |
| `device_name_mac` | The value is considered to be a MAC address, and a link pointing to the device with the given IP is generated. The link label is resolved as the target device name. |
| `url` | The value is considered to be a URL, so a link is generated. |
| `textbox_save` | Generates an editable and saveable text box that saves values in the database. Primarily intended for the `UserData` database column in the `Plugins_Objects` table. |
```json

View File

@@ -102,7 +102,7 @@
"language_code":"en_us",
"string" : "Device name"
},
{
{
"language_code":"es_es",
"string" : "Nombre del dispositivo"
}]
@@ -119,7 +119,7 @@
"language_code":"en_us",
"string" : "Port"
},
{
{
"language_code":"es_es",
"string" : "Puerto"
}]
@@ -136,7 +136,7 @@
"language_code":"en_us",
"string" : "Created"
},
{
{
"language_code":"es_es",
"string" : "Creado"
}]
@@ -153,7 +153,7 @@
"language_code":"en_us",
"string" : "Changed"
},
{
{
"language_code":"es_es",
"string" : "Cambiado"
}]
@@ -170,7 +170,7 @@
"language_code":"en_us",
"string" : "State"
},
{
{
"language_code":"es_es",
"string" : "Estado"
}]
@@ -186,8 +186,8 @@
"language_code":"en_us",
"string" : "Service"
},
{
"language_code":"es_es",
{
"language_code":"es_es",
"string" : "Servicio"
}]
},
@@ -203,7 +203,7 @@
"language_code":"en_us",
"string" : "N/A"
},
{
{
"language_code":"es_es",
"string" : "N/A"
}]
@@ -220,7 +220,7 @@
"language_code":"en_us",
"string" : "N/A"
},
{
{
"language_code":"es_es",
"string" : "N/A"
}]
@@ -237,11 +237,28 @@
"language_code":"en_us",
"string" : "Extra"
},
{
{
"language_code":"es_es",
"string" : "Extra"
}]
},
{
"column": "UserData",
"css_classes": "col-sm-3",
"show": true,
"type": "textbox_save",
"default_value":"",
"options": [],
"localized": ["name"],
"name":[{
"language_code":"en_us",
"string" : "User data"
},
{
"language_code":"es_es",
"string" : "N/A"
}]
},
{
"column": "ForeignKey",
"css_classes": "col-sm-2",

View File

@@ -50,7 +50,8 @@
{
"name" : "subnets",
"type" : "setting",
"value" : "SCAN_SUBNETS"
"value" : "SCAN_SUBNETS",
"base64": true
},
{
"name" : "timeout",

View File

@@ -27,7 +27,7 @@ fullPholusPath = os.path.join(CUR_PATH, 'pholus/pholus3.py')
def main():
# sample
# /home/pi/pialert/front/plugins/pholus_scan/script.py userSubnets=b'MTkyLjE2OC4xLjAvMjQgLS1pbnRlcmZhY2U9ZXRoMQ==' timeoutSec=10
# sudo docker exec pialert /home/pi/pialert/front/plugins/pholus_scan__ignore/script.py userSubnets=b'MTkyLjE2OC4xLjAvMjQgLS1pbnRlcmZhY2U9ZXRoMQ==' timeoutSec=10
# sudo docker exec pialert /home/pi/pialert/front/plugins/pholus_scan/script.py userSubnets=b'MTkyLjE2OC4xLjAvMjQgLS1pbnRlcmZhY2U9ZXRoMQ==' timeoutSec=10
# the script expects a parameter in the format of userSubnets=subnet1,subnet2,...
parser = argparse.ArgumentParser(description='Import devices from settings')
@@ -46,6 +46,7 @@ def main():
# which holds a list of user-submitted subnets.
# Printing the userSubnets list to check its content.
mylog('verbose',['[Pholus] Subnets: ', values.userSubnets])
mylog('verbose',['[Pholus] len Subnets: ', len(values.userSubnets)])
# 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>'.

View File

@@ -50,7 +50,8 @@
{
"name" : "subnets",
"type" : "setting",
"value" : "SCAN_SUBNETS"
"value" : "SCAN_SUBNETS",
"base64": true
}],
"settings": [

View File

@@ -96,11 +96,6 @@ class DB():
self.sql.execute (f"""DELETE FROM Events
WHERE eve_DateTime <= date('now', '-{str(DAYS_TO_KEEP_EVENTS)} day')""")
# # Cleanup Plugin Events History
# mylog('verbose', ['[DB Cleanup] Plugins_History: Delete all older than '+str(DAYS_TO_KEEP_EVENTS)+' days (DAYS_TO_KEEP_EVENTS setting)'])
# self.sql.execute (f"""DELETE FROM Plugins_History
# WHERE DateTimeChanged <= date('now', '{str(DAYS_TO_KEEP_EVENTS)} day')""")
# Trim Plugins_History entries to less than PLUGINS_KEEP_HIST setting per unique "Plugin" column entry
mylog('verbose', [f'[DB Cleanup] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)'])
@@ -154,17 +149,6 @@ class DB():
AND Pholus_Scan.Value = p2.Value
AND Pholus_Scan.Record_Type = p2.Record_Type
);""")
# De-Dupe (de-duplicate - remove duplicate entries) from the Nmap_Scan table
mylog('verbose', ['[DB Cleanup] Nmap_Scan: Delete all duplicates'])
self.sql.execute ("""DELETE FROM Nmap_Scan
WHERE rowid > (
SELECT MIN(rowid) FROM Nmap_Scan p2
WHERE Nmap_Scan.MAC = p2.MAC
AND Nmap_Scan.Port = p2.Port
AND Nmap_Scan.State = p2.State
AND Nmap_Scan.Service = p2.Service
);""")
# Shrink DB
mylog('verbose', ['[DB Cleanup] Shrink Database'])
@@ -210,7 +194,9 @@ class DB():
);
""")
# Alter Devices table
# -------------------------------------------------------------------------
# Alter Devices table
# -------------------------------------------------------------------------
# dev_Network_Node_MAC_ADDR column
dev_Network_Node_MAC_ADDR_missing = self.sql.execute ("""
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_MAC_ADDR'
@@ -244,18 +230,16 @@ class DB():
ALTER TABLE "Devices" ADD "dev_Icon" TEXT
""")
# indicates, if Settings table is available
settingsMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='Settings';
""").fetchone() == None
# -------------------------------------------------------------------------
# Settings table setup
# -------------------------------------------------------------------------
# Re-creating Settings table
mylog('verbose', ["[upgradeDB] Re-creating Settings table"])
if settingsMissing == False:
self.sql.execute("DROP TABLE Settings;")
self.sql.execute(""" DROP TABLE IF EXISTS Settings;""")
self.sql.execute("""
CREATE TABLE "Settings" (
"Code_Name" TEXT,
@@ -270,21 +254,14 @@ class DB():
);
""")
# indicates, if Pholus_Scan table is available
pholusScanMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='Pholus_Scan';
""").fetchone() == None
# if pholusScanMissing == False:
# # Re-creating Pholus_Scan table
# self.sql.execute("DROP TABLE Pholus_Scan;")
# pholusScanMissing = True
# -------------------------------------------------------------------------
# Pholus_Scan table setup
# -------------------------------------------------------------------------
if pholusScanMissing:
mylog('verbose', ["[upgradeDB] Re-creating Pholus_Scan table"])
self.sql.execute("""
CREATE TABLE "Pholus_Scan" (
# Create Pholus_Scan table if missing
mylog('verbose', ["[upgradeDB] Re-creating Pholus_Scan table"])
self.sql.execute("""CREATE TABLE IF NOT EXISTS "Pholus_Scan" (
"Index" INTEGER,
"Info" TEXT,
"Time" TEXT,
@@ -294,14 +271,13 @@ class DB():
"Value" TEXT,
"Extra" TEXT,
PRIMARY KEY("Index" AUTOINCREMENT)
);
""")
);
""")
# indicates, if Nmap_Scan table is available
nmapScanMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='Nmap_Scan';
""").fetchone() == None
# -------------------------------------------------------------------------
# Parameters table setup
# -------------------------------------------------------------------------
# Re-creating Parameters table
mylog('verbose', ["[upgradeDB] Re-creating Parameters table"])
@@ -317,25 +293,71 @@ class DB():
# Initialize Parameters if unavailable
initOrSetParam(self, 'Back_App_State','Initializing')
# if nmapScanMissing == False:
# # Re-creating Nmap_Scan table
# self.sql.execute("DROP TABLE Nmap_Scan;")
# nmapScanMissing = True
# -------------------------------------------------------------------------
# Parameters table setup DEPRECATED after 1/1/2024
# -------------------------------------------------------------------------
if nmapScanMissing:
mylog('verbose', ["[upgradeDB] Re-creating Nmap_Scan table"])
self.sql.execute("""
CREATE TABLE "Nmap_Scan" (
"Index" INTEGER,
"MAC" TEXT,
"Port" TEXT,
"Time" TEXT,
"State" TEXT,
"Service" TEXT,
"Extra" TEXT,
PRIMARY KEY("Index" AUTOINCREMENT)
);
""")
# indicates, if Nmap_Scan table is available
nmapScanMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='Nmap_Scan';
""").fetchone() == None
if nmapScanMissing == False:
# move data into the PLugins_Objects table
self.sql.execute("""INSERT INTO Plugins_Objects (
Plugin,
Object_PrimaryID,
Object_SecondaryID,
DateTimeCreated,
DateTimeChanged,
Watched_Value1,
Watched_Value2,
Watched_Value3,
Watched_Value4,
Status,
Extra,
UserData,
ForeignKey
)
SELECT
'NMAP' AS Plugin,
MAC AS Object_PrimaryID,
Port AS Object_SecondaryID,
Time AS DateTimeCreated,
DATETIME('now') AS DateTimeChanged,
State AS Watched_Value1,
Service AS Watched_Value2,
'' AS Watched_Value3,
'' AS Watched_Value4,
'watched-not-changed' AS Status,
Extra AS Extra,
Extra AS UserData,
MAC AS ForeignKey
FROM Nmap_Scan;""")
# Delete the Nmap_Scan table
self.sql.execute("DROP TABLE Nmap_Scan;")
nmapScanMissing = True
# if nmapScanMissing:
# mylog('verbose', ["[upgradeDB] Re-creating Nmap_Scan table"])
# self.sql.execute("""
# CREATE TABLE "Nmap_Scan" (
# "Index" INTEGER,
# "MAC" TEXT,
# "Port" TEXT,
# "Time" TEXT,
# "State" TEXT,
# "Service" TEXT,
# "Extra" TEXT,
# PRIMARY KEY("Index" AUTOINCREMENT)
# );
# """)
# -------------------------------------------------------------------------
# Plugins tables setup
# -------------------------------------------------------------------------
# Plugin state
sql_Plugins_Objects = """ CREATE TABLE IF NOT EXISTS Plugins_Objects(
@@ -397,16 +419,12 @@ class DB():
); """
self.sql.execute(sql_Plugins_History)
# -------------------------------------------------------------------------
# Plugins_Language_Strings table setup
# -------------------------------------------------------------------------
# Dynamically generated language strings
# indicates, if Language_Strings table is available
languageStringsMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='Plugins_Language_Strings';
""").fetchone() == None
if languageStringsMissing == False:
self.sql.execute("DROP TABLE Plugins_Language_Strings;")
self.sql.execute("DROP TABLE IF EXISTS Plugins_Language_Strings;")
self.sql.execute(""" CREATE TABLE IF NOT EXISTS Plugins_Language_Strings(
"Index" INTEGER,
Language_Code TEXT NOT NULL,
@@ -417,16 +435,13 @@ class DB():
); """)
self.commitDB()
# -------------------------------------------------------------------------
# CurrentScan table setup
# -------------------------------------------------------------------------
# indicates, if CurrentScan table is available
currentScanMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='CurrentScan';
""").fetchone() == None
if currentScanMissing == False:
self.sql.execute("DROP TABLE CurrentScan;")
self.sql.execute("DROP TABLE IF EXISTS CurrentScan;")
self.sql.execute(""" CREATE TABLE CurrentScan (
cur_ScanCycle INTEGER,
cur_MAC STRING(50) NOT NULL COLLATE NOCASE,
@@ -439,26 +454,21 @@ class DB():
);
""")
# indicates, if DHCP_Leases table is available
DHCP_LeasesMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='DHCP_Leases';
""").fetchone() == None
# -------------------------------------------------------------------------
# DELETING OBSOLETE TABLES - to remove with updated db file after 1/1/2024
# -------------------------------------------------------------------------
if DHCP_LeasesMissing == False:
self.sql.execute("DROP TABLE DHCP_Leases;")
# indicates, if PiHole_Network table is available
PiHole_NetworkMissing = self.sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='PiHole_Network';
""").fetchone() == None
if PiHole_NetworkMissing == False:
self.sql.execute("DROP TABLE PiHole_Network;")
# Deletes obsolete ScanCycles
self.sql.execute(""" DROP TABLE IF EXISTS ScanCycles;""")
self.sql.execute(""" DROP TABLE IF EXISTS DHCP_Leases;""")
self.sql.execute(""" DROP TABLE IF EXISTS PiHole_Network;""")
self.commitDB()
# -------------------------------------------------------------------------
# DELETING OBSOLETE TABLES - to remove with updated db file after 1/1/2024
# -------------------------------------------------------------------------
#-------------------------------------------------------------------------------
def get_table_as_json(self, sqlQuery):

View File

@@ -93,12 +93,12 @@ def print_scan_stats(db):
stats = sql.fetchall()
mylog('verbose', f'[Scan Stats] Devices Detected.......: {stats[0]["devices_detected"]}')
mylog('verbose', f'[Scan Stats] New Devices..........: {stats[0]["new_devices"]}')
mylog('verbose', f'[Scan Stats] Down Alerts..........: {stats[0]["down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Down Alerts......: {stats[0]["new_down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Connections......: {stats[0]["new_connections"]}')
mylog('verbose', f'[Scan Stats] Disconnections.......: {stats[0]["disconnections"]}')
mylog('verbose', f'[Scan Stats] IP Changes...........: {stats[0]["ip_changes"]}')
mylog('verbose', f'[Scan Stats] New Devices............: {stats[0]["new_devices"]}')
mylog('verbose', f'[Scan Stats] Down Alerts............: {stats[0]["down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Down Alerts........: {stats[0]["new_down_alerts"]}')
mylog('verbose', f'[Scan Stats] New Connections........: {stats[0]["new_connections"]}')
mylog('verbose', f'[Scan Stats] Disconnections.........: {stats[0]["disconnections"]}')
mylog('verbose', f'[Scan Stats] IP Changes.............: {stats[0]["ip_changes"]}')
mylog('verbose', '[Scan Stats] Scan Method Statistics:')
for row in stats:

View File

@@ -6,6 +6,7 @@ import smtplib
import conf
import socket
from helper import hide_email, noti_struc
from logger import mylog, print_log
@@ -83,8 +84,14 @@ def send (msg: noti_struc):
except smtplib.SMTPAuthenticationError as e:
mylog('none', [' ERROR: Failed at - ', failedAt])
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPAuthenticationError), skipping Email (enable LOG_LEVEL=debug for more logging)'])
mylog('none', [' ERROR: ', str(e)])
except smtplib.SMTPServerDisconnected as e:
mylog('none', [' ERROR: Failed at - ', failedAt])
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPServerDisconnected), skipping Email (enable LOG_LEVEL=debug for more logging)'])
mylog('none', [' ERROR: ', str(e)])
except socket.gaierror as e:
mylog('none', [' ERROR: Failed at - ', failedAt])
mylog('none', [' ERROR: Could not resolve hostname (socket.gaierror), skipping Email (enable LOG_LEVEL=debug for more logging)'])
mylog('none', [' ERROR: ', str(e)])
mylog('debug', '[Send Email] Last executed - ' + str(failedAt))