http.c

Go to the documentation of this file.
00001 /********************************************************************\
00002  * This program is free software; you can redistribute it and/or    *
00003  * modify it under the terms of the GNU General Public License as   *
00004  * published by the Free Software Foundation; either version 2 of   *
00005  * the License, or (at your option) any later version.              *
00006  *                                                                  *
00007  * This program is distributed in the hope that it will be useful,  *
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00010  * GNU General Public License for more details.                     *
00011  *                                                                  *
00012  * You should have received a copy of the GNU General Public License*
00013  * along with this program; if not, contact:                        *
00014  *                                                                  *
00015  * Free Software Foundation           Voice:  +1-617-542-5942       *
00016  * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
00017  * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
00018  *                                                                  *
00019  \********************************************************************/
00020 
00021 /* $Id: http.c 1340 2008-03-25 02:22:37Z benoitg $ */
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 
00039 #include "httpd.h"
00040 
00041 #include "safe.h"
00042 #include "debug.h"
00043 #include "conf.h"
00044 #include "auth.h"
00045 #include "firewall.h"
00046 #include "http.h"
00047 #include "httpd.h"
00048 #include "client_list.h"
00049 #include "common.h"
00050 #include "centralserver.h"
00051 
00052 #include "util.h"
00053 
00054 #include "../config.h"
00055 
00056 extern pthread_mutex_t  client_list_mutex;
00057 
00059 void
00060 http_callback_404(httpd *webserver, request *r)
00061 {
00062         char            *urlFragment,
00063                         tmp_url[MAX_BUF],
00064                         *url;
00065         s_config        *config = config_get_config();
00066         t_auth_serv     *auth_server = get_auth_server();
00067 
00068         memset(tmp_url, 0, sizeof(tmp_url));
00069         /* 
00070          * XXX Note the code below assumes that the client's request is a plain
00071          * http request to a standard port. At any rate, this handler is called only
00072          * if the internet/auth server is down so it's not a huge loss, but still.
00073          */
00074         snprintf(tmp_url, (sizeof(tmp_url) - 1), "http://%s%s%s%s",
00075                         r->request.host,
00076                         r->request.path,
00077                         r->request.query[0] ? "?" : "",
00078                         r->request.query);
00079         url = httpdUrlEncode(tmp_url);
00080 
00081         if (!is_online()) {
00082                 /* The internet connection is down at the moment  - apologize and do not redirect anywhere */
00083                 http_wifidog_header(r, "<h2>Uh oh! Internet access unavailable</h2>");
00084                 httpdOutput(r, "<p>We apologize, but it seems that the internet connection that powers this hotspot is temporarily unavailable.</p>");
00085                 httpdOutput(r, "<p>If at all possible, please notify the owners of this hotspot that the internet connection is out of service.</p>");
00086                 httpdOutput(r, "<p>The maintainers of this network are aware of this disruption.  We hope that this situation will be resolved soon.</p>");
00087                 httpdPrintf(r, "<p>In a while please <a href='%s'>click here</a> to try your request again.</p>", tmp_url);
00088                 http_wifidog_footer(r);
00089                 debug(LOG_INFO, "Sent %s an apology since I am not online - no point sending them to auth server", r->clientAddr);
00090         }
00091         else if (!is_auth_online()) {
00092                 /* The auth server is down at the moment - apologize and do not redirect anywhere */
00093                 http_wifidog_header(r, "<h2>Uh oh! Login screen unavailable</h2>");
00094                 httpdOutput(r, "<p>We apologize, but it seems that we are currently unable to re-direct you to the login screen.</p>");
00095                 httpdOutput(r, "<p>The maintainers of this network are aware of this disruption.  We hope that this situation will be resolved soon.</p>");
00096                 httpdPrintf(r, "<p>In a couple of minutes please <a href='%s'>click here</a> to try your request again.</p>", tmp_url);
00097                 http_wifidog_footer(r);
00098                 debug(LOG_INFO, "Sent %s an apology since auth server not online - no point sending them to auth server", r->clientAddr);
00099         }
00100         else {
00101                 /* Re-direct them to auth server */
00102                 safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&url=%s",
00103                         auth_server->authserv_login_script_path_fragment,
00104                         config->gw_address,
00105                         config->gw_port, 
00106                         config->gw_id,
00107                         url);
00108                 debug(LOG_INFO, "Captured %s requesting [%s] and re-directing them to login page", r->clientAddr, url);
00109                 http_send_redirect_to_auth(r, urlFragment, "Redirect to login page");
00110                 free(urlFragment);
00111         }
00112         free(url);
00113 }
00114 
00115 void 
00116 http_callback_wifidog(httpd *webserver, request *r)
00117 {
00118         http_wifidog_header(r, "WiFiDog");
00119         httpdOutput(r, "Please use the menu to navigate the features of this WiFiDog installation.");
00120         http_wifidog_footer(r);
00121 }
00122 
00123 void 
00124 http_callback_about(httpd *webserver, request *r)
00125 {
00126         http_wifidog_header(r, "About WiFiDog");
00127         httpdOutput(r, "This is WiFiDog version <b>" VERSION "</b>");
00128         http_wifidog_footer(r);
00129 }
00130 
00131 void 
00132 http_callback_status(httpd *webserver, request *r)
00133 {
00134         char * status = NULL;
00135         status = get_status_text();
00136         http_wifidog_header(r, "WiFiDog Status");
00137         httpdOutput(r, "<pre>");
00138         httpdOutput(r, status);
00139         httpdOutput(r, "</pre>");
00140         http_wifidog_footer(r);
00141         free(status);
00142 }
00147 void http_send_redirect_to_auth(request *r, char *urlFragment, char *text)
00148 {
00149         char *protocol = NULL;
00150         int port = 80;
00151         t_auth_serv     *auth_server = get_auth_server();
00152 
00153         if (auth_server->authserv_use_ssl) {
00154                 protocol = "https";
00155                 port = auth_server->authserv_ssl_port;
00156         } else {
00157                 protocol = "http";
00158                 port = auth_server->authserv_http_port;
00159         }
00160                                         
00161         char *url = NULL;
00162         safe_asprintf(&url, "%s://%s:%d%s%s",
00163                 protocol,
00164                 auth_server->authserv_hostname,
00165                 port,
00166                 auth_server->authserv_path,
00167                 urlFragment
00168         );
00169         http_send_redirect(r, url, text);
00170         free(url);      
00171 }
00172 
00177 void http_send_redirect(request *r, char *url, char *text)
00178 {
00179                 char *header = NULL;
00180                 char *response = NULL;
00181                                                         /* Re-direct them to auth server */
00182                 debug(LOG_DEBUG, "Redirecting client browser to %s", url);
00183                 safe_asprintf(&header, "Location: %s",
00184                         url
00185                 );
00186                 if(text) {
00187                         safe_asprintf(&response, "307 %s\n",
00188                                 text
00189                         );      
00190                 }
00191                 else {
00192                         safe_asprintf(&response, "307 %s\n",
00193                                 "Redirecting"
00194                         );              
00195                 }       
00196                 httpdSetResponse(r, response);
00197                 httpdAddHeader(r, header);
00198                 free(response);
00199                 free(header);   
00200                 if(text) {
00201                         http_wifidog_header(r, text);
00202                 }
00203                 else {
00204                         http_wifidog_header(r, "Redirection to message");
00205                 }               
00206 
00207                 httpdPrintf(r, "Please <a href='%s'>click here</a>.",
00208                         url
00209                 );
00210                 http_wifidog_footer(r);
00211 }
00212 
00213 void 
00214 http_callback_auth(httpd *webserver, request *r)
00215 {
00216         t_client        *client;
00217         httpVar * token;
00218         char    *mac;
00219         httpVar *logout = httpdGetVariableByName(r, "logout");
00220         if ((token = httpdGetVariableByName(r, "token"))) {
00221                 /* They supplied variable "token" */
00222                 if (!(mac = arp_get(r->clientAddr))) {
00223                         /* We could not get their MAC address */
00224                         debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr);
00225                         http_wifidog_header(r, "WiFiDog Error");
00226                         httpdOutput(r, "Failed to retrieve your MAC address");
00227                         http_wifidog_footer(r);
00228                 } else {
00229                         /* We have their MAC address */
00230 
00231                         LOCK_CLIENT_LIST();
00232                         
00233                         if ((client = client_list_find(r->clientAddr, mac)) == NULL) {
00234                                 debug(LOG_DEBUG, "New client for %s", r->clientAddr);
00235                                 client_list_append(r->clientAddr, mac, token->value);
00236                         } else if (logout) {
00237                             t_authresponse  authresponse;
00238                             s_config *config = config_get_config();
00239                             unsigned long long incoming = client->counters.incoming;
00240                             unsigned long long outgoing = client->counters.outgoing;
00241                             char *ip = safe_strdup(client->ip);
00242                             char *urlFragment = NULL;
00243                             t_auth_serv *auth_server = get_auth_server();
00244                                                                 
00245                             fw_deny(client->ip, client->mac, client->fw_connection_state);
00246                             client_list_delete(client);
00247                             debug(LOG_DEBUG, "Got logout from %s", client->ip);
00248                             
00249                             /* Advertise the logout if we have an auth server */
00250                             if (config->auth_servers != NULL) {
00251                                         UNLOCK_CLIENT_LIST();
00252                                         auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token->value, 
00253                                                                             incoming, outgoing);
00254                                         LOCK_CLIENT_LIST();
00255                                         
00256                                         /* Re-direct them to auth server */
00257                                         debug(LOG_INFO, "Got manual logout from client ip %s, mac %s, token %s"
00258                                         "- redirecting them to logout message", client->ip, client->mac, client->token);
00259                                         safe_asprintf(&urlFragment, "%smessage=%s",
00260                                                 auth_server->authserv_msg_script_path_fragment,
00261                                                 GATEWAY_MESSAGE_ACCOUNT_LOGGED_OUT
00262                                         );
00263                                         http_send_redirect_to_auth(r, urlFragment, "Redirect to logout message");
00264                                         free(urlFragment);
00265                             }
00266                             free(ip);
00267                         } 
00268                         else {
00269                                 debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip);
00270                         }
00271                         UNLOCK_CLIENT_LIST();
00272                         if (!logout) {
00273                                 authenticate_client(r);
00274                         }
00275                         free(mac);
00276                 }
00277         } else {
00278                 /* They did not supply variable "token" */
00279                 http_wifidog_header(r, "WiFiDog Error");
00280                 httpdOutput(r, "Invalid token");
00281                 http_wifidog_footer(r);
00282         }
00283 }
00284 
00285 void
00286 http_wifidog_header(request *r, char *title)
00287 {
00288     httpdOutput(r, "<html>\n");
00289     httpdOutput(r, "<head>\n");
00290     httpdPrintf(r, "<title>%s</title>\n", title);
00291     httpdOutput(r, "<meta HTTP-EQUIV='Pragma' CONTENT='no-cache'>\n");
00292 
00293     httpdOutput(r, "<style>\n");
00294     httpdOutput(r, "body {\n");
00295     httpdOutput(r, "  margin: 10px 60px 0 60px; \n");
00296     httpdOutput(r, "  font-family : bitstream vera sans, sans-serif;\n");
00297     httpdOutput(r, "  color: #46a43a;\n");
00298     httpdOutput(r, "}\n");
00299 
00300     httpdOutput(r, "a {\n");
00301     httpdOutput(r, "  color: #46a43a;\n");
00302     httpdOutput(r, "}\n");
00303 
00304     httpdOutput(r, "a:active {\n");
00305     httpdOutput(r, "  color: #46a43a;\n");
00306     httpdOutput(r, "}\n");
00307 
00308     httpdOutput(r, "a:link {\n");
00309     httpdOutput(r, "  color: #46a43a;\n");
00310     httpdOutput(r, "}\n");
00311 
00312     httpdOutput(r, "a:visited {\n");
00313     httpdOutput(r, "  color: #46a43a;\n");
00314     httpdOutput(r, "}\n");
00315 
00316     httpdOutput(r, "#header {\n");
00317     httpdOutput(r, "  height: 30px;\n");
00318     httpdOutput(r, "  background-color: #B4F663;\n");
00319     httpdOutput(r, "  padding: 20px;\n");
00320     httpdOutput(r, "  font-size: 20pt;\n");
00321     httpdOutput(r, "  text-align: center;\n");
00322     httpdOutput(r, "  border: 2px solid #46a43a;\n");
00323     httpdOutput(r, "  border-bottom: 0;\n");
00324     httpdOutput(r, "}\n");
00325 
00326     httpdOutput(r, "#menu {\n");
00327     httpdOutput(r, "  width: 200px;\n");
00328     httpdOutput(r, "  float: right;\n");
00329     httpdOutput(r, "  background-color: #B4F663;\n");
00330     httpdOutput(r, "  border: 2px solid #46a43a;\n");
00331     httpdOutput(r, "  font-size: 80%;\n");
00332     httpdOutput(r, "  min-height: 300px;\n");
00333     httpdOutput(r, "}\n");
00334 
00335     httpdOutput(r, "#menu h2 {\n");
00336     httpdOutput(r, "  margin: 0;\n");
00337     httpdOutput(r, "  background-color: #46a43a;\n");
00338     httpdOutput(r, "  text-align: center;\n");
00339     httpdOutput(r, "  color: #B4F663;\n");
00340     httpdOutput(r, "}\n");
00341 
00342     httpdOutput(r, "#copyright {\n");
00343     httpdOutput(r, "}\n");
00344 
00345     httpdOutput(r, "#content {\n");
00346     httpdOutput(r, "  padding: 20px;\n");
00347     httpdOutput(r, "  border: 2px solid #46a43a;\n");
00348     httpdOutput(r, "  min-height: 300px;\n");
00349     httpdOutput(r, "}\n");
00350     httpdOutput(r, "</style>\n");
00351 
00352     httpdOutput(r, "</head>\n");
00353 
00354     httpdOutput(r, "<body\n");
00355 
00356     httpdOutput(r, "<div id=\"header\">\n");
00357     httpdPrintf(r, "    %s\n", title);
00358     httpdOutput(r, "</div>\n");
00359 
00360     httpdOutput(r, "<div id=\"menu\">\n");
00361 
00362 
00363     httpdOutput(r, "    <h2>Info</h2>\n");
00364     httpdOutput(r, "    <ul>\n");
00365     httpdOutput(r, "    <li>Version: " VERSION "\n");
00366     httpdPrintf(r, "    <li>Node ID: %s\n", config_get_config()->gw_id);
00367     httpdOutput(r, "    </ul>\n");
00368     httpdOutput(r, "    <br>\n");
00369 
00370     httpdOutput(r, "    <h2>Menu</h2>\n");
00371     httpdOutput(r, "    <ul>\n");
00372     httpdOutput(r, "    <li><a href='/wifidog/status'>WiFiDog Status</a>\n");
00373     httpdOutput(r, "    <li><a href='/wifidog/about'>About WiFiDog</a>\n");
00374     httpdOutput(r, "    <li><a href='http://www.wifidog.org'>WiFiDog's homepage</a>\n");
00375     httpdOutput(r, "    </ul>\n");
00376     httpdOutput(r, "</div>\n");
00377 
00378     httpdOutput(r, "<div id=\"content\">\n");
00379     httpdPrintf(r, "<h2>%s</h2>\n", title);
00380 }
00381 
00382 void
00383 http_wifidog_footer(request *r)
00384 {
00385         httpdOutput(r, "</div>\n");
00386 
00387     httpdOutput(r, "<div id=\"copyright\">\n");
00388     httpdOutput(r, "Copyright (C) 2004-2005.  This software is released under the GNU GPL license.\n");
00389     httpdOutput(r, "</div>\n");
00390 
00391 
00392         httpdOutput(r, "</body>\n");
00393         httpdOutput(r, "</html>\n");
00394 }

Generated on Sun Apr 13 21:55:00 2008 for WifiDog by  doxygen 1.5.3