diff --git a/src/client_list.c b/src/client_list.c index 136b0edd..6559d7fb 100644 --- a/src/client_list.c +++ b/src/client_list.c @@ -50,11 +50,6 @@ static t_offline_client *first_offline_client = NULL; */ static volatile unsigned long long client_id = 1; -/** - * Mutex to protect client_id and guarantee uniqueness. - */ -static pthread_mutex_t client_id_mutex = PTHREAD_MUTEX_INITIALIZER; - /** Global mutex to protect access to the client list */ pthread_mutex_t client_list_mutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/conf.c b/src/conf.c index d539c856..216f45fc 100644 --- a/src/conf.c +++ b/src/conf.c @@ -86,6 +86,7 @@ typedef enum { oAuthServWsScriptPathFragment, oAuthServerOfflineFile, oInternetOfflineFile, + oLocalPortal, oHTTPDMaxConn, oHTTPDName, oHTTPDRealm, @@ -165,6 +166,7 @@ static const struct { "wsscriptpathfragment", oAuthServWsScriptPathFragment}, { "authserverofflinefile", oAuthServerOfflineFile}, { "internetofflinefile", oInternetOfflineFile}, { + "localportal", oLocalPortal}, { "firewallruleset", oFirewallRuleSet}, { "firewallrule", oFirewallRule}, { "trustedmaclist", oTrustedMACList}, { @@ -273,6 +275,7 @@ config_init(void) config.htmlredirfile = safe_strdup(DEFAULT_REDIRECTFILE); config.internet_offline_file = safe_strdup(DEFAULT_INTERNET_OFFLINE_FILE); config.authserver_offline_file = safe_strdup(DEFAULT_AUTHSERVER_OFFLINE_FILE); + config.local_portal = safe_strdup(DEFAULT_LOCAL_PORTAL); config.js_redir = 1; // default enable it config.wired_passed = 1; // default wired device no need login config.parse_checked = 1; // before parse domain's ip; fping check it @@ -1148,6 +1151,11 @@ config_read() free(config.internet_offline_file); config.internet_offline_file = safe_strdup(p1); break; + case oLocalPortal: + if (config.local_portal) + free(config.local_portal); + config.local_portal = safe_strdup(p1); + break; case oBadOption: /* FALL THROUGH */ default: diff --git a/src/conf.h b/src/conf.h index 3550ea9b..156aabdd 100644 --- a/src/conf.h +++ b/src/conf.h @@ -62,6 +62,7 @@ #define DEFAULT_SYSLOG_FACILITY LOG_DAEMON #define DEFAULT_WDCTL_SOCK "/tmp/wdctl.sock" #define DEFAULT_INTERNAL_SOCK "/tmp/wifidog.sock" +#define DEFAULT_LOCAL_PORTAL "http://www.wifidogx.online" #define DEFAULT_AUTHSERVPORT 80 #define DEFAULT_AUTHSERVSSLPORT 443 /** Note that DEFAULT_AUTHSERVSSLAVAILABLE must be 0 or 1, even if the config file syntax is yes or no */ @@ -303,6 +304,7 @@ typedef struct { char *htmlredirfile; char *internet_offline_file; char *authserver_offline_file; + char *local_portal; short wired_passed; /** 1 wired device no need to auth */ short parse_checked; short js_redir; /** boolean, whether to enable javascript to redirect url request to auth server */ diff --git a/src/fw4_nft.c b/src/fw4_nft.c index 134a082c..1e7efc03 100644 --- a/src/fw4_nft.c +++ b/src/fw4_nft.c @@ -478,12 +478,6 @@ nft_fw_del_rule_by_ip_and_mac(const char *ip, const char *mac, const char *chain int nft_fw_access(fw_access_t type, const char *ip, const char *mac, int tag) { - // according to type, if type is FW_ACCESS_ALLOW, set the firewall rules to allow the client - // if type is FW_ACCESS_DENY, set the firewall rules to deny the client - - // the rules are as the following: - // add rule inet fw4 mangle_prerouting_wifidogx_outgoing ether saddr ab:23:23:ab:23:23 ip saddr - // add rule inet fw4 mangle_postrouting_wifidogx_incoming ether saddr ab:23:23:ab:23:23 ip saddr switch(type) { case FW_ACCESS_ALLOW: run_cmd("nft add rule inet fw4 mangle_prerouting_wifidogx_outgoing ether saddr %s ip saddr %s counter mark set 0x20000 accept", mac, ip); @@ -512,27 +506,25 @@ nft_fw_reload_client(int tag) return 1; } - // open the file /tmp/nftables_wifidogx_client_list - // define the file /tmp/nftables_wifidogx_client_list as NFT_WIFIDOGX_CLIENT_LIST FILE *fp = fopen(NFT_WIFIDOGX_CLIENT_LIST, "w"); if (fp == NULL) { debug(LOG_ERR, "Failed to open %s", NFT_WIFIDOGX_CLIENT_LIST); return 1; } - // flush the rules in the chain mangle_prerouting_wifidogx_outgoing fprintf(fp, "nft flush chain inet fw4 mangle_prerouting_wifidogx_outgoing\n"); - // flush the rules in the chain mangle_postrouting_wifidogx_incoming fprintf(fp, "nft flush chain inet fw4 mangle_postrouting_wifidogx_incoming\n"); - // iterate the client_list + t_client *current = first_client; char line[256] = {0}; do { - snprintf(line, sizeof(line), "nft add rule inet fw4 mangle_prerouting_wifidogx_outgoing ether saddr %s ip saddr %s counter mark set 0x%02x0000/0xff0000 accept\n", current->mac, current->ip, tag&0x000000ff); - // write the line to the file /tmp/nftables_wifidogx_client_list + snprintf(line, sizeof(line), + "nft add rule inet fw4 mangle_prerouting_wifidogx_outgoing ether saddr %s ip saddr %s counter mark set 0x%02x0000/0xff0000 accept\n", + current->mac, current->ip, tag&0x000000ff); fprintf(fp, "%s", line); memset(line, 0, sizeof(line)); - snprintf(line, sizeof(line), "nft add rule inet fw4 mangle_postrouting_wifidogx_incoming ip daddr %s counter accept\n", current->ip); - // write the line to the file /tmp/nftables_wifidogx_client_list + snprintf(line, sizeof(line), + "nft add rule inet fw4 mangle_postrouting_wifidogx_incoming ip daddr %s counter accept\n", + current->ip); fprintf(fp, "%s", line); memset(line, 0, sizeof(line)); current = current->next; diff --git a/src/gateway.c b/src/gateway.c index 0f61cbe4..2becde64 100644 --- a/src/gateway.c +++ b/src/gateway.c @@ -422,7 +422,7 @@ threads_init(s_config *config) debug(LOG_INFO, "No auth server available, not starting the following threads"); return; } - + /* Start heartbeat thread */ result = pthread_create(&tid_ping, NULL, (void *)thread_ping, NULL); if (result != 0) { @@ -510,6 +510,7 @@ http_redir_loop(s_config *config) evhttp_set_cb(http, "/wifidog/auth", ev_http_callback_auth, request_ctx); //evhttp_set_cb(http, "/wifidog/disconnect", ev_http_callback_disconnect, request_ctx); evhttp_set_cb(http, "/wifidog/temporary_pass", ev_http_callback_temporary_pass, NULL); + evhttp_set_cb(http, "/wifidog/local_auth", ev_http_callback_local_auth, NULL); evhttp_set_gencb(http, ev_http_callback_404, NULL); diff --git a/src/http.c b/src/http.c index 2b2a116d..fcb4e9c7 100644 --- a/src/http.c +++ b/src/http.c @@ -53,6 +53,7 @@ #include "wd_util.h" #include "version.h" #include "wd_client.h" +#include "fw_iptables.h" #define APPLE_REDIRECT_MSG "" \ "" \ @@ -544,6 +545,44 @@ ev_http_callback_disconnect(struct evhttp_request *req, void *arg) } } +/** + * @brief process client's local pass request + * + * @param req Client's http request + * @param arg useless + * + */ +void +ev_http_callback_local_auth(struct evhttp_request *req, void *arg) +{ + s_config *config = config_get_config(); + if (config->auth_servers) { + evhttp_send_error(req, HTTP_OK, "Only no auth server configured can use local pass"); + return; + } + + // get the ip and mac of the client + const char *mac = ev_http_find_query(req, "mac"); + const char *ip = ev_http_find_query(req, "ip"); + if (!mac || !ip) { + evhttp_send_error(req, HTTP_OK, "MAC and IP need to be specified"); + goto END; + } + + // fw_allow the client + LOCK_CLIENT_LIST(); + iptables_fw_access(FW_ACCESS_ALLOW, ip, mac, 0); + UNLOCK_CLIENT_LIST(); + + // redirect the client to the internet + ev_http_send_redirect(req, config->local_portal, "Redirect to internet"); + +END: + if (mac) free((void *)mac); + if (ip) free((void *)ip); +} + + /** * @brief Temporaray allow client to access internet a minute * diff --git a/src/http.h b/src/http.h index 266d3230..7c471b84 100644 --- a/src/http.h +++ b/src/http.h @@ -72,4 +72,6 @@ void ev_http_replay_wisper(struct evhttp_request *); /** @brief get query's value according to key */ char *ev_http_find_query(struct evhttp_request *, const char *); +void ev_http_callback_local_auth(struct evhttp_request *, void *); + #endif /* _HTTP_H_ */