예제 #1
0
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...");
}
예제 #2
0
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...");
}
예제 #3
0
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;
}
예제 #4
0
/** 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);
}
예제 #5
0
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();
}
예제 #6
0
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();
}