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_logout(httpd *webserver, request *r) { t_client *client; s_config *config = config_get_config(); LOCK_CLIENT_LIST(); client = client_list_find_by_ip(r->clientAddr); /* Send logout to auth server if client is logged in */ if (client != NULL) { t_authresponse authresponse; char *ip = strdup(client->ip); char *mac = strdup(client->mac); char *token = strdup(client->token); unsigned long long incoming = client->counters.incoming; unsigned long long outgoing = client->counters.outgoing; debug(LOG_INFO, "Got manual logout from client ip %s, mac %s, token %s", client->ip, client->mac, client->token); fw_deny(client->ip, client->mac, client->fw_connection_state); client_list_delete(client); /* Unlock client list here since auth_server_request may take a while */ UNLOCK_CLIENT_LIST(); /* Advertise the logout if we have an auth server */ if (config->auth_servers != NULL) { auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token, incoming, outgoing); } free(ip); free(mac); free(token); } else { /* Do nothing if the client is not in the client list (i.e. not logged in) */ debug(LOG_INFO, "Got manual logout from client %s, but client not in list", r->clientAddr); UNLOCK_CLIENT_LIST(); } if (config->auth_servers != NULL) { /* Re-direct them to auth server */ char *urlFragment = NULL; t_auth_serv *auth_server = get_auth_server(); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACCOUNT_LOGGED_OUT ); http_send_redirect_to_auth(r, urlFragment, "Redirect to logout message"); free(urlFragment); } }
void load_fwrule_conf(void) { FILE *fp = NULL; char buff[128]; int cnum = 0; char *ptr = NULL; char *ip = NULL; char *mac = NULL; char *token = NULL; t_client *client; if (NULL == (fp = fopen(WCLIENT_CONF, "r"))) { return ; } while (cnum < 256 && fgets(buff, sizeof(buff), fp) != NULL) { unsigned int len = strlen(buff); if (buff[len-1] == '\r' || buff[len-1] == '\n') { buff[len-1] = '\0'; } ip = strtok_r(buff, " ", &ptr); if (!ip) continue; mac = strtok_r(NULL, " ", &ptr); if (!mac) continue; token = strtok_r(NULL, " ", &ptr); if (!token) continue; // alloc a client and append it to client list if ((client = client_list_find_by_ip(ip)) == NULL) { client = client_list_append(ip, mac, token); client->fw_connection_state = FW_MARK_KNOWN; fw_allow(ip, mac, FW_MARK_KNOWN); debug(LOG_DEBUG, "load client %s %s %s", ip, mac, token); } cnum ++; } fclose(fp); }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], rc; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; debug(LOG_DEBUG, "begin iptables_fw_counters_update"); /* Look for outgoing traffic */ // modified by lijg , 2013-05-18, 修改获取上行流量 safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_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 %*s %*s %*s %*s", &counter, ip); //rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip); //debug(LOG_DEBUG, "outgoing >> %s -- %llu (%u)", ip, counter, rc); if (2 == 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: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, counter, p1->counters.last_updated); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s in client list, this should not happen unless if the gateway crashed", ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_OUTGOING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_INCOMING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_INCOMING); 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 %*s %15[0-9.]", &counter, ip); if (2 == 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 incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s in client list, this should not happen unless if the gateway crashed", ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_OUTGOING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, TABLE_WIFIDOG_INCOMING); iptables_fw_destroy_mention("mangle", TABLE_WIFIDOG_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); debug(LOG_DEBUG, "end iptables_fw_counters_update\n\n"); return 1; }
/** Authenticates a single client against the central server and returns when done * Alters the firewall rules depending on what the auth server says @param r httpd request struct */ void authenticate_client(request * r) { t_client *client, *tmp; t_authresponse auth_response; char *token; httpVar *var; char *urlFragment = NULL; s_config *config = NULL; t_auth_serv *auth_server = NULL; LOCK_CLIENT_LIST(); client = client_dup(client_list_find_by_ip(r->clientAddr)); UNLOCK_CLIENT_LIST(); if (client == NULL) { debug(LOG_ERR, "authenticate_client(): Could not find client for %s", r->clientAddr); return; } /* Users could try to log in(so there is a valid token in * request) even after they have logged in, try to deal with * this */ if ((var = httpdGetVariableByName(r, "token")) != NULL) { token = safe_strdup(var->value); } else { token = safe_strdup(client->token); } /* * At this point we've released the lock while we do an HTTP request since it could * take multiple seconds to do and the gateway would effectively be frozen if we * kept the lock. */ auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, client->ip, client->mac, token, 0, 0); LOCK_CLIENT_LIST(); /* can't trust the client to still exist after n seconds have passed */ tmp = client_list_find_by_client(client); if (NULL == tmp) { debug(LOG_ERR, "authenticate_client(): Could not find client node for %s (%s)", client->ip, client->mac); UNLOCK_CLIENT_LIST(); client_list_destroy(client); /* Free the cloned client */ free(token); return; } client_list_destroy(client); /* Free the cloned client */ client = tmp; if (strcmp(token, client->token) != 0) { /* If token changed, save it. */ free(client->token); client->token = token; } else { free(token); } /* Prepare some variables we'll need below */ config = config_get_config(); auth_server = get_auth_server(); switch (auth_response.authcode) { case AUTH_ERROR: /* Error talking to central server */ debug(LOG_ERR, "Got ERROR from central server authenticating token %s from %s at %s", client->token, client->ip, client->mac); send_http_page(r, "Error!", "Error: We did not get a valid answer from the central server"); break; case AUTH_DENIED: /* Central server said invalid token */ debug(LOG_INFO, "Got DENIED from central server authenticating token %s from %s at %s - deleting from firewall and redirecting them to denied message", client->token, client->ip, client->mac); fw_deny(client); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_DENIED); http_send_redirect_to_auth(r, urlFragment, "Redirect to denied message"); free(urlFragment); break; case AUTH_VALIDATION: /* They just got validated for X minutes to check their email */ debug(LOG_INFO, "Got VALIDATION from central server authenticating token %s from %s at %s" "- adding to firewall and redirecting them to activate message", client->token, client->ip, client->mac); fw_allow(client, FW_MARK_PROBATION); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACTIVATE_ACCOUNT); http_send_redirect_to_auth(r, urlFragment, "Redirect to activate message"); free(urlFragment); break; case AUTH_ALLOWED: /* Logged in successfully as a regular account */ debug(LOG_INFO, "Got ALLOWED from central server authenticating token %s from %s at %s - " "adding to firewall and redirecting them to portal", client->token, client->ip, client->mac); fw_allow(client, FW_MARK_KNOWN); // add by zp debug(LOG_INFO,"goto fw_allow()..."); served_this_session++; safe_asprintf(&urlFragment, "%sgw_id=%s", auth_server->authserv_portal_script_path_fragment, config->gw_id); // modify by zp http_send_redirect_to_auth(r, urlFragment, "Redirect to portal"); //char * text = "advertisement"; //http_send_redirect_to_advertisement(r, urlFragment, text); free(urlFragment); break; case AUTH_VALIDATION_FAILED: /* Client had X minutes to validate account by email and didn't = too late */ debug(LOG_INFO, "Got VALIDATION_FAILED from central server authenticating token %s from %s at %s " "- redirecting them to failed_validation message", client->token, client->ip, client->mac); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACCOUNT_VALIDATION_FAILED); http_send_redirect_to_auth(r, urlFragment, "Redirect to failed validation message"); free(urlFragment); break; default: debug(LOG_WARNING, "I don't know what the validation code %d means for token %s from %s at %s - sending error message", auth_response.authcode, client->token, client->ip, client->mac); send_http_page(r, "Internal Error", "We can not validate your request at this time"); break; } UNLOCK_CLIENT_LIST(); return; }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], rc; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; int fd; /* Look for outgoing traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_OUTGOING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } fprintf(stderr,"popen:"); /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; /*set nonblocking -> would need to change fscanf against read and buffer and other parsing logic fd = fileno(output); fcntl(fd, F_SETFL, O_NONBLOCK); */ while (output && !(feof(output))) { fprintf(stderr,"#"); rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s %*s", &counter, ip); //rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip); fprintf(stderr,"!"); if (2 == 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: Bytes=%llu", ip, counter); //here we deadlock sometimes,... LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, counter, p1->counters.last_updated); } } else { debug(LOG_ERR, "Could not find %s in client list", ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_INCOMING); iptables_insert_gateway_id(&script); output = popen(script, "r"); free(script); if (!output) { debug(LOG_ERR, "popen(): %s", strerror(errno)); return -1; } fprintf(stderr,"popen:"); /* skip the first two lines */ while (('\n' != fgetc(output)) && !feof(output)) ; while (('\n' != fgetc(output)) && !feof(output)) ; while (output && !(feof(output))) { fprintf(stderr,"#"); rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %*s %15[0-9.]", &counter, ip); fprintf(stderr,"!"); if (2 == 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 incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter); } } else { debug(LOG_ERR, "Could not find %s in client list", ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); return 1; }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], target[MAX_BUF]; int rc; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; /* Look for outgoing traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_OUTGOING); 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 ( !(feof(output) )) { rc = fscanf(output, "%*s %llu %s %*s %*s %*s %*s %15[0-9.]", &counter,target,ip); /* eat rest of line */ while (('\n' != fgetc(output)) && !feof(output)) {} if (3 == rc && !strcmp(target,"MARK")) { /* 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: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, counter, p1->counters.last_updated); } } else { debug(LOG_WARNING, "Could not find %s in client list", ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_INCOMING); 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 ( !(feof(output) )) { rc = fscanf(output, "%*s %llu %s %*s %*s %*s %*s %*s %15[0-9.]", &counter,target,ip); /* eat rest of line */ while (('\n' != fgetc(output)) && !feof(output)) {} if (3 == rc && !strcmp(target,"ACCEPT")) { /* 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 incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter); } } else { debug(LOG_WARNING, "Could not find %s in client list", ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); return 0; }
/** Initiates a transaction with the auth server, either to authenticate or to * update the traffic counters at the server @param authresponse Returns the information given by the central server @param request_type Use the REQUEST_TYPE_* defines in centralserver.h @param ip IP adress of the client this request is related to @param mac MAC adress of the client this request is related to @param token Authentification token of the client @param incoming Current counter of the client's total incoming traffic, in bytes @param outgoing Current counter of the client's total outgoing traffic, in bytes */ t_authcode auth_server_request(t_authresponse *authresponse, const char *request_type, const char *ip, const char *mac, const char *token, unsigned long long int incoming, unsigned long long int outgoing) { int sockfd; t_client *client; ssize_t numbytes; size_t totalbytes; char buf[MAX_BUF]; char *tmp; char *safe_token; int done, nfds; fd_set readfds; struct timeval timeout; t_auth_serv *auth_server = NULL; auth_server = get_auth_server(); /* Blanket default is error. */ authresponse->authcode = AUTH_ERROR; sockfd = in_connect_auth_server(auth_server); if (sockfd == -1) { /* Could not connect to any auth server */ return (AUTH_ERROR); } /** * TODO: XXX change the PHP so we can harmonize stage as request_type * everywhere. */ memset(buf, 0, sizeof(buf)); safe_token=httpdUrlEncode(token); snprintf(buf, (sizeof(buf) - 1), "GET %s%sstage=%s&ip=%s&mac=%s&token=%s&incoming=%llu&outgoing=%llu&gw_id=%s HTTP/1.0\r\n" "User-Agent: WiFiDog %s\r\n" "Host: %s\r\n" "\r\n", auth_server->authserv_path, auth_server->authserv_auth_script_path_fragment, request_type, ip, mac, safe_token, incoming, outgoing, config_get_config()->gw_id, VERSION, auth_server->authserv_hostname ); free(safe_token); debug(LOG_DEBUG, "Sending HTTP request to auth server: [%s]\n", buf); send(sockfd, buf, strlen(buf), 0); debug(LOG_DEBUG, "Reading response"); numbytes = totalbytes = 0; done = 0; do { FD_ZERO(&readfds); FD_SET(sockfd, &readfds); timeout.tv_sec = 30; /* XXX magic... 30 second is as good a timeout as any */ timeout.tv_usec = 0; nfds = sockfd + 1; nfds = select(nfds, &readfds, NULL, NULL, &timeout); if (nfds > 0) { /** We don't have to use FD_ISSET() because there * was only one fd. */ numbytes = read(sockfd, buf + totalbytes, MAX_BUF - (totalbytes + 1)); if (numbytes < 0) { debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno)); /* FIXME */ close(sockfd); return (AUTH_ERROR); } else if (numbytes == 0) { done = 1; } else { totalbytes += numbytes; debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes); } } else if (nfds == 0) { debug(LOG_ERR, "Timed out reading data via select() from auth server"); /* FIXME */ close(sockfd); return (AUTH_ERROR); } else if (nfds < 0) { debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno)); /* FIXME */ close(sockfd); return (AUTH_ERROR); } } while (!done); close(sockfd); buf[totalbytes] = '\0'; debug(LOG_DEBUG, "HTTP Response from Server: [%s]", buf); if ((tmp = strstr(buf, "Auth: "))) { if (sscanf(tmp, "Auth: %d", (int *)&authresponse->authcode) == 1) { debug(LOG_INFO, "Auth server returned authentication code %d", authresponse->authcode); if(authresponse->authcode == 1) { debug(LOG_INFO, "Auth server returned 1,then check bandwidth."); int bwdn=0,bwup=0; if ((tmp = strstr(buf, "Bwdn: "))) { if (sscanf(tmp, "Bwdn: %d", &bwdn) == 1) { debug(LOG_INFO, "Auth server returned user download bandwidth %d", bwdn); } } if ((tmp = strstr(buf, "Bwup: "))) { if (sscanf(tmp, "Bwup: %d", &bwup) == 1) { debug(LOG_INFO, "Auth server returned user upload bandwidth %d", bwup); } } if(bwdn==0 || bwup==0){ bwdn=config_get_config()->clientbandwidthdown; bwup=config_get_config()->clientbandwidthup; } LOCK_CLIENT_LIST(); client = client_list_find_by_ip(ip); if (client != NULL) { debug(LOG_DEBUG, "get bandwidth %d %d", bwdn,bwup); client->bwdn = bwdn; client->bwup = bwup; } UNLOCK_CLIENT_LIST(); } return(authresponse->authcode); } else { debug(LOG_WARNING, "Auth server did not return expected authentication code"); return(AUTH_ERROR); } } else { return(AUTH_ERROR); } /* XXX Never reached because of the above if()/else pair. */ return(AUTH_ERROR); }
/** Update the counters of all the clients in the client list */ int iptables_fw_counters_update(void) { FILE *output; char *script, ip[16], rc, mac[18]; unsigned long long int counter; t_client *p1; struct in_addr tempaddr; const s_config *config = config_get_config(); /* Look for outgoing traffic */ 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))) { //3554 390634 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MAC C0:38:96:96:74:7D MARK set 0x3 /*rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s %*s", &counter, ip);*/ //rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip); 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 ((p1 = client_list_find_by_ip(ip))) { p1->counters.active_duration--; if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { p1->counters.outgoing_delta = p1->counters.outgoing_history + counter - p1->counters.outgoing; p1->counters.outgoing = p1->counters.outgoing_history + counter; p1->counters.last_updated = time(NULL); debug(LOG_DEBUG, "%s(%s) - Outgoing traffic %llu bytes, updated counter.outgoing to %llu bytes. Updated last_updated to %d", ip, mac, counter, p1->counters.outgoing, p1->counters.last_updated); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s(%s) in client list, this should not happen unless if the gateway crashed", ip, mac); debug(LOG_ERR, "Preventively deleting firewall rules for %s(%s) in table %s", ip, mac, CHAIN_OUTGOING); iptables_fw_destroy_mention("mangle", CHAIN_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s(%s) in table %s", ip, mac, CHAIN_INCOMING); iptables_fw_destroy_mention("mangle", CHAIN_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); /* Look for incoming traffic */ safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_INCOMING); 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 %*s %15[0-9.]", &counter, ip); if (2 == 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 incoming traffic for %s: Bytes=%llu", ip, counter); LOCK_CLIENT_LIST(); if ((p1 = client_list_find_by_ip(ip))) { if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { p1->counters.incoming_delta = p1->counters.incoming_history + counter - p1->counters.incoming; p1->counters.incoming = p1->counters.incoming_history + counter; debug(LOG_DEBUG, "%s - Incoming traffic %llu bytes, Updated counter.incoming to %llu bytes", ip, counter, p1->counters.incoming); } } else { debug(LOG_ERR, "iptables_fw_counters_update(): Could not find %s in client list, this should not happen unless if the gateway crashed", ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, CHAIN_OUTGOING); iptables_fw_destroy_mention("mangle", CHAIN_OUTGOING, ip); debug(LOG_ERR, "Preventively deleting firewall rules for %s in table %s", ip, CHAIN_INCOMING); iptables_fw_destroy_mention("mangle", CHAIN_INCOMING, ip); } UNLOCK_CLIENT_LIST(); } } pclose(output); return 1; }
/** Authenticates a single client against the central server and returns when done * Alters the firewall rules depending on what the auth server says @param r httpd request struct */ void authenticate_client(request *r, char *gw_id) { t_client *client; t_authresponse auth_response; char *mac, *token; char *urlFragment = NULL; s_config *config = NULL; t_auth_serv *auth_server = NULL; LOCK_CLIENT_LIST(); client = client_list_find_by_ip(r->clientAddr); if (client == NULL) { debug(LOG_ERR, "Could not find client for %s", r->clientAddr); UNLOCK_CLIENT_LIST(); return; } mac = safe_strdup(client->mac); token = safe_strdup(client->token); UNLOCK_CLIENT_LIST(); /* * At this point we've released the lock while we do an HTTP request since it could * take multiple seconds to do and the gateway would effectively be frozen if we * kept the lock. */ auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, r->clientAddr, mac, token, 0, 0, gw_id); LOCK_CLIENT_LIST(); /* can't trust the client to still exist after n seconds have passed */ client = client_list_find(r->clientAddr, mac); if (client == NULL) { debug(LOG_ERR, "Could not find client node for %s (%s)", r->clientAddr, mac); UNLOCK_CLIENT_LIST(); free(token); free(mac); return; } free(token); free(mac); /* Prepare some variables we'll need below */ config = config_get_config(); auth_server = get_auth_server(); switch(auth_response.authcode) { case AUTH_ERROR: /* Error talking to central server */ debug(LOG_ERR, "Got %d from central server authenticating token %s from %s at %s", auth_response, client->token, client->ip, client->mac); send_http_page(r, "Error!", "Error: We did not get a valid answer from the central server"); break; case AUTH_DENIED: /* Central server said invalid token */ debug(LOG_INFO, "Got DENIED from central server authenticating token %s from %s at %s - redirecting them to denied message", client->token, client->ip, client->mac); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_DENIED ); http_send_redirect_to_auth(r, urlFragment, "Redirect to portal", gw_id); //set connection logged out (xperimental) //snprintf(,client->token, client->ip, client->mac) /*{ char mysqlCmd[256]; sprintf(mysqlCmd,"echo \"DELETE FROM connections WHERE token='%s';\"|mysql -uauthpuppy -pauthpuppydev authpuppy > /tmp/wifidog_deauth_mysql_result",client->token); debug(LOG_WARNING,"issuing this would help: %s",mysqlCmd); //system(mysqlCmd);//kills wifidog somehow *g }*/ free(urlFragment); //for race conditions, remove from firewall fw_deny(client->ip, client->mac, client->fw_connection_state); //experimental delete client from list client_list_delete(client); break; case AUTH_VALIDATION: /* They just got validated for X minutes to check their email */ debug(LOG_INFO, "Got VALIDATION from central server authenticating token %s from %s at %s" "- adding to firewall and redirecting them to activate message", client->token, client->ip, client->mac); client->fw_connection_state = FW_MARK_PROBATION; fw_allow(client->ip, client->mac, FW_MARK_PROBATION); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACTIVATE_ACCOUNT ); http_send_redirect_to_auth(r, urlFragment, "Redirect to activate message", gw_id); free(urlFragment); break; case AUTH_ALLOWED: /* Logged in successfully as a regular account */ debug(LOG_INFO, "Got ALLOWED from central server authenticating token %s from %s at %s - " "adding to firewall and redirecting them to portal", client->token, client->ip, client->mac); client->fw_connection_state = FW_MARK_KNOWN; fw_allow(client->ip, client->mac, FW_MARK_KNOWN); served_this_session++; safe_asprintf(&urlFragment, "%sgw_id=%s", auth_server->authserv_portal_script_path_fragment, gw_id ); http_send_redirect_to_auth(r, urlFragment, "Redirect to portal", gw_id); free(urlFragment); break; case AUTH_VALIDATION_FAILED: /* Client had X minutes to validate account by email and didn't = too late */ debug(LOG_INFO, "Got VALIDATION_FAILED from central server authenticating token %s from %s at %s " "- redirecting them to failed_validation message", client->token, client->ip, client->mac); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACCOUNT_VALIDATION_FAILED ); http_send_redirect_to_auth(r, urlFragment, "Redirect to failed validation message", gw_id); free(urlFragment); break; default: debug(LOG_WARNING, "I don't know what the validation code %d means for token %s from %s at %s - sending error message", auth_response.authcode, client->token, client->ip, client->mac); send_http_page(r, "Internal Error", "We can not validate your request at this time"); break; } UNLOCK_CLIENT_LIST(); return; }
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(); }