00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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 #if defined(__NetBSD__)
00061 #include <netinet/in_systm.h>
00062 #include <netinet/ip.h>
00063 #include <netinet/ip_icmp.h>
00064 #endif
00065
00066 #include "httpd.h"
00067 #include "safe.h"
00068 #include "debug.h"
00069 #include "conf.h"
00070 #include "firewall.h"
00071 #include "fw_iptables.h"
00072 #include "auth.h"
00073 #include "centralserver.h"
00074 #include "client_list.h"
00075
00076 extern pthread_mutex_t client_list_mutex;
00077
00078
00079 extern pid_t restart_orig_pid;
00080
00081
00082
00091 int
00092 fw_allow(char *ip, char *mac, int fw_connection_state)
00093 {
00094 debug(LOG_DEBUG, "Allowing %s %s with fw_connection_state %d", ip, mac, fw_connection_state);
00095
00096 return iptables_fw_access(FW_ACCESS_ALLOW, ip, mac, fw_connection_state);
00097 }
00098
00106 int
00107 fw_deny(char *ip, char *mac, int fw_connection_state)
00108 {
00109 debug(LOG_DEBUG, "Denying %s %s with fw_connection_state %d", ip, mac, fw_connection_state);
00110
00111 return iptables_fw_access(FW_ACCESS_DENY, ip, mac, fw_connection_state);
00112 }
00113
00114
00121 char *
00122 arp_get(char *req_ip)
00123 {
00124 FILE *proc;
00125 char ip[16];
00126 char mac[18];
00127 char * reply = NULL;
00128
00129 if (!(proc = fopen("/proc/net/arp", "r"))) {
00130 return NULL;
00131 }
00132
00133
00134 while (!feof(proc) && fgetc(proc) != '\n');
00135
00136
00137 reply = NULL;
00138 while (!feof(proc) && (fscanf(proc, " %15[0-9.] %*s %*s %17[A-Fa-f0-9:] %*s %*s", ip, mac) == 2)) {
00139 if (strcmp(ip, req_ip) == 0) {
00140 reply = safe_strdup(mac);
00141 break;
00142 }
00143 }
00144
00145 fclose(proc);
00146
00147 return reply;
00148 }
00149
00152 int
00153 fw_init(void)
00154 {
00155 int flags, oneopt = 1, zeroopt = 0;
00156 int result = 0;
00157 t_client * client = NULL;
00158
00159 debug(LOG_INFO, "Creating ICMP socket");
00160 if ((icmp_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1 ||
00161 (flags = fcntl(icmp_fd, F_GETFL, 0)) == -1 ||
00162 fcntl(icmp_fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
00163 setsockopt(icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) ||
00164 setsockopt(icmp_fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1) {
00165 debug(LOG_ERR, "Cannot create ICMP raw socket.");
00166 return 0;
00167 }
00168
00169 debug(LOG_INFO, "Initializing Firewall");
00170 result = iptables_fw_init();
00171
00172 if (restart_orig_pid) {
00173 debug(LOG_INFO, "Restoring firewall rules for clients inherited from parent");
00174 LOCK_CLIENT_LIST();
00175 client = client_get_first_client();
00176 while (client) {
00177 fw_allow(client->ip, client->mac, client->fw_connection_state);
00178 client = client->next;
00179 }
00180 UNLOCK_CLIENT_LIST();
00181 }
00182
00183 return result;
00184 }
00185
00188 void
00189 fw_clear_authservers(void)
00190 {
00191 debug(LOG_INFO, "Clearing the authservers list");
00192 iptables_fw_clear_authservers();
00193 }
00194
00197 void
00198 fw_set_authservers(void)
00199 {
00200 debug(LOG_INFO, "Setting the authservers list");
00201 iptables_fw_set_authservers();
00202 }
00203
00208 int
00209 fw_destroy(void)
00210 {
00211 if (icmp_fd != 0) {
00212 debug(LOG_INFO, "Closing ICMP socket");
00213 close(icmp_fd);
00214 }
00215
00216 debug(LOG_INFO, "Removing Firewall rules");
00217 return iptables_fw_destroy();
00218 }
00219
00223 void
00224 fw_sync_with_authserver(void)
00225 {
00226 t_authresponse authresponse;
00227 char *token, *ip, *mac;
00228 t_client *p1, *p2;
00229 unsigned long long incoming, outgoing;
00230 s_config *config = config_get_config();
00231
00232 if (-1 == iptables_fw_counters_update()) {
00233 debug(LOG_ERR, "Could not get counters from firewall!");
00234 return;
00235 }
00236
00237 LOCK_CLIENT_LIST();
00238
00239 for (p1 = p2 = client_get_first_client(); NULL != p1; p1 = p2) {
00240 p2 = p1->next;
00241
00242 ip = safe_strdup(p1->ip);
00243 token = safe_strdup(p1->token);
00244 mac = safe_strdup(p1->mac);
00245 outgoing = p1->counters.outgoing;
00246 incoming = p1->counters.incoming;
00247
00248 UNLOCK_CLIENT_LIST();
00249
00250
00251
00252
00253 icmp_ping(ip);
00254
00255 if (config->auth_servers != NULL) {
00256 auth_server_request(&authresponse, REQUEST_TYPE_COUNTERS, ip, mac, token, incoming, outgoing);
00257 }
00258 LOCK_CLIENT_LIST();
00259
00260 if (!(p1 = client_list_find(ip, mac))) {
00261 debug(LOG_ERR, "Node %s was freed while being re-validated!", ip);
00262 } else {
00263 time_t current_time=time(NULL);
00264 debug(LOG_INFO, "Checking client %s for timeout: Last updated %ld (%ld seconds ago), timeout delay %ld seconds, current time %ld, ",
00265 p1->ip, p1->counters.last_updated, current_time-p1->counters.last_updated, config->checkinterval * config->clienttimeout, current_time);
00266 if (p1->counters.last_updated +
00267 (config->checkinterval * config->clienttimeout)
00268 <= current_time) {
00269
00270 debug(LOG_INFO, "%s - Inactive for more than %ld seconds, removing client and denying in firewall",
00271 p1->ip, config->checkinterval * config->clienttimeout);
00272 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00273 client_list_delete(p1);
00274
00275
00276 if (config->auth_servers != NULL) {
00277 UNLOCK_CLIENT_LIST();
00278 auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token, 0, 0);
00279 LOCK_CLIENT_LIST();
00280 }
00281 } else {
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 if (config->auth_servers != NULL) {
00292 switch (authresponse.authcode) {
00293 case AUTH_DENIED:
00294 debug(LOG_NOTICE, "%s - Denied. Removing client and firewall rules", p1->ip);
00295 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00296 client_list_delete(p1);
00297 break;
00298
00299 case AUTH_VALIDATION_FAILED:
00300 debug(LOG_NOTICE, "%s - Validation timeout, now denied. Removing client and firewall rules", p1->ip);
00301 fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
00302 client_list_delete(p1);
00303 break;
00304
00305 case AUTH_ALLOWED:
00306 if (p1->fw_connection_state != FW_MARK_KNOWN) {
00307 debug(LOG_INFO, "%s - Access has changed to allowed, refreshing firewall and clearing counters", p1->ip);
00308
00309
00310
00311 if (p1->fw_connection_state != FW_MARK_PROBATION) {
00312 p1->counters.incoming = p1->counters.outgoing = 0;
00313 }
00314 else {
00315
00316 debug(LOG_INFO, "%s - Skipped clearing counters after all, the user was previously in validation", p1->ip);
00317 }
00318 p1->fw_connection_state = FW_MARK_KNOWN;
00319 fw_allow(p1->ip, p1->mac, p1->fw_connection_state);
00320 }
00321 break;
00322
00323 case AUTH_VALIDATION:
00324
00325
00326
00327
00328
00329 debug(LOG_INFO, "%s - User in validation period", p1->ip);
00330 break;
00331
00332 case AUTH_ERROR:
00333 debug(LOG_WARNING, "Error communicating with auth server - leaving %s as-is for now", p1->ip);
00334 break;
00335
00336 default:
00337 debug(LOG_ERR, "I do not know about authentication code %d", authresponse.authcode);
00338 break;
00339 }
00340 }
00341 }
00342 }
00343
00344 free(token);
00345 free(ip);
00346 free(mac);
00347 }
00348 UNLOCK_CLIENT_LIST();
00349 }
00350
00351 void
00352 icmp_ping(char *host)
00353 {
00354 struct sockaddr_in saddr;
00355 #if defined(__linux__) || defined(__NetBSD__)
00356 struct {
00357 struct ip ip;
00358 struct icmp icmp;
00359 } packet;
00360 #endif
00361 unsigned int i, j;
00362 int opt = 2000;
00363 unsigned short id = rand16();
00364
00365 memset(&saddr, 0, sizeof(saddr));
00366 saddr.sin_family = AF_INET;
00367 inet_aton(host, &saddr.sin_addr);
00368 #if defined(HAVE_SOCKADDR_SA_LEN) || defined(__NetBSD__)
00369 saddr.sin_len = sizeof(struct sockaddr_in);
00370 #endif
00371
00372 #if defined(__linux__) || defined(__NetBSD__)
00373 memset(&packet.icmp, 0, sizeof(packet.icmp));
00374 packet.icmp.icmp_type = ICMP_ECHO;
00375 packet.icmp.icmp_id = id;
00376
00377 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
00378 j += ((unsigned short *)&packet.icmp)[i];
00379
00380 while (j >> 16)
00381 j = (j & 0xffff) + (j >> 16);
00382
00383 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
00384
00385 if (setsockopt(icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == -1)
00386 debug(LOG_ERR, "setsockopt(): %s", strerror(errno));
00387
00388 if (sendto(icmp_fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
00389 (const struct sockaddr *)&saddr, sizeof(saddr)) == -1)
00390 debug(LOG_ERR, "sendto(): %s", strerror(errno));
00391
00392 opt = 1;
00393 if (setsockopt(icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == -1)
00394 debug(LOG_ERR, "setsockopt(): %s", strerror(errno));
00395 #endif
00396
00397 return;
00398 }
00399
00400 unsigned short rand16(void) {
00401 static int been_seeded = 0;
00402
00403 if (!been_seeded) {
00404 unsigned int seed = 0;
00405 struct timeval now;
00406
00407
00408 gettimeofday(&now, NULL);
00409 seed = now.tv_sec ^ now.tv_usec ^ (getpid() << 16);
00410
00411 srand(seed);
00412 been_seeded = 1;
00413 }
00414
00415
00416
00417
00418
00419
00420 return( (unsigned short) (rand() >> 15) );
00421 }