/** * @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); }
void http_callback_auth(httpd *webserver, request *r) { t_client *client; httpVar * token; char *mac; if ((token = httpdGetVariableByName(r, "token"))) { /* They supplied variable "token" */ if (!(mac = arp_get(r->clientAddr))) { /* We could not get their MAC address */ debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr); send_http_page(r, "WiFiDog Error", "Failed to retrieve your MAC address"); } else { /* We have their MAC address */ LOCK_CLIENT_LIST(); if ((client = client_list_find(r->clientAddr, mac)) == NULL) { debug(LOG_DEBUG, "New client for %s", r->clientAddr); client_list_append(r->clientAddr, mac, token->value); } else { debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip); } UNLOCK_CLIENT_LIST(); authenticate_client(r); free(mac); } } else { /* They did not supply variable "token" */ send_http_page(r, "WiFiDog error", "Invalid token"); } }
static int write_connection_cb(server_generic_client_t *client) { assert(!(client->state & SERVER_GENERIC_CLIENT_STATE_CLOSING)); if ( client->state & SERVER_GENERIC_CLIENT_STATE_ACCEPTED ) return client->server->write(client); else { server_generic_notify_write_disable(client); return authenticate_client(client->server, client); } }
/* * callback called by server-logic when data is available for reading. * We direct the message either to the authentication process either * to the real data handling function. * * If the authentication function return -1 (error), this will cause * server-logic to call the close_connection_cb callback. */ static int read_connection_cb(server_generic_client_t *client) { int ret = 0; assert(!(client->state & SERVER_GENERIC_CLIENT_STATE_CLOSING)); if ( client->state & SERVER_GENERIC_CLIENT_STATE_ACCEPTED ) ret = client->server->read(client); else ret = authenticate_client(client->server, client); return ret; }
/** * @brief preauthenticated - called for all request of a client in this state. * @param connection * @param ip_addr * @param mac * @return */ static int preauthenticated(struct MHD_Connection *connection, const char *ip_addr, const char *mac, const char *url, t_client *client) { char *host = NULL; const char *redirect_url; s_config *config = config_get_config(); if (!client) { client = add_client(ip_addr); if (!client) return send_error(connection, 503); } MHD_get_connection_values(connection, MHD_HEADER_KIND, get_host_value_callback, &host); /* check if this is a redirect querty with a foreign host as target */ if(is_foreign_hosts(connection, host)) { return redirect_to_splashpage(connection, client, host, url); } /* request is directed to us */ /* check if client wants to be authenticated */ if(check_authdir_match(url, config->authdir)) { /* Only the first request will redirected to config->redirectURL. * When the client reloads a page when it's authenticated, it should be redirected * to their origin url */ if (config->redirectURL) redirect_url = config->redirectURL; else redirect_url = get_redirect_url(connection); if (try_to_authenticate(connection, client, host, url)) { return authenticate_client(connection, ip_addr, mac, redirect_url, client); } else { /* user used an invalid token, redirect to splashpage but hold query "redir" intact */ return encode_and_redirect_to_splashpage(connection, redirect_url); } } if(is_splashpage(host, url)) { return show_splashpage(connection, client); } /* no special handling left - try to serve static content to the user */ return serve_file(connection, client, url); }
void http_callback_auth(httpd * webserver, request * r) { t_client *client; httpVar *token; char *mac; httpVar *logout = httpdGetVariableByName(r, "logout"); const s_config *config = config_get_config(); if ((token = httpdGetVariableByName(r, "token"))) { /* They supplied variable "token" */ if (!(mac = arp_get(r->clientAddr))) { /* We could not get their MAC address */ debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr); send_http_page(r, "WiFiDog Error", "Failed to retrieve your MAC address"); } else { t_redir_node *node; int index = 0; LOCK_REDIR(); node = redir_list_find(mac); if (node) { index = node->wlindex; } UNLOCK_REDIR(); /* We have their MAC address */ LOCK_CLIENT_LIST(); if ((client = client_list_find(r->clientAddr, mac)) == NULL) { debug(LOG_DEBUG, "New client for %s", r->clientAddr); client = client_list_add(r->clientAddr, mac, token->value); client->fw_connection_state = FW_MARK_REDIR; client->counters.active_duration = config->sessiontimeout[index-1]; } else if (logout) { logout_client(client); } else { debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip); } UNLOCK_CLIENT_LIST(); if (!logout) { /* applies for case 1 and 3 from above if */ authenticate_client(r); } free(mac); } } else { /* They did not supply variable "token" */ send_http_page(r, "WiFiDog error", "Invalid token"); } }
/** * @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); }
void http_callback_auth(httpd *webserver, request *r) { t_client *client; httpVar * token; char *mac; httpVar *logout = httpdGetVariableByName(r, "logout"); if ((token = httpdGetVariableByName(r, "token"))) { /* They supplied variable "token" */ if (!(mac = arp_get(r->clientAddr))) { /* We could not get their MAC address */ debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr); send_http_page(r, "WiFiDog Error", "Failed to retrieve your MAC address"); } else { /* We have their MAC address */ LOCK_CLIENT_LIST(); if ((client = client_list_find(r->clientAddr, mac)) == NULL) { debug(LOG_DEBUG, "New client for %s", r->clientAddr); client_list_append(r->clientAddr, mac, token->value); } else if (logout) { t_authresponse authresponse; s_config *config = config_get_config(); unsigned long long incoming = client->counters.incoming; unsigned long long outgoing = client->counters.outgoing; char *ip = safe_strdup(client->ip); char *urlFragment = NULL; t_auth_serv *auth_server = get_auth_server(); fw_deny(client->ip, client->mac, client->fw_connection_state); client_list_delete(client); debug(LOG_DEBUG, "Got logout from %s", client->ip); /* Advertise the logout if we have an auth server */ if (config->auth_servers != NULL) { UNLOCK_CLIENT_LIST(); auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token->value, incoming, outgoing); LOCK_CLIENT_LIST(); /* Re-direct them to auth server */ debug(LOG_INFO, "Got manual logout from client ip %s, mac %s, token %s" "- redirecting them to logout message", client->ip, client->mac, client->token); 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); } free(ip); } else { debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip); } UNLOCK_CLIENT_LIST(); if (!logout) { authenticate_client(r); } free(mac); } } else { /* They did not supply variable "token" */ send_http_page(r, "WiFiDog error", "Invalid token"); } }
void check_config(void) { char buf[BUFSIZ]; char aclfile[MAXPATHLEN]; char *tools_dir=NULL; char *tree_owner=NULL; char *map_file=NULL; char *cmd; char *p; char *q=(char *)""; FILE *fp; int cmdfound; char *uniq_str_arg; struct stat st; struct passwd *pw; char * bufptr; BOOLEAN matched; int i; char * dummy; if (debug) diag("checking config"); if ( !batch ) { tree_base = *arglist++; tree_owner = *arglist++; } /* if */ cmd = *arglist; if (debug) diag("command: %s", cmd ); if ( strcmp ( cmd, "odexm_begin") == 0 ) { start_batch = 1; return; } /* if */ if ( strcmp ( cmd, "odexm_end") == 0 ) { end_batch = 1; return; } /* if */ if ( first ) { first = FALSE; if ((fp = fopen( conf_file, "r")) == NULL) efatal("fopen %s", conf_file); matched = FALSE; while ( fgets( buf, sizeof(buf), fp ) != NULL) { rm_newline ( buf ); bufptr = (char *) buf; uniq_str_arg = strdup ( nxtarg ( &bufptr, " \t" ) ); if ( strcmp ( uniq_str_arg, uniq_str ) != 0 ) continue; /* if */ matched = TRUE; if ( batch ) tree_base = strdup ( nxtarg ( &bufptr, " \t" ) ); else /* Skip over argument */ dummy = nxtarg ( &bufptr, " \t" ); /* if */ tools_dir = strdup ( nxtarg ( &bufptr, " \t" ) ); if ( batch ) tree_owner = strdup ( nxtarg ( &bufptr, " \t" ) ); else /* Skip over argument */ dummy = nxtarg ( &bufptr, " \t" ); /* if */ map_file = strdup ( nxtarg ( &bufptr, " \t" ) ); break; } /* while */ fclose ( fp ); if ( ! matched ) { sprintf (buf, "No match for unique string %s\nin configuration file %s.\n", uniq_str, conf_file ); fatal (buf); } if (debug) diag("map file %s", map_file ); if (lstat(map_file, &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG) { sprintf(buf, "Invalid odexm map file: %s\n", map_file); fatal(buf); } if (debug) diag("map file mode ok"); if ((pw = getpwnam(tree_owner)) == NULL) fatal("Owner of directory not found"); if (pw -> pw_uid == 0) fatal("Cannot run as root"); if (setgid(pw->pw_gid) < 0) efatal("setgid"); if (setuid(pw->pw_uid) < 0) efatal("setuid"); if (chdir(tree_base) < 0) efatal("chdir"); if (debug) diag("setuid/chdir ok"); (void) concat ( exec_path, sizeof (exec_path), tools_dir, ":/bin:/usr/bin:/usr/ucb", NULL ); if ((fp = fopen(map_file, "r")) == NULL) efatal("map file fopen"); i = 0; while ((p = fgets(buf, sizeof(buf), fp)) != NULL) { if ((q = strrchr (p, '\n')) != NULL) *q = '\0'; q = nxtarg(&p, " \t"); strcpy ( map_data [i].cmd, q ); q = nxtarg(&p, " \t"); strcpy ( map_data [i].bin, q ); q = nxtarg(&p, " \t"); strcpy ( map_data [i].acl, q ); i++; } map_entries = i; (void) fclose(fp); } /* if */ if ( tempslot != 0 && !made_temp_dir ) { made_temp_dir = TRUE; concat ( tempdir, sizeof(tempdir), tree_base, "/#odexmXXXXXX", NULL); if ( opentemp(tempdir, tempdir ) < 0) { efatal("opentemp %s failed", tree_base); } } /* if */ cmdfound = FALSE; if ( strcmp ( cmd, "odexm_cp" ) != 0 ) { for ( i = 0; i < map_entries; i++ ) { if (strcmp( map_data [i].cmd, cmd) == 0) { cmdfound = TRUE; (void) strcpy(aclfile, q); strcpy ( cmdbuf, map_data [i].bin ); } /* if */ } /* for */ if (!cmdfound) { sprintf (buf, "No match for command %s in map file %s.\n", cmd, map_file ); fatal("%s", buf); } if (debug) diag("command %s acl %s temp %s", cmdbuf, aclfile, tempdir); /* if */ } /* if */ if ( !batch ) authenticate_client (); /* if */ }
/*ARGSUSED*/ void main( int argc, char **argv) { errdesc = 1; debug = 0; if ( argc == 2 ) { conf_file = *(argv+1); } /* if */ /* * setup network connections */ setup_connections(); if ( batch ) { /* * check authentication */ authenticate_client(); read_config_info (); } else { strcpy ( uniq_str, "kxct-compatible" ); } /* if */ for (;;) { /* * read argument list for command */ read_arglist(); /* * check configuration */ check_config(); if ( start_batch ) { start_batch = 0; continue; } /* if */ if ( end_batch ) { break; } /* if */ /* * receive data file */ if (tempslot != 0) receive_data(); /* * execute command */ run_command(); /* * transmit data file */ if (tempslot != 0) transmit_data(); /* * transmit the exit status */ transmit_status(); if ( ! batch ) { break; } /* if */ } /* * that is all */ if ( made_temp_dir ) (void) rmdir(tempdir); /* if */ exit(0); }