havp/helper.cpp
changeset 0 8baf084f58c5
equal deleted inserted replaced
-1:000000000000 0:8baf084f58c5
       
     1 /***************************************************************************
       
     2                           helper.cpp  -  description
       
     3                              -------------------
       
     4     begin                : Sa M� 5 2005
       
     5     copyright            : (C) 2005 by Christian Hilgers
       
     6     email                : christian@hilgers.ag
       
     7  ***************************************************************************/
       
     8 
       
     9 /***************************************************************************
       
    10  *                                                                         *
       
    11  *   This program is free software; you can redistribute it and/or modify  *
       
    12  *   it under the terms of the GNU General Public License as published by  *
       
    13  *   the Free Software Foundation; either version 2 of the License, or     *
       
    14  *   (at your option) any later version.                                   *
       
    15  *                                                                         *
       
    16  ***************************************************************************/
       
    17 
       
    18 #include "default.h"
       
    19 #include "params.h"
       
    20 #include "logfile.h"
       
    21 
       
    22 #include <sys/types.h>
       
    23 #include <sys/stat.h>
       
    24 #include <sys/wait.h>
       
    25 #include <unistd.h>
       
    26 #include <fcntl.h>
       
    27 #include <pwd.h>
       
    28 #include <grp.h>
       
    29 #include <signal.h>
       
    30 #include <errno.h>
       
    31 #include <iostream>
       
    32 #include <fstream>
       
    33 #include <cstdlib>
       
    34 #include <cstring>
       
    35 
       
    36 extern char TempFileName[MAXSCANTEMPFILELENGTH+1];
       
    37 extern int fd_tempfile;
       
    38 
       
    39 static void ChildExited( int SignalNo )
       
    40 {
       
    41     //Handle with waitpid() in havp.cpp
       
    42 }
       
    43 
       
    44 static void ChildChildExited( int SignalNo )
       
    45 {
       
    46     int status;
       
    47     while (waitpid(-1, &status, WNOHANG) > 0);
       
    48 }
       
    49 
       
    50 static void RereadAll( int SignalNo )
       
    51 {
       
    52     extern bool rereadall;
       
    53     rereadall = true;
       
    54 }
       
    55 
       
    56 static void RestartChild( int SignalNo )
       
    57 {
       
    58     extern bool childrestart;
       
    59     childrestart = true;
       
    60 }
       
    61 
       
    62 static void ExitProcess( int SignalNo )
       
    63 {
       
    64     pid_t pgid = getpgid(0);
       
    65 
       
    66     //PSE: all processes have same pgid!
       
    67     if (getpid() == pgid)
       
    68     {
       
    69 	//PSE: only parent, no scan-file to delete!!
       
    70 	killpg(pgid,SIGINT);
       
    71 
       
    72 	//Delete pidfile
       
    73 	while (unlink(Params::GetConfigString("PIDFILE").c_str()) < 0 && (errno == EINTR || errno == EBUSY));
       
    74     }
       
    75     else
       
    76     {
       
    77         if (fd_tempfile > -1)
       
    78         {
       
    79             //Delete tempfile
       
    80             while (close(fd_tempfile) < 0 && errno == EINTR);
       
    81             while (unlink(TempFileName) < 0 && (errno == EINTR || errno == EBUSY));
       
    82         }
       
    83     }
       
    84 
       
    85     //End process
       
    86     exit(0);
       
    87 }
       
    88 
       
    89 
       
    90 //Install Signal Handlers for different fork levels
       
    91 int InstallSignal( int level )
       
    92 {
       
    93     struct sigaction Signal;
       
    94     memset(&Signal, 0, sizeof(Signal));
       
    95     Signal.sa_flags = 0;
       
    96 
       
    97     //Level 0 = Main Havp Process
       
    98     //Level 1 = ProxyHandler Process
       
    99     //Level 2 = Scanner Process
       
   100     //Signals are inherited from previous level at forking..
       
   101 
       
   102     if ( level == 0 ) //Main Havp Process
       
   103     {
       
   104         Signal.sa_handler = ExitProcess;
       
   105         if (sigaction(SIGINT, &Signal, NULL) != 0) return -1;
       
   106         if (sigaction(SIGTERM, &Signal, NULL) != 0) return -1;
       
   107 
       
   108         Signal.sa_handler = RereadAll;
       
   109         if (sigaction(SIGHUP, &Signal, NULL) != 0) return -1;
       
   110         //Compatibility for 0.77 and older init-script
       
   111         if (sigaction(SIGUSR2, &Signal, NULL) != 0) return -1;
       
   112 
       
   113         Signal.sa_handler = ChildExited;
       
   114         if (sigaction(SIGCHLD, &Signal, NULL) != 0) return -1;
       
   115 
       
   116         Signal.sa_handler = SIG_IGN;
       
   117         if (sigaction(SIGUSR1, &Signal, NULL) != 0) return -1;
       
   118         if (sigaction(SIGPIPE, &Signal, NULL) != 0) return -1;
       
   119     }
       
   120     else if ( level == 1 ) //ProxyHandler Process
       
   121     {
       
   122         Signal.sa_handler = RestartChild;
       
   123         if (sigaction(SIGUSR1, &Signal, NULL) != 0) return -1;
       
   124 
       
   125         Signal.sa_handler = ChildChildExited;
       
   126         if (sigaction(SIGCHLD, &Signal, NULL) != 0) return -1;
       
   127 
       
   128         Signal.sa_handler = SIG_IGN;
       
   129         if (sigaction(SIGHUP, &Signal, NULL) != 0) return -1;
       
   130         if (sigaction(SIGUSR2, &Signal, NULL) != 0) return -1;
       
   131     }
       
   132     else if ( level == 2 ) //Scanner Process
       
   133     {
       
   134         Signal.sa_handler = SIG_IGN;
       
   135         if (sigaction(SIGUSR1, &Signal, NULL) != 0) return -1;
       
   136     }
       
   137 
       
   138     return 0;
       
   139 }
       
   140 
       
   141 
       
   142 bool MakeDaemon()
       
   143 {
       
   144     pid_t daemon = fork();
       
   145 
       
   146     if ( daemon < 0 )
       
   147     {
       
   148         return false;
       
   149     }
       
   150     else if (daemon != 0)
       
   151     {
       
   152         //Exit Parent
       
   153         exit(0);
       
   154     }
       
   155     //Child
       
   156 
       
   157     setsid();
       
   158     chdir("/tmp/");
       
   159     umask(077);
       
   160 
       
   161     //Close stdin/stdout/stderr
       
   162     close(0);
       
   163     close(1);
       
   164     close(2);
       
   165 
       
   166     return true;
       
   167 }
       
   168 
       
   169 
       
   170 bool HardLockTest()
       
   171 {
       
   172     memset(&TempFileName, 0, sizeof(TempFileName));
       
   173     strncpy(TempFileName, Params::GetConfigString("SCANTEMPFILE").c_str(), MAXSCANTEMPFILELENGTH);
       
   174 
       
   175     if ((fd_tempfile = mkstemp(TempFileName)) < 0)
       
   176     {
       
   177         string Error = strerror(errno);
       
   178         cout << "Could not open lock testfile " << TempFileName << ": " << Error << endl;
       
   179         string user = Params::GetConfigString("USER");
       
   180         string scanpath = Params::GetConfigString("SCANTEMPFILE");
       
   181         cout << "Maybe you need to: chown " << user << " " << scanpath.substr(0, scanpath.rfind("/")) << endl;
       
   182         return false;
       
   183     }
       
   184 
       
   185 #ifndef NOMAND
       
   186     while (fchmod(fd_tempfile, S_IRUSR|S_IWUSR|S_IRGRP|S_ISGID) < 0)
       
   187 #else
       
   188     while (fchmod(fd_tempfile, S_IRUSR|S_IWUSR|S_IRGRP) < 0)
       
   189 #endif
       
   190     {
       
   191         if (errno == EINTR) continue;
       
   192 
       
   193         string Error = strerror(errno);
       
   194         cout << "Testfile fchmod() failed: " << Error << endl;
       
   195         return false;
       
   196     }
       
   197 
       
   198     char eicardata[] = "a5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*\0";
       
   199     eicardata[0] = 'X';
       
   200 
       
   201     while (write(fd_tempfile, eicardata, 68) < 0)
       
   202     {
       
   203         if (errno == EINTR) continue;
       
   204 
       
   205         LogFile::ErrorMessage("Could not write to Scannerfile: %s\n", TempFileName );
       
   206         return false;
       
   207     }
       
   208 
       
   209 #ifdef NOMAND
       
   210     return true;
       
   211 
       
   212 #else
       
   213     struct flock lock;
       
   214 
       
   215     lock.l_type   = F_WRLCK;
       
   216     lock.l_start  = 0;
       
   217     lock.l_whence = SEEK_SET;
       
   218     lock.l_len    = MAXFILELOCKSIZE;
       
   219 
       
   220     while (fcntl(fd_tempfile, F_SETLK, &lock) < 0)
       
   221     {
       
   222         if (errno == EINTR) continue;
       
   223 
       
   224         string Error = strerror(errno);
       
   225         cout << "Testfile fcntl() failed: " << Error << endl;
       
   226         return false;
       
   227     }
       
   228 
       
   229     if (lseek(fd_tempfile, 0, SEEK_SET) < 0)
       
   230     {
       
   231         string Error = strerror(errno);
       
   232         cout << "Testfile lseek() failed: " << Error << endl;
       
   233         return false;
       
   234     }
       
   235 
       
   236     pid_t testpid = fork();
       
   237 
       
   238     if (testpid < 0)
       
   239     {
       
   240         string Error = strerror(errno);
       
   241         cout << "Error forking lock test: " << Error << endl;
       
   242         return false;
       
   243     }
       
   244     else if (testpid != 0)
       
   245     {
       
   246         //Parent
       
   247         int status;
       
   248         while ((testpid = wait(&status)) < 0 && errno == EINTR);
       
   249 
       
   250         if (WEXITSTATUS(status) == 1)
       
   251         {
       
   252             return false;
       
   253         }
       
   254 
       
   255         //Descriptor not needed anymore
       
   256         while (close(fd_tempfile) < 0 && errno == EINTR);
       
   257         fd_tempfile = -1;
       
   258 
       
   259         return true;
       
   260     }
       
   261     //Child
       
   262 
       
   263     int fd;
       
   264 
       
   265     if ((fd = open(TempFileName, O_RDONLY)) < 0)
       
   266     {
       
   267         string Error = strerror(errno);
       
   268         cout << "Could not open lock testfile " << TempFileName << ": " << Error << endl;
       
   269         exit(1);
       
   270     }
       
   271 
       
   272     //Set nonblocking
       
   273     while (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
       
   274     {
       
   275         if (errno == EINTR) continue;
       
   276 
       
   277         string Error = strerror(errno);
       
   278         cout << "Testfile fcntl() failed: " << Error << endl;
       
   279         exit(1);
       
   280     }
       
   281 
       
   282     int testread;
       
   283     char tmpread[2];
       
   284 
       
   285     while ((testread = read(fd, tmpread, 1)) < 0 && errno == EINTR);
       
   286     while (close(fd) < 0 && errno == EINTR);
       
   287 
       
   288     if (testread > 0)
       
   289     {
       
   290         cout << "Filesystem not supporting mandatory locks!" << endl;
       
   291         cout << "On Linux, you need to mount filesystem with \"-o mand\"" << endl;
       
   292         exit(1);
       
   293     }
       
   294 
       
   295     //Success
       
   296     exit(0);
       
   297 #endif
       
   298 }
       
   299 
       
   300 
       
   301 bool ChangeUserAndGroup( string usr, string grp )
       
   302 {
       
   303     if ( geteuid() != 0 ) return true;
       
   304 
       
   305     if ( usr == "" || grp == "" )
       
   306     {
       
   307         cout << "You must define User and Group" << endl;
       
   308         return false;
       
   309     }
       
   310 
       
   311     struct passwd *user;
       
   312     struct group *my_group;
       
   313 
       
   314     if ( (user = getpwnam( usr.c_str() )) == NULL )
       
   315     {
       
   316         cout << "User does not exist: " << usr << endl;
       
   317         cout << "You need to: useradd " << usr << endl;
       
   318         return false;
       
   319     }
       
   320 
       
   321     if ( (my_group = getgrnam( grp.c_str() )) == NULL )
       
   322     {
       
   323         cout << "Group does not exist: " << grp << endl;
       
   324         cout << "You need to: groupadd " << grp << endl;
       
   325         return false;
       
   326     }
       
   327 
       
   328 #ifdef HAVE_INITGROUPS
       
   329     if ( initgroups( usr.c_str(), user->pw_gid ) )
       
   330     {
       
   331         cout << "Group initialization failed (initgroups)" << endl;
       
   332         return false;
       
   333     }
       
   334 #else
       
   335 #if HAVE_SETGROUPS
       
   336     if ( setgroups(1, &user->pw_gid) )
       
   337     {
       
   338         cout << "Group initialization failed (setgroups)" << endl;
       
   339         return false;
       
   340     }
       
   341 #endif
       
   342 #endif
       
   343 
       
   344     if ( setgid( my_group->gr_gid ) < 0 )
       
   345     {
       
   346         cout << "Could not change group to: " << grp << endl;
       
   347         return false;
       
   348     }
       
   349 
       
   350     if ( setuid( user->pw_uid ) < 0 )
       
   351     {
       
   352         cout << "Could not change user to: " << usr << endl;
       
   353         return false;
       
   354     }
       
   355 
       
   356     return true;
       
   357 }
       
   358 
       
   359 string GetUser()
       
   360 {
       
   361     struct passwd *user = getpwuid( geteuid() );
       
   362     if ( user == NULL ) return "<error>";
       
   363     return (string)user->pw_name;
       
   364 }
       
   365 
       
   366 string GetGroup()
       
   367 {
       
   368     struct group *my_group = getgrgid( getegid() );
       
   369     if ( my_group == NULL ) return "<error>";
       
   370     return (string)my_group->gr_name;
       
   371 }
       
   372 
       
   373 bool WritePidFile( pid_t havp_pid )
       
   374 {
       
   375     ofstream pidf( Params::GetConfigString("PIDFILE").c_str(), ios_base::trunc );
       
   376 
       
   377     if ( !pidf ) return false;
       
   378 
       
   379     pidf << havp_pid << endl;
       
   380 
       
   381     pidf.close();
       
   382 
       
   383     return true;
       
   384 }
       
   385