00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00031 #define _GNU_SOURCE
00032
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <syslog.h>
00036 #include <errno.h>
00037 #include <pthread.h>
00038 #include <sys/wait.h>
00039 #include <sys/types.h>
00040 #include <sys/unistd.h>
00041
00042 #include <string.h>
00043
00044 #include <sys/socket.h>
00045 #include <netinet/in.h>
00046 #include <arpa/inet.h>
00047 #include <unistd.h>
00048 #include <sys/uio.h>
00049 #include <fcntl.h>
00050 #include <netdb.h>
00051 #include <sys/time.h>
00052
00053 #ifdef __linux__
00054 #include <net/ethernet.h>
00055 #include <netinet/ip.h>
00056 #include <netinet/ip_icmp.h>
00057 #include <netpacket/packet.h>
00058 #endif
00059
00060 #include "httpd.h"
00061 #include "safe.h"
00062 #include "debug.h"
00063 #include "conf.h"
00064 #include "firewall.h"
00065 #include "fw_iptables.h"
00066 #include "auth.h"
00067 #include "centralserver.h"
00068 #include "client_list.h"
00069
00070 extern pthread_mutex_t client_list_mutex;
00071
00072 int icmp_fd = 0;
00073
00082 int
00083 fw_allow(char *ip, char *mac, int fw_connection_state)
00084 {
00085 debug(LOG_DEBUG, "Allowing %s %s with fw_connection_state %d", ip, mac, fw_connection_state);
00086
00087 return iptables_fw_access(FW_ACCESS_ALLOW, ip, mac, fw_connection_state);
00088 }
00089
00097 int
00098 fw_deny(char *ip, char *mac, int fw_connection_state)
00099 {
00100 debug(LOG_DEBUG, "Denying %s %s with fw_connection_state %d", ip, mac, fw_connection_state);
00101
00102 return iptables_fw_access(FW_ACCESS_DENY, ip, mac, fw_connection_state);
00103 }
00104
00111 char *
00112 arp_get(char *req_ip)
00113 {
00114 FILE *proc;
00115 char ip[16];
00116 char mac[18];
00117 char * reply = NULL;
00118
00119 if (!(proc = fopen("/proc/net/arp", "r"))) {
00120 return NULL;
00121 }
00122
00123
00124 while (!feof(proc) && fgetc(proc) != '\n');
00125
00126
00127 reply = NULL;
00128 while (!feof(proc) && (fscanf(proc, " %15[0-9.] %*s %*s %17[A-F0-9:] %*s %*s", ip, mac) == 2)) {
00129 if (strcmp(ip, req_ip) == 0) {
00130 reply = safe_strdup(mac);
00131 break;
00132 }
00133 }
00134
00135 fclose(proc);
00136
00137 return reply;
00138 }
00139
00142 int
00143 fw_init(void)
00144 {
00145 int flags, oneopt = 1, zeroopt = 0;
00146
00147 debug(LOG_INFO, "Creating ICMP socket");
00148 if ((icmp_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1 ||
00149 (flags = fcntl(icmp_fd, F_GETFL, 0)) == -1 ||
00150 fcntl(icmp_fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
00151 setsockopt(icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) ||
00152 setsockopt(icmp_fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1) {
00153 debug(LOG_ERR, "Cannot create ICMP raw socket.");
00154 return;
00155 }
00156
00157 debug(LOG_INFO, "Initializing Firewall");
00158 return iptables_fw_init();
00159 }
00160
00163 void
00164 fw_clear_authservers(void)
00165 {
00166 debug(LOG_INFO, "Clearing the authservers list");
00167 iptables_fw_clear_authservers();
00168 }
00169
00172 void
00173 fw_set_authservers(void)
00174 {
00175 debug(LOG_INFO, "Setting the authservers list");
00176 iptables_fw_set_authservers();
00177 }
00178
00183 int
00184 fw_destroy(void)
00185 {
00186 if (icmp_fd != 0) {
00187 debug(LOG_INFO, "Closing ICMP socket");
00188 close(icmp_fd);
00189 }
00190
00191 debug(LOG_INFO, "Removing Firewall rules");
00192 return iptables_fw_destroy();
00193 }
00194
00198 void
00199 fw_counter(void)
00200 {
00201 t_authresponse authresponse;
00202 char *token, *ip, *mac;
00203 t_client *p1, *p2;
00204 unsigned long long incoming, outgoing;
00205 s_config *config = config_get_config();
00206
00207 if (-1 == iptables_fw_counters_update()) {
00208 debug(LOG_ERR, "Could not get counters from firewall!");
00209 return;
00210 }
00211
00212 LOCK_CLIENT_LIST();
00213
00214 for (p1 = p2 = client_get_first_client(); NULL != p1; p1 = p2) {
00215 p2 = p1->next;
00216
00217 ip = safe_strdup(p1->ip);
00218 token = safe_strdup(p1->token);
00219 mac = safe_strdup(p1->mac);
00220 outgoing = p1->counters.outgoing;
00221 incoming = p1->counters.incoming;
00222
00223 UNLOCK_CLIENT_LIST();
00224
00225 icmp_ping(ip);
00226
00227 auth_server_request(&authresponse, REQUEST_TYPE_COUNTERS, ip, mac, token, incoming, outgoing);
00228 LOCK_CLIENT_LIST();
00229
00230 if (!(p1 = client_list_find(ip, mac))) {
00231 debug(LOG_ERR, "Node %s was freed while being re-validated!", ip);
00232 } else {
00233 if (p1->counters.last_updated +
00234 (config->checkinterval * config->clienttimeout)
00235 <= time(NULL)) {
00236
00237 debug(LOG_INFO, "%s - Inactive for %ld seconds, removing client and denying in firewall", p1->ip, config->checkinterval * config->clienttimeout);
00238 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00239 client_list_delete(p1);
00240
00241
00242 UNLOCK_CLIENT_LIST();
00243 auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token, 0, 0);
00244 LOCK_CLIENT_LIST();
00245 }
00246 else {
00247
00248
00249
00250
00251
00252
00253 switch (authresponse.authcode) {
00254 case AUTH_DENIED:
00255 debug(LOG_NOTICE, "%s - Denied. Removing client and firewall rules", p1->ip);
00256 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00257 client_list_delete(p1);
00258 break;
00259
00260 case AUTH_VALIDATION_FAILED:
00261 debug(LOG_NOTICE, "%s - Validation timeout, now denied. Removing client and firewall rules", p1->ip);
00262 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00263 client_list_delete(p1);
00264 break;
00265
00266 case AUTH_ALLOWED:
00267 if (p1->fw_connection_state != FW_MARK_KNOWN) {
00268 debug(LOG_INFO, "%s - Access has changed to allowed, refreshing firewall and clearing counters", p1->ip);
00269 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00270 p1->fw_connection_state = FW_MARK_KNOWN;
00271 p1->counters.incoming = p1->counters.outgoing = 0;
00272 fw_allow(p1->ip, p1->mac, p1->fw_connection_state);
00273 }
00274 break;
00275
00276 case AUTH_VALIDATION:
00277
00278
00279
00280
00281
00282 debug(LOG_INFO, "%s - User in validation period", p1->ip);
00283 break;
00284
00285 case AUTH_ERROR:
00286 debug(LOG_WARNING, "Error communicating with auth server - leaving %s as-is for now", p1->ip);
00287 break;
00288
00289 default:
00290 debug(LOG_DEBUG, "I do not know about authentication code %d", authresponse.authcode);
00291 break;
00292 }
00293 }
00294 }
00295
00296 free(token);
00297 free(ip);
00298 free(mac);
00299 }
00300 UNLOCK_CLIENT_LIST();
00301 }
00302
00303 void icmp_ping(char *host) {
00304 struct sockaddr_in saddr;
00305 #ifdef __linux__
00306 struct {
00307 struct ip ip;
00308 struct icmp icmp;
00309 } packet;
00310 #endif
00311 unsigned int i, j;
00312 int opt = 2000;
00313 unsigned short id = rand16();
00314
00315 saddr.sin_family = AF_INET;
00316 saddr.sin_port = 0;
00317 inet_aton(host, &saddr.sin_addr);
00318 #ifdef HAVE_SOCKADDR_SA_LEN
00319 saddr.sin_len = sizeof(struct sockaddr_in);
00320 #endif
00321
00322 memset(&(saddr.sin_zero), '\0', sizeof(saddr.sin_zero));
00323
00324 #ifdef __linux__
00325 memset(&packet.icmp, 0, sizeof(packet.icmp));
00326 packet.icmp.icmp_type = ICMP_ECHO;
00327 packet.icmp.icmp_id = id;
00328 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
00329 j += ((unsigned short *)&packet.icmp)[i];
00330 while (j>>16)
00331 j = (j & 0xffff) + (j >> 16);
00332 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
00333
00334 if (setsockopt(icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == -1) {
00335 debug(LOG_ERR, "setsockopt(): %s", strerror(errno));
00336 }
00337 if (sendto(icmp_fd, (char *)&packet.icmp, sizeof(struct icmp), 0, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
00338 debug(LOG_ERR, "sendto(): %s", strerror(errno));
00339 }
00340 opt = 1;
00341 if (setsockopt(icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == -1) {
00342 debug(LOG_ERR, "setsockopt(): %s", strerror(errno));
00343 }
00344 #endif
00345
00346 return;
00347 }
00348
00349 unsigned short rand16(void) {
00350 static int been_seeded = 0;
00351
00352 if (!been_seeded) {
00353 int fd, n = 0;
00354 unsigned int c = 0, seed = 0;
00355 char sbuf[sizeof(seed)];
00356 char *s;
00357 struct timeval now;
00358
00359
00360 gettimeofday(&now, NULL);
00361 seed = now.tv_sec ^ now.tv_usec ^ (getpid() << 16);
00362
00363 srand(seed);
00364 been_seeded = 1;
00365 }
00366
00367
00368
00369
00370
00371
00372 return( (unsigned short) (rand() >> 15) );
00373 }