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