]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - squidguard_log.c
Give a try to splint and apply a few of the recommandations
[thirdparty/sarg.git] / squidguard_log.c
index 2f2fcfa23ed1fed8563c996b4e8814e7e9a100a1..0123a8944363a0c58e22d6565f5548dde5645718 100644 (file)
@@ -1,10 +1,11 @@
 /*
- * AUTHOR: Pedro Lineu Orso                         pedro.orso@gmail.com
- *                                                            1998, 2008
  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
+ *                                                            1998, 2010
  *
  * SARG donations:
  *      please look at http://sarg.sourceforge.net/donations.php
+ * Support:
+ *     http://sourceforge.net/projects/sarg/forums/forum/363374
  * ---------------------------------------------------------------------
  *
  *  This program is free software; you can redistribute it and/or modify
  */
 
 #include "include/conf.h"
+#include "include/defs.h"
 
 static char **files_done = NULL;
 static int nfiles_done = 0;
 
 
-void read_log(char *wentp, FILE *fp_ou)
+static void read_log(const char *wentp, FILE *fp_ou)
 {
    FILE *fp_in = NULL;
-   char bufbsf[255];
+   char buf[MAXLEN];
    char leks[5], sep[2], res[MAXLEN];
-   char mon[10], hour[15];
+   char mon[20], day[3], year[5], hour[15];
    char list[MAXLEN];
    char wdata[127];
+   char url[MAX_URL_LEN];
+   char user[MAX_USER_LEN];
+   char ip[25];
    int  idata=0;
    int  i;
+   char *str;
+   struct getwordstruct gwarea;
+   struct getwordstruct gwarea1;
 
    if(debug) {
-      strcpy(buf,text[7]);
-      if (getword(urly,sizeof(urly),buf,' ')<0 || getword(href,sizeof(href),buf,' ')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s string.\n",text[7]);
-         exit(1);
-      }
-      sprintf(msg,"%s squidGuard %s: %s",urly,buf,wentp);
-      debuga(msg);
+      debuga(_("Reading squidGuard log file %s\n"),wentp);
    }
 
    /* With squidGuard, you can log groups in only one log file.
@@ -70,77 +72,119 @@ void read_log(char *wentp, FILE *fp_ou)
    */
    for (i=0; i<nfiles_done; i++)
       if (!strcmp(wentp, files_done[i])) return;
-   
+
    nfiles_done++;
    files_done = realloc(files_done, nfiles_done*sizeof(char *));
    if (!files_done) {
-       perror("parse squidGuard - realloc");
-       exit(EXIT_FAILURE);
+      debuga(_("Not enough memory to store the name of the new squidGuard log to be read - %s\n"),strerror(errno));
+      exit(EXIT_FAILURE);
    }
    files_done[nfiles_done-1] = strdup(wentp);
    if (!files_done[nfiles_done-1]) {
-       perror("parse squidGuard - strdup");
-       exit(EXIT_FAILURE);
+      debuga(_("Not enough memory to store the name of the new squidGuard log to be read - %s\n"),strerror(errno));
+      exit(EXIT_FAILURE);
    }
 
    if ((fp_in=fopen(wentp,"r"))==NULL) {
-         fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],wentp);
-       exit(1);
+      debuga(_("(squidguard) Cannot open log file %s\n"),wentp);
+      exit(EXIT_FAILURE);
    }
-   
-   if ((fp_in=fopen(wentp,"r"))==NULL) {
-      fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],wentp);
-      exit(1);
-   }
-   
+
    while (fgets(buf,sizeof(buf),fp_in) != NULL) {
-      if(strlen(SquidGuardLogFormat) > 0) {
-         strcpy(bufbsf,SquidGuardLogFormat);
+      getword_start(&gwarea,buf);
+      if(SquidGuardLogFormat[0] != '\0') {
+         getword_start(&gwarea1,SquidGuardLogFormat);
          leks[0]='\0';
-         if (getword(leks,sizeof(leks),bufbsf,'#')<0) {
-            printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
-            exit(1);
+         if (getword(leks,sizeof(leks),&gwarea1,'#')<0) {
+            debuga(_("There is a broken record or garbage in your %s file\n"),wentp);
+            exit(EXIT_FAILURE);
          }
          while(strcmp(leks,"end") != 0) {
-            if (getword(leks,sizeof(leks),bufbsf,'#')<0 || getword(sep,sizeof(sep),bufbsf,'#')<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
-               exit(1);
+            if (getword(leks,sizeof(leks),&gwarea1,'#')<0 || getword(sep,sizeof(sep),&gwarea1,'#')<0) {
+               debuga(_("Maybe you have a broken record or garbage in your %s file\n"),wentp);
+               exit(EXIT_FAILURE);
             }
             if(strcmp(leks,"end") != 0) {
-               if (getword(res,sizeof(res),buf,sep[0])<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
-                  exit(1);
+               if (getword(res,sizeof(res),&gwarea,sep[0])<0) {
+                  debuga(_("Maybe you have a broken record or garbage in your %s file\n"),wentp);
+                  exit(EXIT_FAILURE);
                }
-               if(strcmp(leks,"year") == 0)
+               if(strcmp(leks,"year") == 0) {
+                  if (strlen(res)>=sizeof(year)) {
+                     debuga(_("Year string too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(year,res);
-               else if(strcmp(leks,"year") == 0)
-                  strcpy(year,res);
-               else if(strcmp(leks,"mon") == 0)
+               } else if(strcmp(leks,"mon") == 0) {
+                  if (strlen(res)>=sizeof(mon)) {
+                     debuga(_("Month string too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(mon,res);
-               else if(strcmp(leks,"day") == 0)
+               } else if(strcmp(leks,"day") == 0) {
+                  if (strlen(res)>=sizeof(day)) {
+                     debuga(_("Day string too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(day,res);
-               else if(strcmp(leks,"hour") == 0)
+               } else if(strcmp(leks,"hour") == 0) {
+                  if (strlen(res)>=sizeof(hour)) {
+                     debuga(_("Hour string too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(hour,res);
-               else if(strcmp(leks,"list") == 0)
+               } else if(strcmp(leks,"list") == 0) {
+                  if (strlen(res)>=sizeof(list)) {
+                     debuga(_("Banning list name too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(list,res);
-               else if(strcmp(leks,"ip") == 0)
+               } else if(strcmp(leks,"ip") == 0) {
+                  if (strlen(res)>=sizeof(ip)) {
+                     debuga(_("IP address too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(ip,res);
-               else if(strcmp(leks,"user") == 0)
+               } else if(strcmp(leks,"user") == 0) {
+                  if (strlen(res)>=sizeof(user)) {
+                     debuga(_("User ID too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(user,res);
-               else if(strcmp(leks,"url") == 0)
+               } else if(strcmp(leks,"url") == 0) {
+                  if (strlen(res)>=sizeof(url)) {
+                     debuga(_("URL too long in squidGuard log file %s\n"),wentp);
+                     exit(EXIT_FAILURE);
+                  }
                   strcpy(url,res);
+               }
             }
          }
       } else {
-         if (getword(year,sizeof(year),buf,'-')<0 || getword(mon,sizeof(mon),buf,'-')<0 ||
-             getword(day,sizeof(day),buf,' ')<0 || getword(hour,sizeof(hour),buf,' ')<0 ||
-             getword(list,sizeof(list),buf,'/')<0 || getword(list,sizeof(list),buf,'/')<0 ||
-             getword(tmp5,sizeof(tmp5),buf,'/')<0 || getword(tmp5,sizeof(tmp5),buf,'/')<0 ||
-             getword(url,sizeof(url),buf,'/')<0 || getword(tmp5,sizeof(tmp5),buf,' ')<0 ||
-             getword(ip,sizeof(ip),buf,'/')<0 || getword(user,sizeof(user),buf,' ')<0 ||
-             getword(user,sizeof(user),buf,' ')<0) {
-            printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
-            exit(1);
+         if (getword(year,sizeof(year),&gwarea,'-')<0 || getword(mon,sizeof(mon),&gwarea,'-')<0 ||
+             getword(day,sizeof(day),&gwarea,' ')<0 || getword(hour,sizeof(hour),&gwarea,' ')<0 ||
+             getword_skip(MAXLEN,&gwarea,'/')<0 || getword(list,sizeof(list),&gwarea,'/')<0 ||
+             getword_skip(MAXLEN,&gwarea,' ')<0 || getword(url,sizeof(url),&gwarea,' ')<0 ||
+             getword(ip,sizeof(ip),&gwarea,'/')<0 || getword_skip(MAXLEN,&gwarea,' ')<0 ||
+             getword(user,sizeof(user),&gwarea,' ')<0) {
+            debuga(_("There is a broken record or garbage in your %s file\n"),wentp);
+            exit(EXIT_FAILURE);
+          }
+          /*
+          The URL may be "http://url:port/data" if the method is GET or simply "url:port/" if the method is CONNECT.
+          The following code removes the protocol:// if it is detected and always truncates the URL after the domain name.
+          It will fail if the URL doesn't start with the protocol and contains two consecutive / in the path (i.e.
+          the URL is not normalized).
+          */
+          str=strchr(url,'/');
+          if (str) {
+             if (str[1]=='/') {
+               str+=2;
+               for (i=0 ; *str && *str!='/' ; i++) url[i]=*str++;
+               url[i]='\0';
+             } else {
+               *str='\0';
+             }
           }
       }
 
@@ -148,17 +192,16 @@ void read_log(char *wentp, FILE *fp_ou)
       sprintf(wdata,"%s%s%s",year,mon,day);
       idata = atoi(wdata);
 
-      if(strcmp(SquidguardIgnoreDate,"on") == 0) {
-         if(idata < dfrom && idata > duntil)
+      if(SquidguardIgnoreDate) {
+         if(idata < dfrom || idata > duntil)
             continue;
       }
 
       if (strcmp(user,"-") == 0) {
          strcpy(user,ip);
-         bzero(ip, 30);
+         ip[0]='\0';
       }
-      sprintf(tmp6,"%s %s%s%s %s %s %s %s\n",user,year,mon,day,hour,ip,url,list);
-      fputs(tmp6, fp_ou);
+      fprintf(fp_ou,"%s\t%s%s%s\t%s\t%s\t%s\t%s\n",user,year,mon,day,hour,ip,url,list);
       squidguard_count++;
    }
    if (fp_in) fclose(fp_in);
@@ -166,39 +209,41 @@ void read_log(char *wentp, FILE *fp_ou)
 }
 
 
-int squidguard_log()
+void squidguard_log(void)
 {
-
    FILE *fp_ou = NULL, *fp_guard = NULL;
+   char buf[MAXLEN];
    char guard_in[MAXLEN];
    char guard_ou[MAXLEN];
    char logdir[MAXLEN];
    char year[10], day[10], mon[10];
    char user[MAXLEN];
-   char ip[30];
-   int  x, y;
+   char tmp6[MAXLEN];
+   int  y;
    int cstatus;
+   char *str;
+   char *str2;
 
    str2 = user;
 
    if(strlen(SquidGuardConf) < 1 && strlen(SquidGuardLogAlternate) < 1)
      return;
 
-   if (strlen(SquidGuardLogAlternate) > 0)
+   if (SquidGuardLogAlternate[0] != '\0')
       SquidGuardConf[0]='\0';
 
    sprintf(guard_in,"%s/squidguard.unsort",tmp);
    sprintf(guard_ou,"%s/squidguard.log",tmp);
    if((fp_ou=fopen(guard_in,"a"))==NULL) {
-      fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],guard_in);
-      exit(1);
+      debuga(_("(squidguard) Cannot open log file %s\n"),guard_in);
+      exit(EXIT_FAILURE);
    }
 
    bzero(day, 3);
    bzero(mon, 4);
    bzero(year, 5);
 
-   if(strcmp(SquidguardIgnoreDate,"on") == 0) {
+   if(SquidguardIgnoreDate) {
       if(strcmp(df,"e") == 0) {
          strncpy(day,period,2);
          strncpy(mon,period+2,3);
@@ -228,79 +273,86 @@ int squidguard_log()
       }
    }
 
-   if(strlen(SquidGuardConf) > 0) {
+   if(SquidGuardConf[0] != 0) {
       if(access(SquidGuardConf, R_OK) != 0) {
-         sprintf(msg,"Cannot open squidGuard config file: %s",SquidGuardConf);
-         debuga(msg);
-         exit(1);
+         debuga(_("Cannot open squidGuard config file: %s\n"),SquidGuardConf);
+         exit(EXIT_FAILURE);
       }
 
       if((fp_guard=fopen(SquidGuardConf,"r"))==NULL) {
-         fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],SquidGuardConf);
-         exit(1);
+         debuga(_("(squidguard) Cannot open log file %s\n"),SquidGuardConf);
+         exit(EXIT_FAILURE);
       }
-   
+
+      logdir[0]=0;
       while(fgets(buf,sizeof(buf),fp_guard)!=NULL) {
-         if(strstr(buf,"\n") != 0)
-            buf[strlen(buf)-1]='\0';
-         if(strstr(buf,"logdir ") != 0) {
-            if (getword(logdir,sizeof(logdir),buf,' ')<0 || getword(logdir,sizeof(logdir),buf,' ')<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",SquidGuardConf);
-               exit(1);
+         fixendofline(buf);
+         if((str=get_param_value("logdir",buf))!=NULL) {
+            /*
+            We want to tolerate spaces inside the directory name but we must also
+            remove the trailing spaces left by the editor after the directory name.
+            This should not be a problem as nobody use a file name with trailing spaces.
+            */
+            for (y=strlen(str)-1 ; y>=0 && (unsigned char)str[y]<=' ' ; y--);
+            if (y>=sizeof(logdir)-1) y=sizeof(logdir)-2;
+            logdir[y+1] = '\0';
+            while (y>=0) {
+               logdir[y] = str[y];
+               y--;
             }
-         }
-         if((str=(char *) strstr(buf, "log")) != (char *) NULL )  {
-            str=str+3;
-            str2[0]='\0';
-            y=0;
-            while(*str == ' ')
-              str++;
-           if (str == (char *) strstr(str, "anonymous"))
-               str+=9;
+         } else if((str=get_param_value("log",buf))!=NULL) {
+            if((str2=get_param_value("anonymous",str))!=NULL)
+               str=str2;
 
-            for (x=0; x<=strlen(str); x++) {
-               if (str[x] != ' ' && str[x] != '\t') {
-                  str2[y] = str[x];
-                  y++;
-               }
-            }
-            if(strchr(str2,' ') != 0) {
-               if (getword(warea,sizeof(warea),str2,' ')<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",SquidGuardConf);
-                  exit(1);
+            /*
+            If logdir is defined, we prepend it to the log file name, otherwise, we assume
+            the log directive provides an absolute file name to the log file. Therefore,
+            we don't need to add an additionnal / at the beginning of the log file name.
+            */
+            y=(logdir[0]) ? sprintf(wentp,"%s/",logdir) : 0;
+            /*
+            Spaces are allowed in the name of the log file. The file name ends at the first #
+            because it is assumed it is an end of line comment. Any space before the # is then
+            removed. Any control character (i.e. a character with a code lower than 32) ends
+            the file name. That includes the terminating zero.
+            */
+            while((unsigned char)*str>=' ' && *str!='#' && y<sizeof(wentp)-1)
+               wentp[y++]=*str++;
+            if(*str=='#') {
+               str--;
+               while(*str==' ' && y>0) {
+                  str--;
+                  y--;
                }
-               strcpy(str2,warea);
             }
-            if(strchr(str2,'#') != 0) {
-               if (getword(warea,sizeof(warea),str2,'#')<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",SquidGuardConf);
-                  exit(1);
-               }
-               strcpy(str2,warea);
-            }
-            sprintf(wentp,"%s/%s",logdir,str2);
+            wentp[y]=0;
             read_log(wentp,fp_ou);
          }
       }
    } else {
-      sprintf(wentp,"%s",SquidGuardLogAlternate);
+      strcpy(wentp,SquidGuardLogAlternate);
       read_log(wentp,fp_ou);
    }
 
    if (fp_guard) fclose(fp_guard);
    if (fp_ou) fclose(fp_ou);
 
+   if (files_done) {
+      for (y=0; y<nfiles_done; y++)
+         if (files_done[y]) free(files_done[y]);
+      free(files_done);
+   }
+
    if(debug) {
-      sprintf(msg,"%s: %s",text[54],guard_ou);
-      debuga(msg);
+      debuga(_("Sorting file: %s\n"),guard_ou);
    }
 
-   sprintf(tmp6,"sort -k 1,1 -k 2,2 -k 4,4 '%s' -o '%s'",guard_in, guard_ou);
+   sprintf(tmp6,"sort -k 1,1 -k 2,2 -k 4,4 \"%s\" -o \"%s\"",guard_in, guard_ou);
    cstatus=system(tmp6);
    if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-      fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus));
-      fprintf(stderr, "SARG: sort command: %s\n",tmp6);
-      exit(1);
+      debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
+      debuga(_("sort command: %s\n"),tmp6);
+      exit(EXIT_FAILURE);
    }
 
    unlink(guard_in);