static void wdctl_reset(int fd, char *arg) { t_client *node; debug(LOG_DEBUG, "Entering wdctl_reset..."); LOCK_CLIENT_LIST(); debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg); /* We get the node or return... */ if ((node = client_list_find_by_ip(arg)) != NULL); else if ((node = client_list_find_by_mac(arg)) != NULL); else { debug(LOG_DEBUG, "Client not found."); UNLOCK_CLIENT_LIST(); write(fd, "No", 2); return; } debug(LOG_DEBUG, "Got node %x.", node); /* deny.... */ /* TODO: maybe just deleting the connection is not best... But this * is a manual command, I don't anticipate it'll be that useful. */ fw_deny(node->ip, node->mac, node->fw_connection_state); client_list_delete(node); UNLOCK_CLIENT_LIST(); write(fd, "Yes", 3); debug(LOG_DEBUG, "Exiting wdctl_reset..."); }
static void ndsctl_deauth(int fd, char *arg) { t_client *client; char *ip, *mac; debug(LOG_DEBUG, "Entering ndsctl_deauth..."); LOCK_CLIENT_LIST(); /* arg can be IP or MAC address of client */ debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg); /* We get the client or return... */ if ((client = client_list_find_by_ip(arg)) != NULL); else if ((client = client_list_find_by_mac(arg)) != NULL); else if ((client = client_list_find_by_token(arg)) != NULL); else { debug(LOG_DEBUG, "Client not found."); UNLOCK_CLIENT_LIST(); write(fd, "No", 2); return; } /* We have the client. Get both ip and mac address and deauthenticate */ ip = safe_strdup(client->ip); mac = safe_strdup(client->mac); UNLOCK_CLIENT_LIST(); auth_client_action(ip, mac, AUTH_MAKE_DEAUTHENTICATED); free(ip); free(mac); write(fd, "Yes", 3); debug(LOG_DEBUG, "Exiting ndsctl_deauth..."); }
void http_callback_disconnect(httpd * webserver, request * r) { const s_config *config = config_get_config(); /* XXX How do you change the status code for the response?? */ httpVar *token = httpdGetVariableByName(r, "token"); httpVar *mac = httpdGetVariableByName(r, "mac"); if (config->httpdusername && (strcmp(config->httpdusername, r->request.authUser) || strcmp(config->httpdpassword, r->request.authPassword))) { debug(LOG_INFO, "Disconnect requested, forcing authentication"); httpdForceAuthenticate(r, config->httpdrealm); return; } if (token && mac) { t_client *client; LOCK_CLIENT_LIST(); client = client_list_find_by_mac(mac->value); if (!client || strcmp(client->token, token->value)) { UNLOCK_CLIENT_LIST(); debug(LOG_INFO, "Disconnect %s with incorrect token %s", mac->value, token->value); httpdOutput(r, "Invalid token for MAC"); return; } /* TODO: get current firewall counters */ logout_client(client); UNLOCK_CLIENT_LIST(); } else { debug(LOG_INFO, "Disconnect called without both token and MAC given"); httpdOutput(r, "Both the token and MAC need to be specified"); return; } return; }
/** The 404 handler is also responsible for redirecting to the auth server */ void http_callback_404(httpd * webserver, request * r, int error_code) { char tmp_url[MAX_BUF], *url, *mac; s_config *config = config_get_config(); t_auth_serv *auth_server = get_auth_server(); memset(tmp_url, 0, sizeof(tmp_url)); /* * XXX Note the code below assumes that the client's request is a plain * http request to a standard port. At any rate, this handler is called only * if the internet/auth server is down so it's not a huge loss, but still. */ snprintf(tmp_url, (sizeof(tmp_url) - 1), "http://%s%s%s%s", r->request.host, r->request.path, r->request.query[0] ? "?" : "", r->request.query); url = httpdUrlEncode(tmp_url); if (!is_online()) { /* The internet connection is down at the moment - apologize and do not redirect anywhere */ char *buf; safe_asprintf(&buf, "<p>We apologize, but it seems that the internet connection that powers this hotspot is temporarily unavailable.</p>" "<p>If at all possible, please notify the owners of this hotspot that the internet connection is out of service.</p>" "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>" "<p>In a while please <a href='%s'>click here</a> to try your request again.</p>", tmp_url); send_http_page(r, "Internet access unavailable!", buf); free(buf); debug(LOG_INFO, "Sent %s an apology since I am not online - no point sending them to auth server", r->clientAddr); } else if (!is_auth_online()) { /* The auth server is down at the moment - apologize and do not redirect anywhere */ char *buf; safe_asprintf(&buf, "<p>We apologize, but it seems that we are currently unable to re-direct you to the login screen.</p>" "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>" "<p>In a couple of minutes please <a href='%s'>click here</a> to try your request again.</p>", tmp_url); send_http_page(r, "Auth server is not online!", buf); free(buf); debug(LOG_INFO, "Sent %s an apology since auth server not online - no point sending them to auth server", r->clientAddr); } else { /* Re-direct them to auth server */ char *urlFragment; if (!(mac = arp_get(r->clientAddr))) { /* We could not get their MAC address */ debug(LOG_INFO, "Failed to retrieve MAC address for ip %s, so not putting in the login request", r->clientAddr); safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&channel_path=%s&ssid=%s&ip=%s&url=%s", auth_server->authserv_login_script_path_fragment, config->gw_address, config->gw_port, config->gw_id, g_channel_path?g_channel_path:"null", g_ssid?g_ssid:"null", r->clientAddr, url); } else { t_client *clt = NULL; debug(LOG_INFO, "Got client MAC address for ip %s: %s", r->clientAddr, mac); safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&channel_path=%s&ssid=%s&ip=%s&mac=%s&url=%s", auth_server->authserv_login_script_path_fragment, config->gw_address, config->gw_port, config->gw_id, g_channel_path?g_channel_path:"null", g_ssid?g_ssid:"null", r->clientAddr, mac, url); //>>> liudf 20160106 added if(_special_process(r, mac, urlFragment)) { free(urlFragment); free(url); free(mac); return; } if(is_roaming(mac)) { fw_set_roam_mac(mac); http_send_redirect(r, tmp_url, "device roaming"); free(urlFragment); free(url); free(mac); return; } // if device has login; but after long time reconnected router, its ip changed LOCK_CLIENT_LIST(); clt = client_list_find_by_mac(mac); if(clt && strcmp(clt->ip, r->clientAddr) != 0) { fw_deny(clt); free(clt->ip); clt->ip = safe_strdup(r->clientAddr); fw_allow(clt, clt->fw_connection_state); UNLOCK_CLIENT_LIST(); http_send_redirect(r, tmp_url, "device has login"); free(urlFragment); free(url); free(mac); return; } UNLOCK_CLIENT_LIST(); // if device is wired and wired device no need auth if(config->wired_passed == 1 && is_device_wired(mac)) { debug(LOG_INFO, "wired_passed: %s is wired device", mac); t_trusted_mac *pmac = add_trusted_mac(mac); fw_set_trusted_mac(mac); http_send_redirect(r, tmp_url, "device no need login"); if(pmac != NULL) pmac->ip = safe_strdup(r->clientAddr); free(urlFragment); free(url); free(mac); return; } //<<< liudf added end free(mac); } // if host is not in whitelist, maybe not in conf or domain'IP changed, it will go to here. debug(LOG_INFO, "Check host %s is in whitelist or not", r->request.host); // e.g. www.example.com t_firewall_rule *rule; //e.g. example.com is in whitelist // if request http://www.example.com/, it's not equal example.com. for (rule = get_ruleset("global"); config->js_filter != 1 && rule != NULL; rule = rule->next) { debug(LOG_INFO, "rule mask %s", rule->mask); if (strstr(r->request.host, rule->mask) == NULL) { debug(LOG_INFO, "host %s is not in %s, continue", r->request.host, rule->mask); continue; } int host_length = strlen(r->request.host); int mask_length = strlen(rule->mask); if (host_length != mask_length) { char prefix[1024] = {0}; // must be *.example.com, if not have ".", maybe Phishing. e.g. phishingexample.com strncpy(prefix, r->request.host, host_length - mask_length - 1); // e.g. www strcat(prefix, "."); // www. strcat(prefix, rule->mask); // www.example.com if (strcasecmp(r->request.host, prefix) == 0) { debug(LOG_INFO, "allow subdomain"); fw_allow_host(r->request.host); http_send_redirect(r, tmp_url, "allow subdomain"); free(url); free(urlFragment); return; } } else { // e.g. "example.com" is in conf, so it had been parse to IP and added into "iptables allow" when wifidog start. but then its' A record(IP) changed, it will go to here. debug(LOG_INFO, "allow domain again, because IP changed"); fw_allow_host(r->request.host); http_send_redirect(r, tmp_url, "allow domain"); free(url); free(urlFragment); return; } } debug(LOG_INFO, "Captured %s requesting [%s] and re-directing them to login page", r->clientAddr, url); if(config->js_filter) http_send_js_redirect_ex(r, urlFragment); else http_send_redirect_to_auth(r, urlFragment, "Redirect to login page"); free(urlFragment); } free(url); }
void notify_client_disconnect(char *mac, char *ifname) { t_client *client; t_redir_node *node; FILE *output; char *script, ip[16], rc; unsigned long long int counter; struct in_addr tempaddr; int ifIndex = get_ifIndex(ifname); // printf("Client Disconnected\n"); LOCK_REDIR(); node = redir_list_find(mac); if (node && node->redir_pending) { UNLOCK_REDIR(); safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_OUTGOING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %17[0-9a-fA-F:] %*s %*s 0x%*u", &counter, ip, mac); if (3 == rc && EOF != rc) { /* Sanity */ if (!inet_aton(ip, &tempaddr)) { debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip); continue; } debug(LOG_DEBUG, "Read outgoing traffic for %s(%s): Bytes=%llu", ip, mac, counter); LOCK_CLIENT_LIST(); if ((client = client_list_find_by_ip(ip))) { client->counters.outgoing = client->counters.outgoing_history + counter; client->counters.last_updated = time(NULL); UNLOCK_CLIENT_LIST(); pclose(output); return; } } } UNLOCK_CLIENT_LIST(); pclose(output); } if(node) if(node->ifindex != ifIndex) debug(LOG_NOTICE,"%s: %s connected to idx %d, recv'd disconnect evt from idx %d\n",__func__, mac, node->ifindex, ifIndex); if (node && (node->ifindex == ifIndex)) { if (node->redir_pending) { char command[100]; char fmac[13]; formatmacaddr(mac, &fmac); node->redir_pending = 0; debug(LOG_NOTICE,"%s: recv'd disconnect evt for %s from idx %d\n",__func__, mac, node->ifindex); snprintf(command,100,"echo %s > /proc/sys/net/bridge/bridge-http-redirect-del-mac",fmac); // printf("%s",command); execute(command,0); if (node->route_added) { memset(command, 0, sizeof(command)); sprintf(command, "/bin/ip route del %s/32 src %s dev %s", node->host_ip, node->dev_ip, node->dev); //printf("\nexecuting %s\n", command); execute(command, 0); } fw_mark_mangle(mac,0); } debug(LOG_NOTICE,"%s: removing node list for %s from idx %d\n",__func__, mac, node->ifindex); redir_list_delete(node); } UNLOCK_REDIR(); LOCK_CLIENT_LIST(); client = client_list_find_by_mac(mac); if (client) { /*fw_deny_raw(client->ip, client->mac, client->fw_connection_state);*/ iptables_fw_access(FW_ACCESS_DENY, client->ip, client->mac, client->fw_connection_state); client_list_delete(client); } UNLOCK_CLIENT_LIST(); }
void notify_client_connect(char *mac, char *ifname) { t_client *client; t_redir_node *node; s_config *config = config_get_config(); int ifIndex = get_ifIndex(ifname); if( !config->status[ifIndex] ) { debug(LOG_NOTICE, "Captive Portal is not enabled for %s", ifname); return; } LOCK_REDIR(); // config_cp_auth_status(ifname, mac, 1); /* Updating the cpAuthStatus to 1 */ node = redir_list_find(mac); if (!node) { node = redir_list_append(mac); } if (!node) { UNLOCK_REDIR(); return; } debug(LOG_NOTICE,"%s recv'd association req from mac %s %p\n",__func__,mac, node); /*post_event(ifname, mac, 1 << 0); *//* BIT0 is set which is a session query notification */ node->ifindex = ifIndex; node->wlindex = config->profile[ifIndex]; if (ifname) strncpy(node->dev, ifname, sizeof(node->dev)); node->cpAuthstatus = 1; node->expiry = time(NULL); if (!node->redir_pending) { char command[100]; char fmac[13]; formatmacaddr(mac, &fmac); node->redir_pending = 1; snprintf(command,100,"echo %s > /proc/sys/net/bridge/bridge-http-redirect-add-mac",fmac); // printf("%s",command); execute(command,0); fw_mark_mangle(mac,1); } if(config->operate_mode){ if((time(NULL) - timekeeper[0].timestamp) > MAX_HOSTNAME_RESOLVE_TIMEOUT){ make_proc_entry_for_url(config->portal[0], 0); timekeeper[0].timestamp = time(NULL); } }else{ if((time(NULL) - timekeeper[ifIndex].timestamp) > MAX_HOSTNAME_RESOLVE_TIMEOUT){ make_proc_entry_for_url(config->portal[ifIndex], ifIndex); timekeeper[ifIndex].timestamp = time(NULL); } } timekeeper[ifIndex].timestamp = time(NULL); UNLOCK_REDIR(); LOCK_CLIENT_LIST(); client = client_list_find_by_mac(mac); if (client) { /*fw_deny_raw(client->ip, client->mac, client->fw_connection_state); *//*PRATIK: Commented so that it doesn't invoke the firewall*/ iptables_fw_access(FW_ACCESS_DENY, client->ip, client->mac, client->fw_connection_state); client_list_delete(client); } UNLOCK_CLIENT_LIST(); }