| 1 | /********************************************************************\ |
|---|
| 2 | * This program is free software; you can redistribute it and/or * |
|---|
| 3 | * modify it under the terms of the GNU General Public License as * |
|---|
| 4 | * published by the Free Software Foundation; either version 2 of * |
|---|
| 5 | * the License, or (at your option) any later version. * |
|---|
| 6 | * * |
|---|
| 7 | * This program is distributed in the hope that it will be useful, * |
|---|
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|---|
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|---|
| 10 | * GNU General Public License for more details. * |
|---|
| 11 | * * |
|---|
| 12 | * You should have received a copy of the GNU General Public License* |
|---|
| 13 | * along with this program; if not, contact: * |
|---|
| 14 | * * |
|---|
| 15 | * Free Software Foundation Voice: +1-617-542-5942 * |
|---|
| 16 | * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * |
|---|
| 17 | * Boston, MA 02111-1307, USA gnu@gnu.org * |
|---|
| 18 | * * |
|---|
| 19 | \********************************************************************/ |
|---|
| 20 | |
|---|
| 21 | /* $Header$ */ |
|---|
| 22 | /** @file centralserver.c |
|---|
| 23 | @brief Functions to talk to the central server (auth/send stats/get rules/etc...) |
|---|
| 24 | @author Copyright (C) 2004 Philippe April <papril777@yahoo.com> |
|---|
| 25 | */ |
|---|
| 26 | |
|---|
| 27 | #include <stdio.h> |
|---|
| 28 | #include <stdlib.h> |
|---|
| 29 | #include <sys/types.h> |
|---|
| 30 | #include <sys/socket.h> |
|---|
| 31 | #include <sys/stat.h> |
|---|
| 32 | #include <netinet/in.h> |
|---|
| 33 | #include <arpa/inet.h> |
|---|
| 34 | #include <errno.h> |
|---|
| 35 | #include <unistd.h> |
|---|
| 36 | #include <netdb.h> |
|---|
| 37 | #include <string.h> |
|---|
| 38 | #include <syslog.h> |
|---|
| 39 | |
|---|
| 40 | #include "common.h" |
|---|
| 41 | |
|---|
| 42 | #include "auth.h" |
|---|
| 43 | #include "conf.h" |
|---|
| 44 | #include "debug.h" |
|---|
| 45 | #include "centralserver.h" |
|---|
| 46 | #include "../config.h" |
|---|
| 47 | |
|---|
| 48 | /** Initiates a transaction with the auth server, either to authenticate or to update the traffic counters at the server |
|---|
| 49 | @param authresponse Returns the information given by the central server |
|---|
| 50 | @param request_type Use the REQUEST_TYPE_* #defines in centralserver.h |
|---|
| 51 | @param ip IP adress of the client this request is related to |
|---|
| 52 | @param mac MAC adress of the client this request is related to |
|---|
| 53 | @param token Authentification token of the client |
|---|
| 54 | @param incoming Current counter of the client's total incoming traffic, in bytes |
|---|
| 55 | @param outgoing Current counter of the client's total outgoing traffic, in bytes |
|---|
| 56 | */ |
|---|
| 57 | int |
|---|
| 58 | auth_server_request(t_authresponse *authresponse, char *request_type, char *ip, char *mac, char *token, long int incoming, long int outgoing) |
|---|
| 59 | { |
|---|
| 60 | int sockfd, num_tries, done; |
|---|
| 61 | size_t numbytes, totalbytes; |
|---|
| 62 | char buf[MAX_BUF]; |
|---|
| 63 | struct hostent *he; |
|---|
| 64 | struct sockaddr_in their_addr; |
|---|
| 65 | char *tmp; |
|---|
| 66 | s_config *config = config_get_config(); |
|---|
| 67 | t_auth_serv *auth_server; |
|---|
| 68 | |
|---|
| 69 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { |
|---|
| 70 | debug(LOG_ERR, "socket(): %s", strerror(errno)); |
|---|
| 71 | exit(1); |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | num_tries = 0; |
|---|
| 75 | done = 0; |
|---|
| 76 | while (!done && ((auth_server = get_auth_server()) != NULL)) { |
|---|
| 77 | if ((he = gethostbyname(auth_server->authserv_hostname)) == NULL) { |
|---|
| 78 | debug(LOG_ERR, "Failed to resolve %s via gethostbyname" |
|---|
| 79 | "(): %s", auth_server->authserv_hostname, |
|---|
| 80 | strerror(errno)); |
|---|
| 81 | return(-1); |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | their_addr.sin_family = AF_INET; |
|---|
| 85 | their_addr.sin_port = htons(auth_server->authserv_http_port); |
|---|
| 86 | their_addr.sin_addr = *((struct in_addr *)he->h_addr); |
|---|
| 87 | memset(&(their_addr.sin_zero), '\0', sizeof(their_addr.sin_zero)); |
|---|
| 88 | |
|---|
| 89 | debug(LOG_INFO, "Connecting to auth server %s on port %d", |
|---|
| 90 | auth_server->authserv_hostname, |
|---|
| 91 | auth_server->authserv_http_port); |
|---|
| 92 | |
|---|
| 93 | if (connect(sockfd, (struct sockaddr *)&their_addr, |
|---|
| 94 | sizeof(struct sockaddr)) == -1) { |
|---|
| 95 | debug(LOG_ERR, "connect(): %s", strerror(errno)); |
|---|
| 96 | debug(LOG_ERR, "Trying next Auth Server (if any)"); |
|---|
| 97 | if (num_tries++ < config->authserv_maxtries) { |
|---|
| 98 | mark_auth_server_bad(auth_server); |
|---|
| 99 | } else { |
|---|
| 100 | mark_auth_server_bad(auth_server); |
|---|
| 101 | debug(LOG_ERR, "Aborting request"); |
|---|
| 102 | return(-1); /* non-fatal */ |
|---|
| 103 | } |
|---|
| 104 | } else { |
|---|
| 105 | done = 1; |
|---|
| 106 | } |
|---|
| 107 | } |
|---|
| 108 | /** |
|---|
| 109 | * TODO: XXX change the PHP so we can harmonize stage as request_type |
|---|
| 110 | * everywhere. |
|---|
| 111 | */ |
|---|
| 112 | memset(buf, 0, sizeof(buf)); |
|---|
| 113 | snprintf(buf, (sizeof(buf) - 1), "GET %s/auth/?stage=%s&ip=%s&mac=%s" |
|---|
| 114 | "&token=%s&incoming=%ld&outgoing=%ld HTTP/1.0\n" |
|---|
| 115 | "User-Agent: WiFiDog %s\n" |
|---|
| 116 | "Host: %s\n" |
|---|
| 117 | "\n", |
|---|
| 118 | auth_server->authserv_path, request_type, ip, mac, |
|---|
| 119 | token, incoming, outgoing, VERSION, |
|---|
| 120 | auth_server->authserv_hostname); |
|---|
| 121 | send(sockfd, buf, strlen(buf), 0); |
|---|
| 122 | |
|---|
| 123 | debug(LOG_DEBUG, "Sending HTTP request to auth server: [%s]\n", buf); |
|---|
| 124 | |
|---|
| 125 | numbytes = totalbytes = 0; |
|---|
| 126 | while ((numbytes = read(sockfd, buf + totalbytes, |
|---|
| 127 | MAX_BUF - (totalbytes + 1))) > 0) |
|---|
| 128 | totalbytes =+ numbytes; |
|---|
| 129 | |
|---|
| 130 | if (numbytes == -1) { |
|---|
| 131 | debug(LOG_ERR, "read(): %s", strerror(errno)); |
|---|
| 132 | exit(1); |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | numbytes = totalbytes; |
|---|
| 136 | |
|---|
| 137 | buf[numbytes] = '\0'; |
|---|
| 138 | |
|---|
| 139 | close(sockfd); |
|---|
| 140 | |
|---|
| 141 | debug(LOG_DEBUG, "HTTP Response from Server: [%s]", buf); |
|---|
| 142 | |
|---|
| 143 | if ((tmp = strstr(buf, "Auth: "))) { |
|---|
| 144 | if (sscanf(tmp, "Auth: %d", &authresponse->authcode) == 1) { |
|---|
| 145 | debug(LOG_INFO, "Auth server returned authentication code %d", |
|---|
| 146 | authresponse->authcode); |
|---|
| 147 | return(authresponse->authcode); |
|---|
| 148 | } else { |
|---|
| 149 | debug(LOG_WARNING, "Auth server did not return expected information"); |
|---|
| 150 | return(AUTH_ERROR); |
|---|
| 151 | } |
|---|
| 152 | } else { |
|---|
| 153 | return(AUTH_ERROR); |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | return(AUTH_ERROR); |
|---|
| 157 | } |
|---|
| 158 | |
|---|