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