--
-- (C) 2013-23 - ntop.org
--
local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
package.path = dirs.installdir .. "/scripts/lua/modules/timeseries/drivers/?.lua;" .. package.path -- for influxdb
if ((dirs.scriptdir ~= nil) and (dirs.scriptdir ~= "")) then
package.path = dirs.scriptdir .. "/lua/modules/?.lua;" .. package.path
end
require "lua_utils"
require "prefs_utils"
local template = require "template_utils"
local recording_utils = require "recording_utils"
local data_retention_utils = require "data_retention_utils"
local page_utils = require("page_utils")
local ts_utils = require("ts_utils")
local influxdb = require("influxdb")
local script_manager = require("script_manager")
local info = ntop.getInfo()
local auth = require "auth"
local email_peer_pattern = [[^([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)$]]
if (ntop.isPro()) then
package.path = dirs.installdir .. "/scripts/lua/pro/?.lua;" .. package.path
package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path
if hasClickHouseSupport() then
flow_db_utils = require("flow_db_utils")
end
end
sendHTTPContentTypeHeader('text/html')
local alerts_disabled = false
local product = ntop.getInfo().product
local message_info = ""
local message_severity = "alert-warning"
-- NOTE: all the auth methods should be listed below
local auth_toggles = {
["local"] = "toggle_local_auth",
["ldap"] = "toggle_ldap_auth",
["http"] = "toggle_http_auth",
["radius"] = "toggle_radius_auth"
}
if auth.has_capability(auth.capabilities.preferences) then
if not table.empty(_POST) then
if _GET["tab"] == "auth" then
local one_enabled = false
for k, v in pairs(auth_toggles) do
if _POST[v] == "1" then
one_enabled = true
break
end
end
end
end
if (_GET["tab"] == "ext_alerts") then
local available_endpoints = script_manager.getLoadedAlertEndpoints()
for _, endpoint in ipairs(available_endpoints) do
if (endpoint.handlePost) then
local mi, ms = endpoint.handlePost()
if mi then
message_info = mi
end
if ms then
message_severity = ms
end
end
end
end
if (_POST["toggle_radius_auth"] == "1") and
((_POST["radius_server_address"] ~= ntop.getPref("ntopng.prefs.radius.radius_server_address")) or
(_POST["radius_secret"] ~= ntop.getPref("ntopng.prefs.radius.radius_secret")) or
(_POST["radius_admin_group"] ~= ntop.getPref("ntopng.prefs.radius.radius_admin_group")) or
(_POST["radius_auth_proto"] ~= ntop.getPref("ntopng.prefs.radius.radius_auth_proto")) or
(_POST["radius_unpriv_capabilties_group"] ~=
ntop.getPref("ntopng.prefs.radius.radius_unpriv_capabilties_group")) or
(_POST["toggle_radius_accounting"] ~= ntop.getPref("ntopng.prefs.radius.accounting_enabled"))) then
-- In the minute callback there is a periodic script that in case
-- the auth changed, it's going to update the radius info
ntop.setPref("ntopng.prefs.radius.radius_server_address", _POST["radius_server_address"])
ntop.setPref("ntopng.prefs.radius.radius_secret", _POST["radius_secret"])
ntop.setPref("ntopng.prefs.radius.radius_auth_proto", _POST["radius_auth_proto"])
ntop.setPref("ntopng.prefs.radius.radius_admin_group", _POST["radius_admin_group"])
ntop.setPref("ntopng.prefs.radius.radius_unpriv_capabilties_group", _POST["radius_unpriv_capabilties_group"])
ntop.setPref("ntopng.prefs.radius.toggle_radius_accounting", _POST["toggle_radius_accounting"])
ntop.updateRadiusLoginInfo()
end
if (_POST["disable_alerts_generation"] == "1") then
local alert_utils = require "alert_utils"
alert_utils.disableAlertsGeneration()
elseif (_POST["timeseries_driver"] == "influxdb") then
local url = string.gsub(string.gsub(_POST["ts_post_data_url"], "http:__", "http://"), "https:__", "https://")
if ntop.getPref("ntopng.prefs.timeseries_driver") ~= "influxdb" or
(url ~= ntop.getPref("ntopng.prefs.ts_post_data_url")) or
(_POST["influx_dbname"] ~= ntop.getPref("ntopng.prefs.influx_dbname")) or
(_POST["influx_retention"] ~= ntop.getPref("ntopng.prefs.influx_retention")) or
(_POST["toggle_influx_auth"] ~= ntop.getPref("ntopng.prefs.influx_auth_enabled")) or
(_POST["influx_username"] ~= ntop.getPref("ntopng.prefs.influx_username")) or
(_POST["influx_password"] ~= ntop.getPref("ntopng.prefs.influx_password")) then
local username = nil
local password = nil
if _POST["toggle_influx_auth"] == "1" then
username = _POST["influx_username"]
password = _POST["influx_password"]
end
local ok, message = influxdb.init(_POST["influx_dbname"], url, tonumber(_POST["influx_retention"]),
username, password, false --[[verbose]] )
if not ok then
message_info = message
message_severity = "alert-danger"
-- reset driver to the old one
_POST["timeseries_driver"] = nil
elseif message then
message_info = message
message_severity = "alert-success"
end
end
elseif (_POST["n2disk_license"] ~= nil) then
recording_utils.setLicense(_POST["n2disk_license"])
end
if _POST["timeseries_driver"] or _POST["ts_and_stats_data_retention_days"] then
if ntop.getPref("ntopng.prefs.timeseries_driver") == 'influxdb' then
ntop.setCache("ntopng.influxdb.retention_changed", 1)
end
ts_utils.setupAgain()
end
page_utils.set_active_menu_entry(page_utils.menu_entries.preferences)
dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua")
prefs = ntop.getPrefs()
if not isEmptyString(message_info) then
print [[
]]
print(message_info)
print [[]]
print [[
]]
end
local show_advanced_prefs = false
local show_advanced_prefs_key = "ntopng.prefs.show_advanced_prefs"
if _POST["show_advanced_prefs"] then
show_advanced_prefs = toboolean(_POST["show_advanced_prefs"])
ntop.setPref(show_advanced_prefs_key, _POST["show_advanced_prefs"])
notifyNtopng(show_advanced_prefs_key, _POST["show_advanced_prefs"])
else
show_advanced_prefs = toboolean(ntop.getPref(show_advanced_prefs_key))
if isEmptyString(show_advanced_prefs) then
show_advanced_prefs = false
end
end
if _GET['show_advanced_prefs'] ~= nil then
show_advanced_prefs = (_GET['show_advanced_prefs'] == '1')
end
page_utils.print_page_title(i18n("prefs.runtime_prefs"))
if (false) then
io.write("------- SERVER ----------------\n")
tprint(_SERVER)
io.write("-------- GET ---------------\n")
tprint(_GET)
io.write("-------- POST ---------------\n")
tprint(_POST)
io.write("-----------------------\n")
end
if hasAlertsDisabled() then
alerts_disabled = true
end
local subpage_active, tab = prefsGetActiveSubpage(show_advanced_prefs, _GET["tab"])
-- ================================================================================
function printInterfaces()
print(' ]]
end
-- ================================================================================
function printAlerts()
print('
]]
end
-- ================================================================================
function printProtocolPrefs()
print(' ]]
end
-- ================================================================================
function printNetworkDiscovery()
print(']]
end
-- ================================================================================
function printRecording()
local n2disk_info = recording_utils.getN2diskInfo()
print(']]
end
-- ================================================================================
function printDataRetention()
print(']]
end
-- ================================================================================
function printGUI()
print(']]
end
-- ######################
function printMisc()
print(']]
end
-- ================================================================================
function printUpdates()
print(']]
end
-- ================================================================================
local function printAuthDuration()
print('
' .. i18n("prefs.authentication_duration") ..
'
')
prefsInputFieldPrefs(subpage_active.entries["authentication_duration"].title,
subpage_active.entries["authentication_duration"].description, "ntopng.prefs.", "auth_session_duration",
prefs.auth_session_duration, "number", true, nil, nil, {
min = 60 --[[ 1 minute --]] ,
max = 86400 * 7 --[[ 7 days --]] ,
tformat = "mhd"
})
prefsToggleButton(subpage_active, {
field = "toggle_auth_session_midnight_expiration",
default = "0",
pref = "auth_session_midnight_expiration"
})
end
-- ================================================================================
local function printLdapAuth()
if not ntop.isPro() then
return
end
print('
' .. i18n("prefs.ldap_authentication") ..
'
')
local elementToSwitch = {"row_multiple_ldap_account_type", "row_toggle_ldap_anonymous_bind", "server",
"bind_dn", "bind_pwd", "ldap_server_address", "search_path", "user_group",
"admin_group", "row_toggle_ldap_referrals"}
prefsToggleButton(subpage_active, {
field = auth_toggles.ldap,
pref = "ldap.auth_enabled",
default = "0",
to_switch = elementToSwitch,
-- Similar to "to_switch" but for nested items (e.g. "local hosts cache" only
-- enabled when both "host cache" and "cache" are enabled).
-- The following inputs will be shown/hidden when this preference changes.
nested_to_switch = { -- input: the input ID to toggle (e.g. the "local hosts cache")
-- parent: the parent of the input which affects the input logic (e.g. "host cache")
-- parent_enabled_value: the parent input value that should make the child input visible
-- pref_enabled_value: this preference value that should make the child input visible (e.g. "1" when "cache" is enabled)
{
input = "bind_dn",
parent = "input-toggle_ldap_anonymous_bind",
parent_enabled_value = "0",
pref_enabled_value = "1"
}, {
input = "bind_pwd",
parent = "input-toggle_ldap_anonymous_bind",
parent_enabled_value = "0",
pref_enabled_value = "1"
}}
})
local showElements = (ntop.getPref("ntopng.prefs.ldap.auth_enabled") == "1")
local labels_account = {i18n("prefs.posix"), i18n("prefs.samaccount")}
local values_account = {"posix", "samaccount"}
multipleTableButtonPrefs(subpage_active.entries["multiple_ldap_account_type"].title,
subpage_active.entries["multiple_ldap_account_type"].description, labels_account, values_account, "posix",
"primary", "multiple_ldap_account_type", "ntopng.prefs.ldap.account_type", nil, nil, nil, nil, showElements)
prefsInputFieldPrefs(subpage_active.entries["ldap_server_address"].title,
subpage_active.entries["ldap_server_address"].description, "ntopng.prefs.ldap", "ldap_server_address",
"ldap://localhost:389", nil, showElements, true, true, {
attributes = {
pattern = "ldap(s)?://[0-9.\\-A-Za-z]+(:[0-9]+)?",
spellcheck = "false",
required = "required",
maxlength = 255
}
})
local elementToSwitchBind = {"bind_dn", "bind_pwd"}
prefsToggleButton(subpage_active, {
field = "toggle_ldap_anonymous_bind",
default = "1",
pref = "ldap.anonymous_bind",
to_switch = elementToSwitchBind,
reverse_switch = true,
hidden = not showElements
})
local showEnabledAnonymousBind = false
if ntop.getPref("ntopng.prefs.ldap.anonymous_bind") == "0" then
showEnabledAnonymousBind = true
end
local showElementsBind = showElements
if showElements == true then
showElementsBind = showEnabledAnonymousBind
end
prefsInputFieldPrefs(subpage_active.entries["bind_dn"].title, subpage_active.entries["bind_dn"].description ..
"\"CN=ntop_users,DC=ntop,DC=org,DC=local\".", "ntopng.prefs.ldap", "bind_dn", "", nil, showElementsBind,
true, false, {
attributes = {
spellcheck = "false",
maxlength = 255
}
})
prefsInputFieldPrefs(subpage_active.entries["bind_pwd"].title, subpage_active.entries["bind_pwd"].description,
"ntopng.prefs.ldap", "bind_pwd", "", "password", showElementsBind, true, false, {
attributes = {
maxlength = 255
}
})
prefsInputFieldPrefs(subpage_active.entries["search_path"].title,
subpage_active.entries["search_path"].description, "ntopng.prefs.ldap", "search_path", "", "text",
showElements, nil, nil, {
attributes = {
spellcheck = "false",
maxlength = 255
}
})
prefsInputFieldPrefs(subpage_active.entries["user_group"].title,
subpage_active.entries["user_group"].description, "ntopng.prefs.ldap", "user_group", "", "text",
showElements, nil, nil, {
attributes = {
spellcheck = "false",
maxlength = 255
}
})
prefsInputFieldPrefs(subpage_active.entries["admin_group"].title,
subpage_active.entries["admin_group"].description, "ntopng.prefs.ldap", "admin_group", "", "text",
showElements, nil, nil, {
attributes = {
spellcheck = "false",
maxlength = 255
}
})
prefsToggleButton(subpage_active, {
field = "toggle_ldap_referrals",
default = "1",
pref = "ldap.follow_referrals",
reverse_switch = true,
hidden = not showElements
})
end
-- #####################
local function printRadiusAuth()
if subpage_active.entries["toggle_radius_auth"].hidden then
return
end
print('
')
prefsToggleButton(subpage_active, {
field = auth_toggles["local"],
pref = "local.auth_enabled",
default = "1"
})
end
-- #####################
function printAuthentication()
print('')
end
-- #####################
function printGeoMapCustomization()
if not ntop.isPro() then
return
end
print('')
end
-- #####################
function printNetworkBehaviour()
local LEARNING_STATUS = { -- Keep it in sync with ntop_typedefs.h ServiceAcceptance
ALLOWED = "0",
DENIED = "1",
UNDECIDED = "2"
}
print('')
end
-- ================================================================================
function printInMemory()
print('
]]
end
-- ================================================================================
function printStatsTimeseries()
print(' ]]
end
-- ================================================================================
function printLogging()
if prefs.has_cmdl_trace_lvl then
return
end
print('