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