ip.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002  secwatch - Copyright (C) 2006 Nic Stevens -- See COPYING for license details
00003 ------------------------------------------------------------------------------
00004  ip.c - Ip list management functions
00005   
00006   The IP list is a list of IPs that have been detected through log analysis as 
00007   potential hazards. Once a potential has been detected it is tracked with a 
00008   hit count and a timestamp. Each time the hit count is updated the timestamp 
00009   is updated too. If the hit count reaches maxatt then the IP is "banned" 
00010   using the configured firewall rules. 
00011   If the the current_time - timestamp > maxage minutes then the IP is removed
00012   from the list. When an offending IP is re-enabled it remains on the list with 
00013   a fresh timestamp. It will either be removed after a timeout or re-blocked
00014   after fresh attempts.
00015 -----------------------------------------------------------------------------*/
00016 #ifdef HAVE_CONFIG_H
00017 #include "config.h"
00018 #endif
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <time.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <errno.h>
00027 #include "log.h"
00028 #include "strutil.h"
00029 #include "tail.h"
00030 #include "configfile.h"
00031 
00032 typedef struct _ipinfo {
00033      char ip[32];
00034      int hitcount;
00035      int isdropped;
00036      time_t timein;
00037 } ipinfo_t;
00038 
00039 
00040 ipinfo_t *iplist = NULL;
00041 int ipcnt = 0;
00042 int ipDeleteFlag = 0;
00043 
00047 int loadIpList(void) {
00048      struct stat _st, *s = &_st;
00049      int cnt;
00050      char * filename = NULL;
00051      FILE *f;
00052      if(filename == NULL) 
00053           filename = confVarPath("iplist",&cnt);
00054      if(stat(filename,s) != 0) {
00055           writeLog("Cannot stat %s: %m",filename);
00056           return -1;
00057      }
00058      cnt = s->st_size / sizeof(ipinfo_t);
00059      if((iplist = malloc(s->st_size)) == NULL) {
00060           fprintf(stderr,"Cannot allocate space for iplist: %m\n");
00061           exit(-1);
00062      }
00063      if((f = fopen(filename,"r")) == NULL) {
00064           fprintf(stderr,"Cannot open iplist: %m\n");
00065           exit(-1);
00066      }
00067      fread(iplist,sizeof(ipinfo_t),cnt,f);
00068      fclose(f);
00069      ipcnt = cnt;
00070      return 0;
00071 }
00075 int writeIpList(void) {
00076      FILE *f;
00077      char *filename = NULL;
00078      int i;
00079      if(filename == NULL) 
00080           filename = confVarPath("iplist",&i);
00081      if((f = fopen(filename,"w")) == NULL) {
00082           fprintf(stderr,"Cannot open iplist: %m\n");
00083           exit(-1);
00084      }
00085      fwrite(iplist,sizeof(ipinfo_t),ipcnt,f);
00086      fclose(f);
00087      return 0;
00088 }
00092 int deleteIp(char *ip) {
00093      int i;
00094      if((i = ipEntry(ip)) != -1) {
00095           bzero(iplist[i].ip,sizeof(iplist[i].ip));
00096           iplist[i].timein = (time_t)-1;
00097           ipDeleteFlag = 1;
00098           return 0;
00099      }
00100      return -1;
00101 }
00105 int compactIpList() {
00106      ipinfo_t *nlist;
00107      int i, ncnt = 0;
00108      if((nlist = calloc(sizeof(ipinfo_t),ipcnt)) == NULL) {
00109           writeLog("Cannot allocate space for compaction %m");
00110           return -1;
00111      }
00112      for(i = 0; i < ipcnt; i++) 
00113           if(iplist[i].timein != -1) 
00114                nlist[ncnt++] = iplist[i];
00115      if((nlist = realloc(nlist,(sizeof(ipinfo_t)*ncnt))) == NULL) {
00116           writeLog("Cannot allocate space for compaction %m");
00117           return -1;
00118      }
00119      free(iplist);
00120      iplist = nlist;
00121      ipDeleteFlag = 0;
00122 }
00126 int ipadd(char *ip) {
00127      ipinfo_t ipi;
00128      int ipn;
00129      strcpy(ipi.ip,ip);
00130      time(&ipi.timein);
00131      ipi.hitcount = 1;
00132      ipi.isdropped = 0;
00133      ipn = ipcnt++;
00134      if((iplist = realloc(iplist,(sizeof(ipinfo_t)*ipcnt))) == NULL) {
00135           writeLog("Cannot allocate ip member");
00136           return -1;
00137      }
00138      iplist[ipn] = ipi;
00139      writeIpList();
00140      return 0;
00141 }
00144 int ipEntry(char *ip) {
00145      int i;
00146      for(i = 0; i < ipcnt; i++) 
00147           if(strcmp(iplist[i].ip,ip) == 0)
00148                return i;
00149      errno = ENOENT;
00150      return -1;
00151 }
00155 void incrementHitCount(char *ip) {
00156      int i;
00157      if((i = ipEntry(ip)) != -1)
00158           iplist[i].hitcount ++;
00159      else
00160           ipadd(ip);
00161      time(&iplist[i].timein);
00162      writeIpList();
00163 }
00168 void ipManage(void) {
00169      int i;
00170      time_t now;
00171      static int maxatt = -1;
00172      static int maxsecs = -1;
00173      
00174      if(maxatt == -1) 
00175           maxatt=confVarInt("maxatt",&i);
00176      if(maxsecs == -1) 
00177           maxsecs = confVarInt("maxage",&i) * 60;
00178      time(&now);
00179      for(i = 0; i < ipcnt; i++) {
00180           if(iplist[i].isdropped == 0 && iplist[i].hitcount >= maxatt) 
00181                dropIp(i);
00182           else if((now - iplist[i].timein) >= maxsecs)
00183                undropIp(i);
00184      }
00185      if(ipDeleteFlag) 
00186           compactIpList();
00187      writeIpList();
00188 }
00193 char * replaceIp(char *buf, char *ip) {
00194      char *tmp, *p;
00195      int i;
00196      tmp = alloca(strlen(buf)+strlen(ip)+2);
00197      if((i = strpos(buf,"$i")) == -1) 
00198           return NULL;
00199      p = &buf[i];
00200      p+= 2;
00201      strncpy(tmp,buf,i);
00202      strcat(tmp,ip);
00203      strcat(tmp,p);
00204      return strdup(tmp);
00205 }
00209 int dropIp(int ind) {
00210      ipinfo_t *ip = &iplist[ind];
00211      char * s;
00212      char ** dropRules = NULL;
00213      int i, x;
00214      
00215      if(dropRules == NULL) 
00216           dropRules = confVarFlist("fwreject",&i);
00217      
00218      for(i = 0; i < count(dropRules); i++) {
00219           s = replaceIp(confVarText(dropRules[i],&x),ip->ip);
00220           system(s);
00221           free(s);
00222      }
00223      ip->isdropped = 1;
00224      time(&ip->timein);
00225      writeIpList();
00226      inform("secwatch dropped IP %s",ip->ip);
00227      return 0;
00228 }
00233 int undropIp(int ind) {
00234      ipinfo_t *ip = &iplist[ind];
00235      char * s;
00236      char ** allowRules = NULL;
00237      int i, x;
00238      if(allowRules == NULL) 
00239           allowRules = confVarFlist("fwallow",&i);
00240      if(ip->isdropped) {
00241           for(i = 0; i < count(allowRules); i++) {
00242                s = replaceIp(confVarText(allowRules[i],&x),ip->ip);
00243                system(s);
00244                free(s);
00245           }
00246           ip->isdropped = 0;
00247           inform("secwatch undropped IP %s",ip->ip);
00248           time(&ip->timein);
00249      } else 
00250           deleteIp(ip->ip);
00251      writeIpList();
00252      return 0;
00253 }

Generated on Tue Oct 31 10:17:23 2006 for secwatch by  doxygen 1.4.6