From 7e384d3c18f6359ccf41f8552ff613fcbaa0be82 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 25 Jan 2017 22:44:34 +0100 Subject: [PATCH] Added the ability to activate the web HTTP port on two ports. Example -w 80,3000 Changes in the captive portal logic that made it compatible with Android Updated bridging readme to include the latest changes --- doc/README.bridging | 4 +++- include/HTTPserver.h | 4 +--- include/NetworkInterface.h | 2 +- include/Prefs.h | 5 +++-- ntopng.8 | 4 ++-- scripts/locales/en.lua | 4 ++-- scripts/lua/admin/prefs.lua | 24 ++++++++++++++++++----- src/HTTPserver.cpp | 39 +++++++++++++++++++++++-------------- src/NetworkInterface.cpp | 2 +- src/Ntop.cpp | 16 ++++++++++++++- src/Prefs.cpp | 30 +++++++++++++++++++++++----- src/main.cpp | 6 +----- 12 files changed, 97 insertions(+), 43 deletions(-) diff --git a/doc/README.bridging b/doc/README.bridging index e59c382996..b35f019a1f 100644 --- a/doc/README.bridging +++ b/doc/README.bridging @@ -28,4 +28,6 @@ Captive portal is used to authenticate legitimate users and bind them to the correct host pool. In order to enable this feature - you need the enterprise version of ntopng - the captive portal option must be enabled in the ntopng preferences menu -- ntopng must be active on port 80 and 443 for authenticating users (-w 80 -W 443) +- ntopng must be active on port 80 (and port a different port) for authenticating users (-w 80,3000) + +When the captive portal is used, port 80 is used only for that purpose (i.e. it cannot be used to connect to the ntop GUI). diff --git a/include/HTTPserver.h b/include/HTTPserver.h index 2a377bd6a2..42692b8e66 100644 --- a/include/HTTPserver.h +++ b/include/HTTPserver.h @@ -29,18 +29,16 @@ extern bool enable_users_login; class HTTPserver { private: - u_int16_t port; char *docs_dir, *scripts_dir; struct mg_context *httpd_v4; bool ssl_enabled; public: - HTTPserver(u_int16_t _port, const char *_docs_dir, const char *_scripts_dir); + HTTPserver(const char *_docs_dir, const char *_scripts_dir); ~HTTPserver(); bool valid_user_pwd(char *user, char *pass); - inline u_int16_t get_port() { return(port); }; inline char* get_docs_dir() { return(docs_dir); }; inline char* get_scripts_dir() { return(scripts_dir); }; inline bool is_ssl_enabled() { return(ssl_enabled); }; diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 45117e53c7..e110310a00 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -451,7 +451,7 @@ class NetworkInterface { inline int8_t getAlertLevel() { return(alertLevel); } #ifdef NTOPNG_PRO virtual void addIPToLRUMatches(u_int32_t client_ip, u_int16_t user_pool_id, - char *label, bool permanentAuthorization) { ; } + char *label, int32_t lifetime_sec) { ; }; #endif }; diff --git a/include/Prefs.h b/include/Prefs.h index d8015bbf66..f6603c55c5 100644 --- a/include/Prefs.h +++ b/include/Prefs.h @@ -59,7 +59,7 @@ class Prefs { bool enable_flow_activity; u_int16_t housekeeping_frequency; u_int32_t max_num_hosts, max_num_flows; - u_int http_port, https_port; + u_int http_port, alt_http_port, https_port; u_int8_t num_interfaces; bool dump_flows_on_es, dump_flows_on_mysql; bool enable_taps; @@ -98,7 +98,7 @@ class Prefs { void setTraceLevelFromRedis(); void setAlertsEnabledFromRedis(); - + void parseHTTPPort(char *arg); void bind_http_to_loopback() { http_binding_address = strdup((char*)CONST_LOOPBACK_ADDRESS); }; void bind_https_to_loopback() { https_binding_address = strdup((char*)CONST_LOOPBACK_ADDRESS); }; bool getDefaultBoolPrefsValue(const char *pref_key, const bool default_value); @@ -171,6 +171,7 @@ class Prefs { inline bool do_simulate_vlans() { return(simulate_vlans); }; inline char* get_cpu_affinity() { return(cpu_affinity); }; inline u_int get_http_port() { return(http_port); }; + inline u_int get_alt_http_port() { return(alt_http_port); }; inline u_int get_https_port() { return(https_port); }; inline char* get_redis_host() { return(redis_host); } inline char* get_redis_password() { return(redis_password); } diff --git a/ntopng.8 b/ntopng.8 index a0d8ece54d..6c9b4fb756 100644 --- a/ntopng.8 +++ b/ntopng.8 @@ -212,8 +212,8 @@ Directory where lua scripts reside. Default: scripts. .It \-3|\-\-callbacks\-dir\ Directory where callback scripts reside. Default: scripts/callbacks. -.It \-w|\-\-http\-port\ <[:]http_port> -Sets the HTTP port of the embedded web server. If set to 0, the http server will be disabled. If you prepend a : before the port (i.e. -w :80) ntopng will listen to the loopback address. +.It \-w|\-\-http\-port\ <[:]http_port[,]> +Sets the HTTP port of the embedded web server. If set to 0, the http server will be disabled. If you prepend a : before the port (i.e. -w :80) ntopng will listen to the loopback address. You can specify a second HTTP port so that ntopng can isten on both ports. Example -w 80,3000 will start ntopn on both port 80 adn 3000. Note that for enabling the captive portal (not available on the community edition) you need to start ntopng on port 80. NOTE: omitting the -w option won't disable http: ntopng will fallback to the default http port. .It \-W|\-\-https\-port\ <[:]https_port> diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index 02e17b11a5..330a770888 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -194,8 +194,8 @@ local en = { host_pools = { edit_host_pools = "Edit Host Pools", pool = "Pool Name", - manage_pools = "Manage Pools", - create_pools = "Create Pools", + manage_pools = "Manage Pool Membership", + create_pools = "Manage Pools", empty_pool = "Empty Pool", delete_pool = "Delete Pool", remove_member = "Remove Member", diff --git a/scripts/lua/admin/prefs.lua b/scripts/lua/admin/prefs.lua index 8cfaa1b32f..0bf1af4e74 100644 --- a/scripts/lua/admin/prefs.lua +++ b/scripts/lua/admin/prefs.lua @@ -341,18 +341,32 @@ end -- ================================================================================ function printBridgingPrefs() + local show + local label + + label = "Enable the web captive portal for authenticating network users." + + if((prefs["http.port"] == 80) and (prefs["http.alt_port"] ~= 0)) then + show = true + else + show = false + label = label.."

This button is disabled as then ntopng web GUI has NOT been started on port 80 that is required by the captive portal (-w command line parameter)." + end + print('

') print('') print('') - toggleTableButtonPrefs("Captive Portal", - "Enable the web captive portal for authenticating network users.", - "On", "1", "success", - "Off", "0", "danger", - "toggle_captive_portal", "ntopng.prefs.enable_captive_portal", "0") + local elementToSwitchSlack = { "toggle_captive_portal" } + toggleTableButtonPrefs("Captive Portal", label, + "On", "1", "success", + "Off", "0", "danger", + "toggle_captive_portal", "ntopng.prefs.enable_captive_portal", "0", + not(show), nil, nil, elementToSwitch) + print('') print('
User Authentication
') diff --git a/src/HTTPserver.cpp b/src/HTTPserver.cpp index cc5aff9256..7b0b6c2358 100644 --- a/src/HTTPserver.cpp +++ b/src/HTTPserver.cpp @@ -314,7 +314,9 @@ static int is_authorized(const struct mg_connection *conn, /* ****************************************** */ static int isCaptiveConnection(struct mg_connection *conn) { - return(ntop->getPrefs()->isCaptivePortalEnabled() && (ntohs(conn->client.lsa.sin.sin_port) == 80)); + return(ntop->getPrefs()->isCaptivePortalEnabled() + && (ntohs(conn->client.lsa.sin.sin_port) == 80) + && (ntop->getPrefs()->get_alt_http_port() != 0)); } /* ****************************************** */ @@ -622,7 +624,7 @@ static int handle_lua_request(struct mg_connection *conn) { /* ****************************************** */ -HTTPserver::HTTPserver(u_int16_t _port, const char *_docs_dir, const char *_scripts_dir) { +HTTPserver::HTTPserver(const char *_docs_dir, const char *_scripts_dir) { struct mg_callbacks callbacks; static char ports[256], ssl_cert_path[MAX_PATH] = { 0 }, access_log_path[MAX_PATH] = { 0 }; const char *http_binding_addr = ntop->getPrefs()->get_http_binding_address(); @@ -642,16 +644,23 @@ HTTPserver::HTTPserver(u_int16_t _port, const char *_docs_dir, const char *_scri NULL }; - - port = _port, docs_dir = strdup(_docs_dir), scripts_dir = strdup(_scripts_dir); + docs_dir = strdup(_docs_dir), scripts_dir = strdup(_scripts_dir); httpserver = this; - if(port == 0) use_http = false; + if(ntop->getPrefs()->get_http_port() == 0) use_http = false; - if(use_http) - snprintf(ports, sizeof(ports), "%s%s%d", + if(use_http) { + char tmp[16]; + + if(ntop->getPrefs()->get_alt_http_port() != 0) + snprintf(tmp, sizeof(tmp), ",%d", ntop->getPrefs()->get_alt_http_port()); + else + tmp[0] = '\0'; + + snprintf(ports, sizeof(ports), "%s%s%d%s", http_binding_addr, (http_binding_addr[0] == '\0') ? "" : ":", - port); + ntop->getPrefs()->get_http_port(), tmp); + } snprintf(ssl_cert_path, sizeof(ssl_cert_path), "%s/ssl/%s", docs_dir, CONST_HTTPS_CERT_NAME); @@ -666,7 +675,7 @@ HTTPserver::HTTPserver(u_int16_t _port, const char *_docs_dir, const char *_scri snprintf(ports, sizeof(ports), "%s%s%d,%s%s%ds", http_binding_addr, (http_binding_addr[0] == '\0') ? "" : ":", - port, + ntop->getPrefs()->get_http_port(), https_binding_addr, (https_binding_addr[0] == '\0') ? "" : ":", ntop->getPrefs()->get_https_port()); @@ -692,14 +701,12 @@ HTTPserver::HTTPserver(u_int16_t _port, const char *_docs_dir, const char *_scri } if((!use_http) && (!use_ssl) & (!ssl_enabled)) { - if(stat_rc != 0) ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to start HTTP server: HTTP is disabled and the SSL certificate is missing."); ntop->getTrace()->traceEvent(TRACE_ERROR, - "Starting the HTTP server on the default port"); - port = CONST_DEFAULT_NTOP_PORT; - snprintf(ports, sizeof(ports), "%d", port); + "Starting the HTTP server on the default port"); + snprintf(ports, sizeof(ports), "%d", ntop->getPrefs()->get_http_port()); use_http = true; } @@ -737,10 +744,12 @@ HTTPserver::HTTPserver(u_int16_t _port, const char *_docs_dir, const char *_scri ntop->getTrace()->traceEvent(TRACE_NORMAL, "Web server dirs [%s][%s]", docs_dir, scripts_dir); if(use_http) - ntop->getTrace()->traceEvent(TRACE_NORMAL, "HTTP server listening on port %d", port); + ntop->getTrace()->traceEvent(TRACE_NORMAL, "HTTP server listening on port(s) %s", + ports); if(use_ssl & ssl_enabled) - ntop->getTrace()->traceEvent(TRACE_NORMAL, "HTTPS server listening on port %d", ntop->getPrefs()->get_https_port()); + ntop->getTrace()->traceEvent(TRACE_NORMAL, "HTTPS server listening on port %d", + ntop->getPrefs()->get_https_port()); }; /* ****************************************** */ diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index a700d52dc9..e05f6f56e3 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -4831,4 +4831,4 @@ bool NetworkInterface::getMacInfo(lua_State* vm, char *mac, u_int16_t vlan_id) { return(false); } -/* **************************************** */ + diff --git a/src/Ntop.cpp b/src/Ntop.cpp index a98b606ef1..17d049ab1a 100644 --- a/src/Ntop.cpp +++ b/src/Ntop.cpp @@ -218,9 +218,20 @@ void Ntop::registerPrefs(Prefs *_prefs, bool quick_registration) { memset(iface, 0, sizeof(iface)); initRedis(); + + if(ntop->getRedis() == NULL) { + ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to initialize redis. Quitting..."); + exit(-1); + } + initElasticSearch(); #ifdef NTOPNG_PRO + if(((ntop->getPrefs()->get_http_port() != 80) && (ntop->getPrefs()->get_alt_http_port() != 80)) + || ((ntop->getPrefs()->get_http_port() == 80) && (ntop->getPrefs()->get_alt_http_port() == 0))) { + redis->del((char*)CONST_PREFS_CAPTIVE_PORTAL); + } + pro->init_license(); #endif } @@ -426,13 +437,16 @@ void Ntop::loadLocalInterfaceAddress() { return; } } + // Make a second call to GetIpAddrTable to get the // actual data we want if((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) { - if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)& lpMsgBuf, 0, NULL)) { LocalFree(lpMsgBuf); } + return; } diff --git a/src/Prefs.cpp b/src/Prefs.cpp index a5c7263d4b..c61ddc198b 100755 --- a/src/Prefs.cpp +++ b/src/Prefs.cpp @@ -40,7 +40,7 @@ Prefs::Prefs(Ntop *_ntop) { scripts_dir = strdup(CONST_DEFAULT_SCRIPTS_DIR); callbacks_dir = strdup(CONST_DEFAULT_CALLBACKS_DIR); config_file_path = ndpi_proto_path = NULL; - http_port = CONST_DEFAULT_NTOP_PORT; + http_port = CONST_DEFAULT_NTOP_PORT, alt_http_port = 0; http_prefix = strdup(""), zmq_encryption_pwd = NULL; instance_name = NULL; categorization_enabled = false, enable_users_login = true; @@ -540,6 +540,23 @@ static const struct option long_options[] = { /* ******************************************* */ +void Prefs::parseHTTPPort(char *arg) { + char tmp[32], *a, *_t; + + snprintf(tmp, sizeof(tmp), "%s", arg); + + a = strtok_r(tmp, ",", &_t); + if(a) { + http_port = atoi(a); + + a = strtok_r(NULL, ",", &_t); + if(a) + alt_http_port = atoi(a); + } +} + +/* ******************************************* */ + int Prefs::setOption(int optkey, char *optarg) { char *double_dot, *p, *opt = NULL; int len = (optarg ? strlen(optarg) : 0)+6; @@ -703,12 +720,12 @@ int Prefs::setOption(int optkey, char *optarg) { break; case 'w': - if(strchr(optarg, ':') == NULL){ + if(strchr(optarg, ':') == NULL) { // only the port - http_port = atoi(optarg); + parseHTTPPort(optarg); } else if(optarg[0] == ':'){ // first char == ':' binds to the loopback address - http_port = atoi(&optarg[1]); + parseHTTPPort(&optarg[1]); bind_http_to_loopback(); } else { // ':' is after the first character, so @@ -716,7 +733,7 @@ int Prefs::setOption(int optkey, char *optarg) { double_dot = strrchr(optarg, ':'); u_int len = double_dot - optarg; http_binding_address = strndup(optarg, len); - http_port = atoi(&double_dot[1]); + parseHTTPPort(&double_dot[1]); } break; @@ -1219,6 +1236,9 @@ void Prefs::lua(lua_State* vm) { lua_push_bool_table_entry(vm, "is_captive_portal_enabled", enable_captive_portal); lua_push_int_table_entry(vm, "dump_hosts", dump_hosts_to_db); + lua_push_int_table_entry(vm, "http.port", get_http_port()); + lua_push_int_table_entry(vm, "http.alt_port", get_alt_http_port()); + /* RRD prefs */ lua_push_int_table_entry(vm, "intf_rrd_raw_days", intf_rrd_raw_days); lua_push_int_table_entry(vm, "intf_rrd_1min_days", intf_rrd_1min_days); diff --git a/src/main.cpp b/src/main.cpp index d8ca2aac32..7e7aec323f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -113,9 +113,6 @@ int main(int argc, char *argv[]) ntop->registerPrefs(prefs, false); - if(ntop->getRedis() == NULL) - return(-1); - prefs->registerNetworkInterfaces(); if(prefs->get_num_user_specified_interfaces() == 0) { @@ -269,8 +266,7 @@ int main(int argc, char *argv[]) Utils::dropPrivileges(); ntop->loadGeolocation(prefs->get_docs_dir()); - ntop->registerHTTPserver(new HTTPserver(prefs->get_http_port(), - prefs->get_docs_dir(), + ntop->registerHTTPserver(new HTTPserver(prefs->get_docs_dir(), prefs->get_scripts_dir())); /*