00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #define _GNU_SOURCE
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <pthread.h>
00035 #include <string.h>
00036 #include <unistd.h>
00037 #include <syslog.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <fcntl.h>
00041 #include <errno.h>
00042
00043 #include "httpd.h"
00044
00045 #include "safe.h"
00046 #include "debug.h"
00047 #include "conf.h"
00048 #include "auth.h"
00049 #include "firewall.h"
00050 #include "http.h"
00051 #include "httpd.h"
00052 #include "client_list.h"
00053 #include "common.h"
00054 #include "centralserver.h"
00055
00056 #include "util.h"
00057
00058 #include "../config.h"
00059
00060 extern pthread_mutex_t client_list_mutex;
00061
00063 void
00064 http_callback_404(httpd *webserver, request *r)
00065 {
00066 char tmp_url[MAX_BUF],
00067 *url;
00068 s_config *config = config_get_config();
00069 t_auth_serv *auth_server = get_auth_server();
00070
00071 memset(tmp_url, 0, sizeof(tmp_url));
00072
00073
00074
00075
00076
00077 snprintf(tmp_url, (sizeof(tmp_url) - 1), "http://%s%s%s%s",
00078 r->request.host,
00079 r->request.path,
00080 r->request.query[0] ? "?" : "",
00081 r->request.query);
00082 url = httpdUrlEncode(tmp_url);
00083
00084 if (!is_online()) {
00085
00086 char * buf;
00087 safe_asprintf(&buf,
00088 "<p>We apologize, but it seems that the internet connection that powers this hotspot is temporarily unavailable.</p>"
00089 "<p>If at all possible, please notify the owners of this hotspot that the internet connection is out of service.</p>"
00090 "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>"
00091 "<p>In a while please <a href='%s'>click here</a> to try your request again.</p>", tmp_url);
00092
00093 send_http_page(r, "Uh oh! Internet access unavailable!", buf);
00094 free(buf);
00095 debug(LOG_INFO, "Sent %s an apology since I am not online - no point sending them to auth server", r->clientAddr);
00096 }
00097 else if (!is_auth_online()) {
00098
00099 char * buf;
00100 safe_asprintf(&buf,
00101 "<p>We apologize, but it seems that we are currently unable to re-direct you to the login screen.</p>"
00102 "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>"
00103 "<p>In a couple of minutes please <a href='%s'>click here</a> to try your request again.</p>", tmp_url);
00104
00105 send_http_page(r, "Uh oh! Login screen unavailable!", buf);
00106 free(buf);
00107 debug(LOG_INFO, "Sent %s an apology since auth server not online - no point sending them to auth server", r->clientAddr);
00108 }
00109 else {
00110
00111 char *urlFragment;
00112 safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&url=%s",
00113 auth_server->authserv_login_script_path_fragment,
00114 config->gw_address,
00115 config->gw_port,
00116 config->gw_id,
00117 url);
00118 debug(LOG_INFO, "Captured %s requesting [%s] and re-directing them to login page", r->clientAddr, url);
00119 http_send_redirect_to_auth(r, urlFragment, "Redirect to login page");
00120 free(urlFragment);
00121 }
00122 free(url);
00123 }
00124
00125 void
00126 http_callback_wifidog(httpd *webserver, request *r)
00127 {
00128 send_http_page(r, "WiFiDog", "Please use the menu to navigate the features of this WiFiDog installation.");
00129 }
00130
00131 void
00132 http_callback_about(httpd *webserver, request *r)
00133 {
00134 send_http_page(r, "About WiFiDog", "This is WiFiDog version <strong>" VERSION "</strong>");
00135 }
00136
00137 void
00138 http_callback_status(httpd *webserver, request *r)
00139 {
00140 const s_config *config = config_get_config();
00141 char * status = NULL;
00142 char *buf;
00143
00144 if (config->httpdusername &&
00145 (strcmp(config->httpdusername, r->request.authUser) ||
00146 strcmp(config->httpdpassword, r->request.authPassword))) {
00147 debug(LOG_INFO, "Status page requested, forcing authentication");
00148 httpdForceAuthenticate(r, config->httpdrealm);
00149 return;
00150 }
00151
00152 status = get_status_text();
00153 safe_asprintf(&buf, "<pre>%s</pre>", status);
00154 send_http_page(r, "WiFiDog Status", buf);
00155 free(buf);
00156 free(status);
00157 }
00162 void http_send_redirect_to_auth(request *r, char *urlFragment, char *text)
00163 {
00164 char *protocol = NULL;
00165 int port = 80;
00166 t_auth_serv *auth_server = get_auth_server();
00167
00168 if (auth_server->authserv_use_ssl) {
00169 protocol = "https";
00170 port = auth_server->authserv_ssl_port;
00171 } else {
00172 protocol = "http";
00173 port = auth_server->authserv_http_port;
00174 }
00175
00176 char *url = NULL;
00177 safe_asprintf(&url, "%s://%s:%d%s%s",
00178 protocol,
00179 auth_server->authserv_hostname,
00180 port,
00181 auth_server->authserv_path,
00182 urlFragment
00183 );
00184 http_send_redirect(r, url, text);
00185 free(url);
00186 }
00187
00192 void http_send_redirect(request *r, char *url, char *text)
00193 {
00194 char *message = NULL;
00195 char *header = NULL;
00196 char *response = NULL;
00197
00198 debug(LOG_DEBUG, "Redirecting client browser to %s", url);
00199 safe_asprintf(&header, "Location: %s",
00200 url
00201 );
00202 if(text) {
00203 safe_asprintf(&response, "307 %s\n",
00204 text
00205 );
00206 }
00207 else {
00208 safe_asprintf(&response, "307 %s\n",
00209 "Redirecting"
00210 );
00211 }
00212 httpdSetResponse(r, response);
00213 httpdAddHeader(r, header);
00214 free(response);
00215 free(header);
00216 safe_asprintf(&message, "Please <a href='%s'>click here</a>.", url);
00217 send_http_page(r, text ? text : "Redirection to message", message);
00218 free(message);
00219 }
00220
00221 void
00222 http_callback_auth(httpd *webserver, request *r)
00223 {
00224 t_client *client;
00225 httpVar * token;
00226 char *mac;
00227 httpVar *logout = httpdGetVariableByName(r, "logout");
00228 if ((token = httpdGetVariableByName(r, "token"))) {
00229
00230 if (!(mac = arp_get(r->clientAddr))) {
00231
00232 debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr);
00233 send_http_page(r, "WiFiDog Error", "Failed to retrieve your MAC address");
00234 } else {
00235
00236
00237 LOCK_CLIENT_LIST();
00238
00239 if ((client = client_list_find(r->clientAddr, mac)) == NULL) {
00240 debug(LOG_DEBUG, "New client for %s", r->clientAddr);
00241 client_list_append(r->clientAddr, mac, token->value);
00242 } else if (logout) {
00243 t_authresponse authresponse;
00244 s_config *config = config_get_config();
00245 unsigned long long incoming = client->counters.incoming;
00246 unsigned long long outgoing = client->counters.outgoing;
00247 char *ip = safe_strdup(client->ip);
00248 char *urlFragment = NULL;
00249 t_auth_serv *auth_server = get_auth_server();
00250
00251 fw_deny(client->ip, client->mac, client->fw_connection_state);
00252 client_list_delete(client);
00253 debug(LOG_DEBUG, "Got logout from %s", client->ip);
00254
00255
00256 if (config->auth_servers != NULL) {
00257 UNLOCK_CLIENT_LIST();
00258 auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token->value,
00259 incoming, outgoing);
00260 LOCK_CLIENT_LIST();
00261
00262
00263 debug(LOG_INFO, "Got manual logout from client ip %s, mac %s, token %s"
00264 "- redirecting them to logout message", client->ip, client->mac, client->token);
00265 safe_asprintf(&urlFragment, "%smessage=%s",
00266 auth_server->authserv_msg_script_path_fragment,
00267 GATEWAY_MESSAGE_ACCOUNT_LOGGED_OUT
00268 );
00269 http_send_redirect_to_auth(r, urlFragment, "Redirect to logout message");
00270 free(urlFragment);
00271 }
00272 free(ip);
00273 }
00274 else {
00275 debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip);
00276 }
00277 UNLOCK_CLIENT_LIST();
00278 if (!logout) {
00279 authenticate_client(r);
00280 }
00281 free(mac);
00282 }
00283 } else {
00284
00285 send_http_page(r, "WiFiDog error", "Invalid token");
00286 }
00287 }
00288
00289 void send_http_page(request *r, const char *title, const char* message)
00290 {
00291 s_config *config = config_get_config();
00292 char *buffer;
00293 struct stat stat_info;
00294 int fd;
00295 ssize_t written;
00296
00297 fd=open(config->htmlmsgfile, O_RDONLY);
00298 if (fd==-1) {
00299 debug(LOG_CRIT, "Failed to open HTML message file %s: %s", config->htmlmsgfile, strerror(errno));
00300 return;
00301 }
00302
00303 if (fstat(fd, &stat_info)==-1) {
00304 debug(LOG_CRIT, "Failed to stat HTML message file: %s", strerror(errno));
00305 close(fd);
00306 return;
00307 }
00308
00309 buffer=(char*)safe_malloc(stat_info.st_size+1);
00310 written=read(fd, buffer, stat_info.st_size);
00311 if (written==-1) {
00312 debug(LOG_CRIT, "Failed to read HTML message file: %s", strerror(errno));
00313 free(buffer);
00314 close(fd);
00315 return;
00316 }
00317 close(fd);
00318
00319 buffer[written]=0;
00320 httpdAddVariable(r, "title", title);
00321 httpdAddVariable(r, "message", message);
00322 httpdAddVariable(r, "nodeID", config->gw_id);
00323 httpdOutput(r, buffer);
00324 free(buffer);
00325 }
00326