00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include <pthread.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032 #include <sys/stat.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035 #include <errno.h>
00036 #include <unistd.h>
00037 #include <string.h>
00038 #include <syslog.h>
00039
00040 #include "httpd.h"
00041
00042 #include "common.h"
00043 #include "safe.h"
00044 #include "util.h"
00045 #include "auth.h"
00046 #include "conf.h"
00047 #include "debug.h"
00048 #include "centralserver.h"
00049 #include "firewall.h"
00050 #include "../config.h"
00051
00052 extern pthread_mutex_t config_mutex;
00053
00064 t_authcode
00065 auth_server_request(t_authresponse *authresponse, const char *request_type, const char *ip, const char *mac, const char *token, unsigned long long int incoming, unsigned long long int outgoing)
00066 {
00067 int sockfd;
00068 ssize_t numbytes;
00069 size_t totalbytes;
00070 char buf[MAX_BUF];
00071 char *tmp;
00072 char *safe_token;
00073 int done, nfds;
00074 fd_set readfds;
00075 struct timeval timeout;
00076 t_auth_serv *auth_server = NULL;
00077 auth_server = get_auth_server();
00078
00079
00080 authresponse->authcode = AUTH_ERROR;
00081
00082 sockfd = connect_auth_server();
00083 if (sockfd == -1) {
00084
00085 return (AUTH_ERROR);
00086 }
00087
00092 memset(buf, 0, sizeof(buf));
00093 safe_token=httpdUrlEncode(token);
00094 snprintf(buf, (sizeof(buf) - 1),
00095 "GET %s%sstage=%s&ip=%s&mac=%s&token=%s&incoming=%llu&outgoing=%llu&gw_id=%s HTTP/1.0\r\n"
00096 "User-Agent: WiFiDog %s\r\n"
00097 "Host: %s\r\n"
00098 "\r\n",
00099 auth_server->authserv_path,
00100 auth_server->authserv_auth_script_path_fragment,
00101 request_type,
00102 ip,
00103 mac,
00104 safe_token,
00105 incoming,
00106 outgoing,
00107 config_get_config()->gw_id,
00108 VERSION,
00109 auth_server->authserv_hostname
00110 );
00111
00112 free(safe_token);
00113
00114 debug(LOG_DEBUG, "Sending HTTP request to auth server: [%s]\n", buf);
00115 send(sockfd, buf, strlen(buf), 0);
00116
00117 debug(LOG_DEBUG, "Reading response");
00118 numbytes = totalbytes = 0;
00119 done = 0;
00120 do {
00121 FD_ZERO(&readfds);
00122 FD_SET(sockfd, &readfds);
00123 timeout.tv_sec = 30;
00124 timeout.tv_usec = 0;
00125 nfds = sockfd + 1;
00126
00127 nfds = select(nfds, &readfds, NULL, NULL, &timeout);
00128
00129 if (nfds > 0) {
00132 numbytes = read(sockfd, buf + totalbytes, MAX_BUF - (totalbytes + 1));
00133 if (numbytes < 0) {
00134 debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno));
00135
00136 close(sockfd);
00137 return (AUTH_ERROR);
00138 }
00139 else if (numbytes == 0) {
00140 done = 1;
00141 }
00142 else {
00143 totalbytes += numbytes;
00144 debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes);
00145 }
00146 }
00147 else if (nfds == 0) {
00148 debug(LOG_ERR, "Timed out reading data via select() from auth server");
00149
00150 close(sockfd);
00151 return (AUTH_ERROR);
00152 }
00153 else if (nfds < 0) {
00154 debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno));
00155
00156 close(sockfd);
00157 return (AUTH_ERROR);
00158 }
00159 } while (!done);
00160
00161 close(sockfd);
00162
00163 buf[totalbytes] = '\0';
00164 debug(LOG_DEBUG, "HTTP Response from Server: [%s]", buf);
00165
00166 if ((tmp = strstr(buf, "Auth: "))) {
00167 if (sscanf(tmp, "Auth: %d", (int *)&authresponse->authcode) == 1) {
00168 debug(LOG_INFO, "Auth server returned authentication code %d", authresponse->authcode);
00169 return(authresponse->authcode);
00170 } else {
00171 debug(LOG_WARNING, "Auth server did not return expected authentication code");
00172 return(AUTH_ERROR);
00173 }
00174 }
00175 else {
00176 return(AUTH_ERROR);
00177 }
00178
00179
00180 return(AUTH_ERROR);
00181 }
00182
00183
00184
00185 int connect_auth_server() {
00186 int sockfd;
00187
00188 LOCK_CONFIG();
00189 sockfd = _connect_auth_server(0);
00190 UNLOCK_CONFIG();
00191
00192 if (sockfd == -1) {
00193 debug(LOG_ERR, "Failed to connect to any of the auth servers");
00194 mark_auth_offline();
00195 }
00196 else {
00197 debug(LOG_DEBUG, "Connected to auth server");
00198 mark_auth_online();
00199 }
00200 return (sockfd);
00201 }
00202
00203
00204
00205
00206
00207 int _connect_auth_server(int level) {
00208 s_config *config = config_get_config();
00209 t_auth_serv *auth_server = NULL;
00210 struct in_addr *h_addr;
00211 int num_servers = 0;
00212 char * hostname = NULL;
00213 char * popular_servers[] = {
00214 "www.google.com",
00215 "www.yahoo.com",
00216 NULL
00217 };
00218 char ** popularserver;
00219 char * ip;
00220 struct sockaddr_in their_addr;
00221 int sockfd;
00222
00223
00224 level++;
00225
00226
00227
00228
00229 for (auth_server = config->auth_servers; auth_server; auth_server = auth_server->next) {
00230 num_servers++;
00231 }
00232 debug(LOG_DEBUG, "Level %d: Calculated %d auth servers in list", level, num_servers);
00233
00234 if (level > num_servers) {
00235
00236
00237
00238
00239
00240 return (-1);
00241 }
00242
00243
00244
00245
00246 auth_server = config->auth_servers;
00247 hostname = auth_server->authserv_hostname;
00248 debug(LOG_DEBUG, "Level %d: Resolving auth server [%s]", level, hostname);
00249 h_addr = wd_gethostbyname(hostname);
00250 if (!h_addr) {
00251
00252
00253
00254
00255
00256 debug(LOG_DEBUG, "Level %d: Resolving auth server [%s] failed", level, hostname);
00257
00258 for (popularserver = popular_servers; *popularserver; popularserver++) {
00259 debug(LOG_DEBUG, "Level %d: Resolving popular server [%s]", level, *popularserver);
00260 h_addr = wd_gethostbyname(*popularserver);
00261 if (h_addr) {
00262 debug(LOG_DEBUG, "Level %d: Resolving popular server [%s] succeeded = [%s]", level, *popularserver, inet_ntoa(*h_addr));
00263 break;
00264 }
00265 else {
00266 debug(LOG_DEBUG, "Level %d: Resolving popular server [%s] failed", level, *popularserver);
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275 if (h_addr) {
00276 free (h_addr);
00277
00278
00279
00280
00281
00282 debug(LOG_DEBUG, "Level %d: Marking auth server [%s] as bad and trying next if possible", level, hostname);
00283 if (auth_server->last_ip) {
00284 free(auth_server->last_ip);
00285 auth_server->last_ip = NULL;
00286 }
00287 mark_auth_server_bad(auth_server);
00288 return _connect_auth_server(level);
00289 }
00290 else {
00291
00292
00293
00294
00295
00296
00297 mark_offline();
00298 debug(LOG_DEBUG, "Level %d: Failed to resolve auth server and all popular servers. "
00299 "The internet connection is probably down", level);
00300 return(-1);
00301 }
00302 }
00303 else {
00304
00305
00306
00307 ip = safe_strdup(inet_ntoa(*h_addr));
00308 debug(LOG_DEBUG, "Level %d: Resolving auth server [%s] succeeded = [%s]", level, hostname, ip);
00309
00310 if (!auth_server->last_ip || strcmp(auth_server->last_ip, ip) != 0) {
00311
00312
00313
00314
00315 debug(LOG_DEBUG, "Level %d: Updating last_ip IP of server [%s] to [%s]", level, hostname, ip);
00316 if (auth_server->last_ip) free(auth_server->last_ip);
00317 auth_server->last_ip = ip;
00318
00319
00320 fw_clear_authservers();
00321 fw_set_authservers();
00322 }
00323 else {
00324
00325
00326
00327 free(ip);
00328 }
00329
00330
00331
00332
00333 debug(LOG_DEBUG, "Level %d: Connecting to auth server %s:%d", level, hostname, auth_server->authserv_http_port);
00334 their_addr.sin_family = AF_INET;
00335 their_addr.sin_port = htons(auth_server->authserv_http_port);
00336 their_addr.sin_addr = *h_addr;
00337 memset(&(their_addr.sin_zero), '\0', sizeof(their_addr.sin_zero));
00338 free (h_addr);
00339
00340 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
00341 debug(LOG_ERR, "Level %d: Failed to create a new SOCK_STREAM socket: %s", strerror(errno));
00342 return(-1);
00343 }
00344
00345 if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
00346
00347
00348
00349
00350 debug(LOG_DEBUG, "Level %d: Failed to connect to auth server %s:%d (%s). Marking it as bad and trying next if possible", level, hostname, auth_server->authserv_http_port, strerror(errno));
00351 close(sockfd);
00352 mark_auth_server_bad(auth_server);
00353 return _connect_auth_server(level);
00354 }
00355 else {
00356
00357
00358
00359 debug(LOG_DEBUG, "Level %d: Successfully connected to auth server %s:%d", level, hostname, auth_server->authserv_http_port);
00360 return sockfd;
00361 }
00362 }
00363 }