diff --git a/include/ntop_defines.h b/include/ntop_defines.h index 3f621c8133..8f88c9a2aa 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -1217,6 +1217,7 @@ #define PREF_RADIUS_ADMIN_GROUP NTOPNG_PREFS_PREFIX ".radius.radius_admin_group" #define PREF_RADIUS_UNPRIV_CAP_GROUP \ NTOPNG_PREFS_PREFIX ".radius.radius_unpriv_capabilties_group" +#define PREF_RADIUS_EXT_AUTHE_LOCAL_AUTHO NTOPNG_PREFS_PREFIX ".radius.external_auth_for_local_users_enabled" #ifdef HAVE_RADIUS #define MAX_RADIUS_LEN 256 diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index aa23231b97..4fa786c1fe 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -6738,6 +6738,8 @@ local lang = { ["toggle_radius_accounting_descr"] = "Toggle traffic accounting via RADIUS server.", ["toggle_radius_auth"] = "Toggle RADIUS Authentication", ["toggle_radius_auth_descr"] = "Toggle GUI authentication via RADIUS server.", + ["toggle_radius_external_auth_for_local_users"] = "Toggle RADIUS Authentication of Local Users", + ["toggle_radius_external_auth_for_local_users_descr"] = "Toggle authentication of local users via RADIUS (remote authentication, local authorization).", ["toggle_send_telemetry_data_description"] = "Contribute to the project by sending encrypted, anonymous telemetry data to ntop.org. Data only involves the status of %{product} (e.g., uptime, status, crash reports). Nothing regarding the monitored traffic will ever be sent.", ["toggle_send_telemetry_data_title"] = "Telemetry Data", ["toggle_shaping_directions_description"] = "Enable this option to be able to set different shaping policies for ingress and egress traffic.", diff --git a/scripts/lua/admin/prefs.lua b/scripts/lua/admin/prefs.lua index 0cebb04cc9..76f47db640 100644 --- a/scripts/lua/admin/prefs.lua +++ b/scripts/lua/admin/prefs.lua @@ -122,9 +122,9 @@ if auth.has_capability(auth.capabilities.preferences) then (_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 + (_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")) or + (_POST["toggle_radius_external_auth_for_local_users"] ~= ntop.getPref("ntopng.prefs.radius.external_auth_for_local_users_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"]) @@ -134,6 +134,7 @@ if auth.has_capability(auth.capabilities.preferences) then 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.setPref("ntopng.prefs.radius.external_auth_for_local_users_enabled", _POST["toggle_radius_external_auth_for_local_users"]) ntop.updateRadiusLoginInfo() end @@ -919,7 +920,7 @@ if auth.has_capability(auth.capabilities.preferences) then -- RADIUS GUI authentication - local elementToSwitch = {"row_toggle_radius_accounting", "radius_admin_group", + local elementToSwitch = {"row_toggle_radius_accounting", "row_toggle_radius_external_auth_for_local_users", "radius_admin_group", "radius_unpriv_capabilties_group", "radius_server_address", "radius_acct_server_address", "radius_secret", "row_radius_auth_proto"} @@ -962,9 +963,21 @@ if auth.has_capability(auth.capabilities.preferences) then "pap", "primary", "radius_auth_proto", "ntopng.prefs.radius.radius_auth_proto", nil, nil, nil, nil, showElements) + local groupsElements = {"radius_admin_group", "radius_unpriv_capabilties_group"} + local showGroupsElements = (ntop.getPref("ntopng.prefs.radius.external_auth_for_local_users_enabled") ~= "1") + prefsToggleButton(subpage_active, { + field = "toggle_radius_external_auth_for_local_users", + pref = "radius.external_auth_for_local_users_enabled", + default = "0", + to_switch = groupsElements, + reverse_switch = true, + hidden = not showElements + }) + prefsInputFieldPrefs(subpage_active.entries["radius_admin_group"].title, - subpage_active.entries["radius_admin_group"].description, "ntopng.prefs.radius", "radius_admin_group", "", - nil, showElements, true, false, { + subpage_active.entries["radius_admin_group"].description, "ntopng.prefs.radius", + "radius_admin_group", "", nil, + showElements and showGroupsElements, true, false, { attributes = { spellcheck = "false", maxlength = 255, @@ -974,7 +987,8 @@ if auth.has_capability(auth.capabilities.preferences) then prefsInputFieldPrefs(subpage_active.entries["radius_unpriv_capabilties_group"].title, subpage_active.entries["radius_unpriv_capabilties_group"].description, "ntopng.prefs.radius", - "radius_unpriv_capabilties_group", "", nil, showElements, true, false, { + "radius_unpriv_capabilties_group", "", nil, + showElements and showGroupsElements, true, false, { attributes = { spellcheck = "false", maxlength = 255, diff --git a/scripts/lua/modules/http_lint.lua b/scripts/lua/modules/http_lint.lua index 8692993a17..aaab427c48 100644 --- a/scripts/lua/modules/http_lint.lua +++ b/scripts/lua/modules/http_lint.lua @@ -2227,6 +2227,7 @@ local known_parameters = { ["toggle_ldap_auth"] = validateBool, ["toggle_local_auth"] = validateBool, ["toggle_radius_accounting"] = validateBool, + ["toggle_radius_external_auth_for_local_users"] = validateBool, ["toggle_radius_auth"] = validateBool, ["toggle_http_auth"] = validateBool, ["toggle_ldap_referrals"] = validateBool, diff --git a/scripts/lua/modules/prefs_menu.lua b/scripts/lua/modules/prefs_menu.lua index e33a03e2c2..023af5bd55 100644 --- a/scripts/lua/modules/prefs_menu.lua +++ b/scripts/lua/modules/prefs_menu.lua @@ -685,6 +685,13 @@ local menu_subpages = {{ }), hidden = (not hasRadius) }, + toggle_radius_external_auth_for_local_users = { + title = i18n("prefs.toggle_radius_external_auth_for_local_users"), + description = i18n("prefs.toggle_radius_external_auth_for_local_users_descr", { + product = info.product + }), + hidden = (not hasRadius or not have_nedge) + }, toggle_http_auth = { title = i18n("prefs.toggle_http_auth"), description = i18n("prefs.toggle_http_auth_descr"), diff --git a/src/Ntop.cpp b/src/Ntop.cpp index fc47220838..5dde837090 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -1779,8 +1779,10 @@ bool Ntop::checkLDAPAuth(const char *user, const char *password, char *group) co /* ******************************************* */ bool Ntop::checkRadiusAuth(const char *user, const char *password, char *group) const { + bool is_admin = false, has_unprivileged_capabilities = false; + bool external_auth_for_local_users = false; bool radius_ret = false; - char val[64]; + char key[64], val[64]; #ifdef HAVE_RADIUS /* @@ -1797,8 +1799,6 @@ bool Ntop::checkRadiusAuth(const char *user, const char *password, char *group) val[0] != '1') return false; - bool is_admin = false, has_unprivileged_capabilities = false; - ntop->getTrace()->traceEvent(TRACE_INFO, "Checking RADIUS auth"); if (!password || !password[0]) return false; @@ -1807,29 +1807,42 @@ bool Ntop::checkRadiusAuth(const char *user, const char *password, char *group) if (radiusAcc->authenticate(user, password, &has_unprivileged_capabilities, &is_admin)) { - /* Check permissions */ - if (has_unprivileged_capabilities) { - changeUserPcapDownloadPermission(user, true, 86400 /* 1 day */); - changeUserHistoricalFlowPermission(user, true, 86400 /* 1 day */); - changeUserAlertsPermission(user, true, 86400 /* 1 day */); - } else { - char key[64]; - snprintf(key, sizeof(key), CONST_STR_USER_ALLOW_PCAP, user); - ntop->getRedis()->del(key); + if(ntop->getRedis()->get((char *)PREF_RADIUS_EXT_AUTHE_LOCAL_AUTHO, val, sizeof(val)) >= 0 && val[0] == '1') + external_auth_for_local_users = true; - snprintf(key, sizeof(key), CONST_STR_USER_ALLOW_HISTORICAL_FLOW, user); - ntop->getRedis()->del(key); + if (external_auth_for_local_users) { + snprintf(key, sizeof(key), CONST_STR_USER_PASSWORD, user); + if (ntop->getRedis()->get(key, val, sizeof(val)) < 0) + return false; /* Local user with same name does not exist */ - snprintf(key, sizeof(key), CONST_STR_USER_ALLOW_ALERTS, user); - ntop->getRedis()->del(key); + getUserGroupLocal(user, group); + + } else { + /* Check permissions */ + if (has_unprivileged_capabilities) { + changeUserPcapDownloadPermission(user, true, 86400 /* 1 day */); + changeUserHistoricalFlowPermission(user, true, 86400 /* 1 day */); + changeUserAlertsPermission(user, true, 86400 /* 1 day */); + } else { + char key[64]; + + snprintf(key, sizeof(key), CONST_STR_USER_ALLOW_PCAP, user); + ntop->getRedis()->del(key); + + snprintf(key, sizeof(key), CONST_STR_USER_ALLOW_HISTORICAL_FLOW, user); + ntop->getRedis()->del(key); + + snprintf(key, sizeof(key), CONST_STR_USER_ALLOW_ALERTS, user); + ntop->getRedis()->del(key); + } + + strncpy(group, + is_admin ? CONST_USER_GROUP_ADMIN : CONST_USER_GROUP_UNPRIVILEGED, + NTOP_GROUP_MAXLEN); + group[NTOP_GROUP_MAXLEN - 1] = '\0'; } - strncpy(group, - is_admin ? CONST_USER_GROUP_ADMIN : CONST_USER_GROUP_UNPRIVILEGED, - NTOP_GROUP_MAXLEN); - group[NTOP_GROUP_MAXLEN - 1] = '\0'; - radius_ret = true; } #endif