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..."); }
/** * @brief authenticated - called for all request from authenticated clients. * @param connection * @param ip_addr * @param mac * @param url * @param client * @return * * It's unsual to received request from clients which are already authed. * Happens when the user: * - clicked in multiple windows on "accept" -> redirect to origin - no checking * - when the user reloaded a splashpage -> redirect to origin * - when a user calls deny url -> deauth it */ static int authenticated(struct MHD_Connection *connection, const char *ip_addr, const char *mac, const char *url, t_client *client) { s_config *config = config_get_config(); const char *redirect_url; const char *host = NULL; char redirect_to_us[128]; MHD_get_connection_values(connection, MHD_HEADER_KIND, get_host_value_callback, &host); if (is_splashpage(host, url) || check_authdir_match(url, config->authdir)) { redirect_url = get_redirect_url(connection); /* TODO: what should we do when we get such request? */ if (redirect_url == NULL || strlen(redirect_url) == 0) return show_splashpage(connection, client); else return authenticate_client(connection, ip_addr, mac, redirect_url, client); } else if (check_authdir_match(url, config->denydir)) { auth_client_action(ip_addr, mac, AUTH_MAKE_DEAUTHENTICATED); snprintf(redirect_to_us, 128, "http://%s:%u/", config->gw_address, config->gw_port); return send_redirect_temp(connection, redirect_to_us); } /* user doesn't wants the splashpage or tried to auth itself */ return serve_file(connection, client, url); }
static void ndsctl_auth(int fd, char *arg) { t_client *client; char *ip, *mac; debug(LOG_DEBUG, "Entering ndsctl_auth..."); LOCK_CLIENT_LIST(); /* arg should be IP address of client */ debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg); /* Add client to client list... */ if ((client = client_list_add_client(arg)) == NULL) { debug(LOG_DEBUG, "Could not add client."); UNLOCK_CLIENT_LIST(); write(fd, "No", 2); return; } /* We have a client. Get both ip and mac address and authenticate */ ip = safe_strdup(client->ip); mac = safe_strdup(client->mac); UNLOCK_CLIENT_LIST(); auth_client_action(ip, mac, AUTH_MAKE_AUTHENTICATED); free(ip); free(mac); write(fd, "Yes", 3); debug(LOG_DEBUG, "Exiting ndsctl_auth..."); }
/** * @brief authenticate the client and redirect them * @param connection * @param ip_addr - needs to be freed * @param mac - needs to be freed * @param redirect_url - redirect the client to this url * @return */ static int authenticate_client(struct MHD_Connection *connection, const char *ip_addr, const char *mac, const char *redirect_url, t_client *client) { /* TODO: handle redirect_url == NULL */ auth_client_action(ip_addr, mac, AUTH_MAKE_AUTHENTICATED); return send_redirect_temp(connection, redirect_url); }
/** * @brief authenticated - called for all request from authenticated clients. * @param connection * @param ip_addr * @param mac * @param url * @param client * @return * * It's unsual to received request from clients which are already authed. * Happens when the user: * - clicked in multiple windows on "accept" -> redirect to origin - no checking * - when the user reloaded a splashpage -> redirect to origin * - when a user calls deny url -> deauth it */ static int authenticated(struct MHD_Connection *connection, const char *ip_addr, const char *mac, const char *url, t_client *client) { s_config *config = config_get_config(); const char *redirect_url; const char *host = NULL; char redirect_to_us[128]; MHD_get_connection_values(connection, MHD_HEADER_KIND, get_host_value_callback, &host); if (is_splashpage(host, url) || check_authdir_match(url, config->authdir)) { redirect_url = get_redirect_url(connection); /* TODO: what should we do when we get such request? */ if (redirect_url == NULL || strlen(redirect_url) == 0) return show_splashpage(connection, client); else return authenticate_client(connection, ip_addr, mac, redirect_url, client); } else if (check_authdir_match(url, config->denydir)) { auth_client_action(ip_addr, mac, AUTH_MAKE_DEAUTHENTICATED); snprintf(redirect_to_us, 128, "http://%s:%u/", config->gw_address, config->gw_port); return send_redirect_temp(connection, redirect_to_us); } /* check if this is an late request meaning the user tries to get the internet, but ended up here, * because the iptables rule came to late */ if (is_foreign_hosts(connection, host)) { /* might happen if the firewall rule isn't yet installed */ return send_refresh(connection); } /* user doesn't wants the splashpage or tried to auth itself */ return serve_file(connection, client, url); }
/** The multipurpose authentication action handler */ void http_nodogsplash_callback_action(request *r, t_auth_target *authtarget, t_authaction action) { t_client *client; char *mac; const char *ip; char *clienttoken = NULL; const char *requesttoken = authtarget->token; const char *redir = authtarget->redir; ip = r->clientAddr; if(!requesttoken) { debug(LOG_NOTICE, "No token in request from ip %s", ip); return; } if(!redir) { debug(LOG_NOTICE, "No redirect in request from ip %s", ip); return; } if (!(mac = arp_get(ip))) { /* We could not get their MAC address */ debug(LOG_NOTICE, "Could not arp MAC address for %s action %d", ip, action); return; } /* We have their MAC address, find them on the client list */ LOCK_CLIENT_LIST(); client = client_list_find(ip,mac); if(client && client->token) { clienttoken = safe_strdup(client->token); } UNLOCK_CLIENT_LIST(); if(!client) { debug(LOG_NOTICE, "Client %s %s action %d is not on client list", ip, mac, action); http_nodogsplash_serve_info(r, "Nodogsplash Error", "You are not on the client list."); free(mac); return; } /* We have a client */ /* Do we have a client token? */ if(!clienttoken) { debug(LOG_NOTICE, "Client %s %s action %d does not have a token", ip, mac, action); free(mac); return; } debug(LOG_DEBUG, "Action %d: %s %s tokens %s, %s", action, ip, mac, clienttoken, requesttoken); debug(LOG_DEBUG, "Redirect: %s", redir); /* Check token match */ if (strcmp(clienttoken,requesttoken)) { /* tokens don't match, reject */ debug(LOG_NOTICE, "Client %s %s tokens %s, %s do not match", r->clientAddr, mac, clienttoken, requesttoken); http_nodogsplash_serve_info(r, "Nodogsplash Error", "Tokens do not match."); free(mac); free(clienttoken); return; } /* Log value of info string, if any */ if(authtarget->info) { debug(LOG_NOTICE, "Client %s %s info: %s", ip, mac, authtarget->info); } /* take action */ switch(action) { case AUTH_MAKE_AUTHENTICATED: auth_client_action(ip,mac,action); http_nodogsplash_redirect(r, redir); break; case AUTH_MAKE_DEAUTHENTICATED: auth_client_action(ip,mac,action); http_nodogsplash_serve_info(r, "Nodogsplash Deny", "Authentication revoked."); break; default: debug(LOG_ERR, "Unknown auth action: %d", action); } free(mac); free(clienttoken); return; }
static int check_token_is_valid(struct MHD_Connection *connection, t_client *client) { /* token check */ struct collect_query_key token_key = { .key = "token" }; struct collect_query_key tok_key = { .key = "tok" }; MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &collect_query_key, &token_key); MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &collect_query_key, &tok_key); /* token not found in query string */ if (!token_key.value && !tok_key.value) return 0; if (token_key.value && !strcmp(client->token, token_key.value)) return 1; if (tok_key.value && !strcmp(client->token, tok_key.value)) return 1; return 0; } /** * @brief try_to_authenticate * @param connection * @param client * @param host * @param url * @return */ static int try_to_authenticate(struct MHD_Connection *connection, t_client *client, const char *host, const char *url) { /* a successful auth looks like * http://192.168.42.1:2050/nodogsplash_auth/?redir=http%3A%2F%2Fberlin.freifunk.net%2F&tok=94c4cdd2 * when authaction -> http://192.168.42.1:2050/nodogsplash_auth/ */ s_config *config = config_get_config(); /* we are checking here for the second '/' of /denydir/ */ if (check_authdir_match(url, config->authdir)) { /* matched to authdir */ if (check_token_is_valid(connection, client)) { return 1; /* valid token */ } } else if (check_authdir_match(url, config->denydir)) { /* matched to deauth */ /* TODO: do we need denydir? */ return 0; } return 0; } /** * @brief authenticate the client and redirect them * @param connection * @param ip_addr - needs to be freed * @param mac - needs to be freed * @param redirect_url - redirect the client to this url * @return */ static int authenticate_client(struct MHD_Connection *connection, const char *ip_addr, const char *mac, const char *redirect_url, t_client *client) { /* TODO: handle redirect_url == NULL */ auth_client_action(ip_addr, mac, AUTH_MAKE_AUTHENTICATED); if (redirect_url) return send_redirect_temp(connection, redirect_url); else return send_error(connection, 200); }