auth.c

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: auth.c 1104 2006-10-09 00:58:46Z acv $ */
00027 #define _GNU_SOURCE
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <pthread.h>
00032 #include <string.h>
00033 #include <stdarg.h>
00034 #include <sys/types.h>
00035 #include <sys/socket.h>
00036 #include <unistd.h>
00037 #include <syslog.h>
00038 
00039 #include "httpd.h"
00040 #include "http.h"
00041 #include "safe.h"
00042 #include "conf.h"
00043 #include "debug.h"
00044 #include "auth.h"
00045 #include "centralserver.h"
00046 #include "fw_iptables.h"
00047 #include "firewall.h"
00048 #include "client_list.h"
00049 #include "util.h"
00050 
00051 /* Defined in clientlist.c */
00052 extern  pthread_mutex_t client_list_mutex;
00053 
00054 /* Defined in util.c */
00055 extern long served_this_session;
00056 
00062 void
00063 thread_client_timeout_check(void *arg)
00064 {
00065         pthread_cond_t          cond = PTHREAD_COND_INITIALIZER;
00066         pthread_mutex_t         cond_mutex = PTHREAD_MUTEX_INITIALIZER;
00067         struct  timespec        timeout;
00068         
00069         while (1) {
00070                 /* Sleep for config.checkinterval seconds... */
00071                 timeout.tv_sec = time(NULL) + config_get_config()->checkinterval;
00072                 timeout.tv_nsec = 0;
00073 
00074                 /* Mutex must be locked for pthread_cond_timedwait... */
00075                 pthread_mutex_lock(&cond_mutex);
00076                 
00077                 /* Thread safe "sleep" */
00078                 pthread_cond_timedwait(&cond, &cond_mutex, &timeout);
00079 
00080                 /* No longer needs to be locked */
00081                 pthread_mutex_unlock(&cond_mutex);
00082         
00083                 debug(LOG_DEBUG, "Running fw_counter()");
00084         
00085                 fw_sync_with_authserver();
00086         }
00087 }
00088 
00093 void
00094 authenticate_client(request *r)
00095 {
00096         t_client        *client;
00097         t_authresponse  auth_response;
00098         char    *ip,
00099                 *mac,
00100                 *token;
00101         char *newlocation = NULL;
00102         char *protocol = NULL;
00103         s_config        *config = NULL;
00104         t_auth_serv     *auth_server = NULL;
00105         int port = 80;
00106 
00107         LOCK_CLIENT_LIST();
00108 
00109         client = client_list_find_by_ip(r->clientAddr);
00110 
00111         if (client == NULL) {
00112                 debug(LOG_ERR, "Could not find client for %s", ip);
00113                 UNLOCK_CLIENT_LIST();
00114                 return;
00115         }
00116         
00117         mac = safe_strdup(client->mac);
00118         token = safe_strdup(client->token);
00119         
00120         UNLOCK_CLIENT_LIST();
00121         
00122         /* 
00123          * At this point we've released the lock while we do an HTTP request since it could
00124          * take multiple seconds to do and the gateway would effectively be frozen if we
00125          * kept the lock.
00126          */
00127         auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, r->clientAddr, mac, token, 0, 0);
00128         
00129         LOCK_CLIENT_LIST();
00130         
00131         /* can't trust the client to still exist after n seconds have passed */
00132         client = client_list_find(r->clientAddr, mac);
00133         
00134         if (client == NULL) {
00135                 debug(LOG_ERR, "Could not find client node for %s (%s)", r->clientAddr, mac);
00136                 UNLOCK_CLIENT_LIST();
00137                 free(token);
00138                 free(mac);
00139                 return;
00140         }
00141         
00142         free(token);
00143         free(mac);
00144 
00145         /* Prepare some variables we'll need below */
00146         config = config_get_config();
00147         auth_server = get_auth_server();
00148 
00149         if (auth_server->authserv_use_ssl) {
00150                 protocol = "https";
00151                 port = auth_server->authserv_ssl_port;
00152         } else {
00153                 protocol = "http";
00154                 port = auth_server->authserv_http_port;
00155         }
00156 
00157         switch(auth_response.authcode) {
00158 
00159         case AUTH_ERROR:
00160                 /* Error talking to central server */
00161                 debug(LOG_ERR, "Got %d from central server authenticating token %s from %s at %s", auth_response, client->token, client->ip, client->mac);
00162                 http_wifidog_header(r, "Error!");
00163                 httpdOutput(r, "Error: We did not get a valid answer from the central server");
00164                 http_wifidog_footer(r);
00165                 break;
00166 
00167         case AUTH_DENIED:
00168                 /* Central server said invalid token */
00169                 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);
00170                 safe_asprintf(&newlocation, "Location: %s://%s:%d%sgw_message.php?message=denied",
00171                         protocol,
00172                         auth_server->authserv_hostname,
00173                         port,
00174                         auth_server->authserv_path
00175                 );
00176                 httpdSetResponse(r, "307 Redirect to denied message\n");
00177                 httpdAddHeader(r, newlocation);
00178                 free(newlocation);
00179                 http_wifidog_header(r, "Redirection to message");
00180                 httpdPrintf(r, "Please <a href='%s://%s:%d%sgw_message.php?message=denied'>click here</a>.",
00181                         protocol,
00182                         auth_server->authserv_hostname,
00183                         port,
00184                         auth_server->authserv_path
00185                 );
00186                 http_wifidog_footer(r);
00187                 break;
00188 
00189     case AUTH_VALIDATION:
00190                 /* They just got validated for X minutes to check their email */
00191                 debug(LOG_INFO, "Got VALIDATION from central server authenticating token %s from %s at %s"
00192                                 "- adding to firewall and redirecting them to activate message", client->token,
00193                                 client->ip, client->mac);
00194                 client->fw_connection_state = FW_MARK_PROBATION;
00195                 fw_allow(client->ip, client->mac, FW_MARK_PROBATION);
00196                 safe_asprintf(&newlocation, "Location: %s://%s:%d%sgw_message.php?message=activate",
00197                         protocol,
00198                         auth_server->authserv_hostname,
00199                         port,
00200                         auth_server->authserv_path
00201                 );
00202                 httpdSetResponse(r, "307 Redirect to activate message\n");
00203                 httpdAddHeader(r, newlocation);
00204                 free(newlocation);
00205                 http_wifidog_header(r, "Redirection to message");
00206                 httpdPrintf(r, "Please <a href='%s://%s:%d%sgw_message.php?message=activate'>click here</a>.",
00207                         protocol,
00208                         auth_server->authserv_hostname,
00209                         port,
00210                         auth_server->authserv_path
00211                 );
00212                 http_wifidog_footer(r);
00213             break;
00214 
00215     case AUTH_ALLOWED:
00216                 /* Logged in successfully as a regular account */
00217                 debug(LOG_INFO, "Got ALLOWED from central server authenticating token %s from %s at %s - "
00218                                 "adding to firewall and redirecting them to portal", client->token, client->ip, client->mac);
00219                 client->fw_connection_state = FW_MARK_KNOWN;
00220                 fw_allow(client->ip, client->mac, FW_MARK_KNOWN);
00221         served_this_session++;
00222                 safe_asprintf(&newlocation, "Location: %s://%s:%d%sportal/?gw_id=%s",
00223                         protocol,
00224                         auth_server->authserv_hostname,
00225                         port,
00226                         auth_server->authserv_path,
00227                         config->gw_id
00228                 );
00229                 httpdSetResponse(r, "307 Redirect to portal\n");
00230                 httpdAddHeader(r, newlocation);
00231                 free(newlocation);
00232                 http_wifidog_header(r, "Redirection to portal");
00233                 httpdPrintf(r, "Please <a href='%s://%s:%d%sportal/?gw_id=%s'>click here</a> for the portal.",
00234                         protocol,
00235                         auth_server->authserv_hostname,
00236                         port,
00237                         auth_server->authserv_path,
00238                         config->gw_id
00239                 );
00240                 http_wifidog_footer(r);
00241             break;
00242 
00243     case AUTH_VALIDATION_FAILED:
00244                  /* Client had X minutes to validate account by email and didn't = too late */
00245                 debug(LOG_INFO, "Got VALIDATION_FAILED from central server authenticating token %s from %s at %s "
00246                                 "- redirecting them to failed_validation message", client->token, client->ip, client->mac);
00247                 safe_asprintf(&newlocation, "Location: %s://%s:%d%sgw_message.php?message=failed_validation",
00248                         protocol,
00249                         auth_server->authserv_hostname,
00250                         port,
00251                         auth_server->authserv_path
00252                 );
00253                 httpdSetResponse(r, "307 Redirect to failed validation message\n");
00254                 httpdAddHeader(r, newlocation);
00255                 free(newlocation);
00256                 http_wifidog_header(r, "Redirection to message");
00257                 httpdPrintf(r, "Please <a href='%s://%s:%d%sgw_message.php?message=failed_validation'>click here</a>.",
00258                         protocol,
00259                         auth_server->authserv_hostname,
00260                         port,
00261                         auth_server->authserv_path
00262                 );
00263                 http_wifidog_footer(r);
00264             break;
00265 
00266     default:
00267                 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);
00268                 http_wifidog_header(r, "Internal error");
00269                 httpdOutput(r, "We can not validate your request at this time");
00270                 http_wifidog_footer(r);
00271             break;
00272 
00273         }
00274 
00275         UNLOCK_CLIENT_LIST();
00276         return;
00277 }
00278 
00279 

Generated on Sun Jun 24 00:29:52 2007 for WifiDog by  doxygen 1.5.1