root/psad/tags/psad-2.0.2-pre5/install.pl

Revision 1859, 72.6 kB (checked in by mbr, 2 years ago)

added the ability to download the latest signatures from cipherdyne.org, added query_yes_no() to consolidate user input functions

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/perl -w
2 #
3 #########################################################################
4 #
5 # File: install.pl
6 #
7 # Purpose:  install.pl is the installation script for psad.  It is safe
8 #           to execute install.pl even if psad has already been installed
9 #           on a system since install.pl will preserve the existing
10 #           config section within the new script.
11 #
12 # Credits:  (see the CREDITS file)
13 #
14 # Copyright (C) 1999-2006 Michael Rash (mbr@cipherdyne.org)
15 #
16 # License (GNU Public License):
17 #
18 #    This program is distributed in the hope that it will be useful,
19 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
20 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 #    GNU General Public License for more details.
22 #
23 #    You should have received a copy of the GNU General Public License
24 #    along with this program; if not, write to the Free Software
25 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
26 #    USA
27 #
28 # TODO:
29 #
30 #########################################################################
31 #
32 # $Id$
33 #
34
35 use Cwd;
36 use File::Path;
37 use File::Copy;
38 use Sys::Hostname;
39 use IO::Socket;
40 use Getopt::Long;
41 use strict;
42
43 ### Note that Psad.pm is not included within the above list (installation
44 ### over existing psad should not make use of an old Psad.pm).
45
46 ### These three variables should not really be changed unless
47 ### you're really sure.
48 my $PSAD_DIR     = '/var/log/psad';
49 my $PSAD_CONFDIR = '/etc/psad';
50 my $VARLIBDIR    = '/var/lib/psad';
51 my $RUNDIR       = '/var/run/psad';
52 my $LIBDIR       = '/usr/lib/psad';
53 my $LIBDIR64     = '/usr/lib64/psad';
54
55 #============== config ===============
56 my $INSTALL_LOG  = "${PSAD_DIR}/install.log";
57 my $PSAD_FIFO    = "${VARLIBDIR}/psadfifo";
58 my $INIT_DIR     = '/etc/init.d';
59 my $USRSBIN_DIR  = '/usr/sbin'### consistent with FHS (Filesystem
60                                  ### Hierarchy Standard)
61 my $USRBIN_DIR   = '/usr/bin'### consistent with FHS (Filesystem
62 my $CONF_ARCHIVE = "${PSAD_CONFDIR}/archive";
63 my @LOGR_FILES   = (*STDOUT, $INSTALL_LOG);
64 my $RUNLEVEL;    ### This should only be set if install.pl
65                  ### cannot determine the correct runlevel
66 my $WHOIS_PSAD   = "${USRBIN_DIR}/whois_psad";
67
68 my $SIG_UPDATE_URL  = 'http://www.cipherdyne.org/psad/signatures';
69
70 ### directory in which to install snort rules
71 my $SNORT_DIR    = "${PSAD_CONFDIR}/snort_rules";
72
73 ### system binaries ###
74 my $chkconfigCmd = '/sbin/chkconfig';
75 my $rcupdateCmd  = '/sbin/rc-update'### Gentoo
76 my $gzipCmd      = '/usr/bin/gzip';
77 my $psCmd        = '/bin/ps';
78 my $netstatCmd   = '/bin/netstat';
79 my $ifconfigCmd  = '/sbin/ifconfig';
80 my $mknodCmd     = '/bin/mknod';
81 my $makeCmd      = '/usr/bin/make';
82 my $killallCmd   = '/usr/bin/killall';
83 my $perlCmd      = '/usr/bin/perl';
84 my $wgetCmd      = '/usr/bin/wget';
85 my $iptablesCmd  = '/sbin/iptables';
86 my $psadCmd      = "${USRSBIN_DIR}/psad";
87 #============ end config ============
88
89 ### map perl modules to versions
90 my %required_perl_modules = (
91     'Unix::Syslog' => {
92         'force-install' => 0,
93         'mod-dir' => 'Unix-Syslog'
94     },
95     'Bit::Vector' => {
96         'force-install' => 0,
97         'mod-dir' => 'Bit-Vector'
98     },
99     'Date::Calc', => {
100         'force-install' => 0,
101         'mod-dir' => 'Date-Calc'
102     },
103     'Net::IPv4Addr' => {
104         'force-install' => 0,
105         'mod-dir' => 'Net-IPv4Addr'
106     },
107     'IPTables::Parse' => {
108         'force-install' => 1,
109         'mod-dir' => 'IPTables-Parse'
110     },
111     'IPTables::ChainMgr' => {
112         'force-install' => 1,
113         'mod-dir' => 'IPTables-ChainMgr'
114     },
115     'Psad' => {
116         'force-install' => 1,
117         'mod-dir' => 'Psad'
118     }
119 );
120
121 my @cmd_search_paths = qw(
122     /bin
123     /sbin
124     /usr/bin
125     /usr/sbin
126     /usr/local/bin
127     /usr/local/sbin
128 );
129
130 ### IP regex
131 my $ip_re = qr|(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}|;
132
133 ### used to preserve old FW_MSG_SEARCH vars from previous
134 ### psad installation.  This is only needed when upgrading
135 ### to a newer version of psad that uses the fw_search.conf
136 ### file from a previous version that doesn't.
137 my @old_fw_msg_search;
138
139 ### get the hostname of the system
140 my $HOSTNAME = hostname();
141
142 my $src_dir = getcwd() or die "[*] Could not get current working directory.";
143
144 if (-e $INSTALL_LOG) {
145     open INSTALL, "> $INSTALL_LOG" or
146         die "[*] Could not open $INSTALL_LOG: $!";
147     close INSTALL;
148 }
149
150 ### scope these vars
151 my $PERL_INSTALL_DIR;  ### This is used to find pre-0.9.2 installations of psad
152
153 ### for user answers
154 my $ACCEPT_YES_DEFAULT = 1;
155 my $ACCEPT_NO_DEFAULT  = 2;
156 my $NO_ANS_DEFAULT     = 0;
157
158 ### set the install directory for the Psad.pm module
159 my $found = 0;
160 for my $dir (@INC) {
161     if ($dir =~ /site_perl\/\d\S+/) {
162         $PERL_INSTALL_DIR = $dir;
163         $found = 1;
164         last;
165     }
166 }
167 unless ($found) {
168     $PERL_INSTALL_DIR = $INC[0];
169 }
170
171 ### set the default execution flags and command line args
172 my $noarchive   = 0;
173 my $uninstall   = 0;
174 my $help        = 0;
175 my $archived_old = 0;
176 my $skip_syslog_test = 0;
177 my $skip_module_install   = 0;
178 my $cmdline_force_install = 0;
179 my $force_path_update = 0;
180 my $force_mod_re = '';
181 my $exclude_mod_re = '';
182 my $no_rm_old_lib_dir = 0;
183 my $syslog_conf = '';
184
185 ### make Getopts case sensitive
186 Getopt::Long::Configure('no_ignore_case');
187
188 &usage(1) unless (GetOptions(
189     'force-mod-install' => \$cmdline_force_install,  ### force install of all modules
190     'Force-mod-regex=s' => \$force_mod_re,  ### force specific mod install with regex
191     'Exclude-mod-regex=s' => \$exclude_mod_re, ### exclude a particular perl module
192     'path-update'       => \$force_path_update, ### update command paths
193     'Skip-mod-install'  => \$skip_module_install,
194     'no-rm-lib-dir'     => \$no_rm_old_lib_dir, ### remove any old /usr/lib/psad dir
195     'no-preserve'       => \$noarchive,   ### Don't preserve existing configs.
196     'syslog-conf=s'     => \$syslog_conf, ### specify path to syslog config file.
197     'no-syslog-test'    => \$skip_syslog_test,
198     'uninstall'         => \$uninstall,   ### Uninstall psad.
199     'help'              => \$help         ### Display help.
200 ));
201 &usage(0) if $help;
202
203 $force_mod_re = qr|$force_mod_re| if $force_mod_re;
204 $exclude_mod_re = qr|$exclude_mod_re| if $exclude_mod_re;
205
206 my %Cmds = (
207     'gzip'     => $gzipCmd,
208     'ps'       => $psCmd,
209     'mknod'    => $mknodCmd,
210     'netstat'  => $netstatCmd,
211     'ifconfig' => $ifconfigCmd,
212     'make'     => $makeCmd,
213     'killall'  => $killallCmd,
214     'perl'     => $perlCmd,
215     'iptables' => $iptablesCmd,
216 );
217
218 my $distro = &get_distro();
219
220 if ($distro eq 'redhat' or $distro eq 'fedora') {
221     ### add chkconfig only if we are runing on a redhat distro
222     $Cmds{'chkconfig'} = $chkconfigCmd;
223 } elsif ($distro eq 'gentoo') {
224     ### add rc-update if we are running on a gentoo distro
225     $Cmds{'rc-update'} = $rcupdateCmd;
226 }
227
228 my $init_dir = '';
229
230 if (-d $INIT_DIR) {
231     $init_dir = $INIT_DIR;
232 } elsif (-d '/etc/rc.d/init.d') {
233     $init_dir = '/etc/rc.d/init.d';
234 } elsif (-d '/etc/rc.d') {  ### for Slackware
235     $init_dir = '/etc/rc.d';
236 } else {
237     die "[*] Cannot find the init script directory, edit ",
238         "the \$INIT_DIR variable.\n";
239 }
240
241 ### need to make sure this exists before attempting to
242 ### write anything to the install log.
243 mkdir $PSAD_DIR, 0500 unless -d $PSAD_DIR;
244
245 ### make sure the system binaries are where we expect
246 ### them to be.
247 &check_commands();
248
249 $Cmds{'psad'} = $psadCmd;
250
251 ### check to make sure we are running as root
252 $< == 0 && $> == 0 or die "You need to be root (or equivalent UID 0",
253     " account) to install/uninstall psad!\n";
254
255 ### occasionally things from old psad installations need to be
256 ### dealt with separately.
257 &check_old_psad_installation();
258
259 if ($uninstall) {
260     &uninstall();
261 } else {
262     &install();
263 }
264 exit 0;
265 #================= end main =================
266
267 sub install() {
268
269     ### make sure install.pl is being called from the source directory
270     unless (-e 'psad' and -e 'Psad/lib/Psad.pm') {
271         die "[*] install.pl can only be executed from the directory\n",
272             "    that contains the psad sources!  Exiting.";
273     }
274     &logr('[+] ' . localtime() . " Installing psad on hostname: $HOSTNAME\n");
275
276     ### make sure another psad process is not running
277     if (&ask_to_stop_psad()) {
278         &stop_psad();
279     }
280
281     unless (-d $RUNDIR) {
282         &logr("[+] Creating $RUNDIR\n");
283         mkdir $RUNDIR, 0500;
284     }
285     unless (-d $VARLIBDIR) {
286         &logr("[+] Creating $VARLIBDIR\n");
287         mkdir $VARLIBDIR, 0500;
288     }
289
290     ### deal with old psad_auto_ips path
291     if (-e "${PSAD_CONFDIR}/psad_auto_ips") {
292         move "${PSAD_CONFDIR}/psad_auto_ips",
293             "${PSAD_CONFDIR}/auto_dl" or die "[*] Could not move ",
294             "${PSAD_CONFDIR}/psad_auto_ips -> ${PSAD_CONFDIR}/auto_dl: $!";
295     }
296     ### deal with old psad_signatures path
297     if (-e "${PSAD_CONFDIR}/psad_signatures") {
298         move "${PSAD_CONFDIR}/psad_signatures",
299             "${PSAD_CONFDIR}/signatures" or die "[*] Could not move ",
300             "${PSAD_CONFDIR}/psad_signatures -> ${PSAD_CONFDIR}/signatures: $!";
301     }
302     ### deal with old psad_posf path
303     if (-e "${PSAD_CONFDIR}/psad_posf") {
304         move "${PSAD_CONFDIR}/psad_posf",
305             "${PSAD_CONFDIR}/posf" or die "[*] Could not move ",
306             "${PSAD_CONFDIR}/psad_posf -> ${PSAD_CONFDIR}/posf: $!";
307     }
308     ### deal with old psad_icmp_types path
309     if (-e "${PSAD_CONFDIR}/psad_icmp_types") {
310         move "${PSAD_CONFDIR}/psad_icmp_types",
311             "${PSAD_CONFDIR}/icmp_types" or die "[*] Could not move ",
312             "${PSAD_CONFDIR}/psad_icmp_types -> ${PSAD_CONFDIR}/icmp_types: $!";
313     }
314
315     ### change any existing psad module directory to allow anyone to import
316     for my $dir ($LIBDIR, $LIBDIR64) {
317         if (-d $dir) {
318             chmod 0755, $dir;
319             unless ($no_rm_old_lib_dir) {
320                 &logr("[+] Removing $dir/ directory from previous " .
321                     "psad installation.\n");
322                 rmtree $dir;
323             }
324         }
325     }
326     unless (-d $PSAD_CONFDIR) {
327         &logr("[+] Creating $PSAD_CONFDIR\n");
328         mkdir $PSAD_CONFDIR, 0500;
329     }
330     unless (-d $CONF_ARCHIVE) {
331         &logr("[+] Creating $CONF_ARCHIVE\n");
332         mkdir $CONF_ARCHIVE, 0500;
333     }
334     unless (-e $PSAD_FIFO) {
335         &logr("[+] Creating named pipe $PSAD_FIFO\n");
336         unless (((system "$Cmds{'mknod'} -m 600 $PSAD_FIFO p")>>8) == 0) {
337             &logr("[*] Could not create the named pipe \"$PSAD_FIFO\"!\n" .
338                 "[*] psad requires this file to exist!  Aborting install.\n");
339             die;
340         }
341         unless (-p $PSAD_FIFO) {
342             &logr("[*] Could not create the named pipe \"$PSAD_FIFO\"!\n" .
343                 "[*] psad requires this file to exist!  Aborting " .
344                 "install.\n");
345             die;
346         }
347     }
348
349     unless (-d $PSAD_DIR) {
350         &logr("[+] Creating $PSAD_DIR\n");
351         mkdir $PSAD_DIR, 0500;
352     }
353     unless (-e "${PSAD_DIR}/fwdata") {
354         &logr("[+] Creating ${PSAD_DIR}/fwdata file\n");
355         open F, "> ${PSAD_DIR}/fwdata" or die "[*] Could not open ",
356             "${PSAD_DIR}/fwdata: $!";
357         close F;
358         chmod 0600, "${PSAD_DIR}/fwdata";
359         &perms_ownership("${PSAD_DIR}/fwdata", 0600);
360     }
361
362     unless (-d $USRSBIN_DIR) {
363         &logr("[+] Creating $USRSBIN_DIR\n");
364         mkdir $USRSBIN_DIR,0755;
365     }
366     if (-d 'whois') {
367         &logr("[+] Compiling Marco d'Itri's whois client\n");
368         system "$Cmds{'make'} -C whois";
369         if (-e 'whois/whois') {
370             &logr("[+] Copying whois binary to $WHOIS_PSAD\n");
371             copy "whois/whois", $WHOIS_PSAD or die "[*] Could not copy ",
372                 "whois/whois -> $WHOIS_PSAD: $!";
373         } else {
374             die "[*] Could not compile whois";
375         }
376     }
377     &perms_ownership($WHOIS_PSAD, 0755);
378     print "\n\n";
379
380     ### install perl modules
381     unless ($skip_module_install) {
382         for my $module (keys %required_perl_modules) {
383             &install_perl_module($module);
384         }
385     }
386
387     &logr("[+] Installing Snort-2.3.3 signatures in $SNORT_DIR\n");
388     unless (-d $SNORT_DIR) {
389         mkdir $SNORT_DIR, 0500 or die "[*] Could not create $SNORT_DIR: $!";
390     }
391     opendir D, 'snort_rules' or die "[*] Could not open ",
392         "the snort_rules directory: $!";
393     my @files = readdir D;
394     closedir D;
395
396     for my $file (@files) {
397         next unless $file =~ /\.rules$/ or $file =~ /\.config$/;
398         &logr("[+] Installing snort_rules/${file}\n");
399         copy "snort_rules/${file}", "${SNORT_DIR}/${file}" or
400             die "[*] Could not copy snort_rules/${file} -> ",
401                 "${SNORT_DIR}/${file}: $!";
402         &perms_ownership("${SNORT_DIR}/${file}", 0600);
403     }
404     print "\n\n";
405
406     &logr("[+] Compiling kmsgsd, and psadwatchd:\n");
407
408     ### remove any previously compiled kmsgsd
409     unlink 'kmsgsd' if -e 'kmsgsd';
410
411     ### remove any previously compiled psadwatchd
412     unlink 'psadwatchd' if -e 'psadwatchd';
413
414     ### compile the C psad daemons
415     system $Cmds{'make'};
416     if (! -e 'kmsgsd' && -e 'kmsgsd.pl') {
417         &logr("[-] Could not compile kmsgsd.c.  Installing perl kmsgsd.\n");
418         unless (((system "$Cmds{'perl'} -c kmsgsd.pl")>>8) == 0) {
419             die "[*] kmsgsd.pl does not compile with \"perl -c\".  ",
420                 "Download the latest sources " .
421                 "from:\n\nhttp://www.cipherdyne.org/\n";
422         }
423         copy 'kmsgsd.pl', 'kmsgsd' or die "[*] Could not copy ",
424             "kmsgsd.pl -> kmsgsd: $!";
425     }
426     if (! -e 'psadwatchd' && -e 'psadwatchd.pl') {
427         &logr("[-] Could not compile psadwatchd.c.  " .
428             "Installing perl psadwatchd.\n");
429         unless (((system "$Cmds{'perl'} -c psadwatchd.pl")>>8) == 0) {
430             die "[*] psadwatchd.pl does not compile with \"perl -c\".  ",
431                 "Download the latest sources " .
432                 "from:\n\nhttp://www.cipherdyne.org/\n";
433         }
434         copy 'psadwatchd.pl', 'psadwatchd' or die "[*] Could not copy ",
435             "psadwatchd.pl -> psadwatchd: $!";
436     }
437
438     ### install fwcheck_psad.pl
439     print "\n\n";
440     &logr("[+] Verifying compilation of fwcheck_psad.pl script:\n");
441     unless (((system "$Cmds{'perl'} -c fwcheck_psad.pl")>>8) == 0) {
442         die "[*] fwcheck_psad.pl does not compile with \"perl -c\".  Download ",
443             "the latest sources from:\n\nhttp://www.cipherdyne.org/\n";
444     }
445
446     ### make sure the psad (perl) daemon compiles.  The other three
447     ### daemons have all been re-written in C.
448     &logr("[+] Verifying compilation of psad perl daemon:\n");
449     unless (((system "$Cmds{'perl'} -c psad")>>8) == 0) {
450         die "[*] psad does not compile with \"perl -c\".  Download the",
451             " latest sources from:\n\nhttp://www.cipherdyne.org/\n";
452     }
453     print "\n\n";
454
455     ### install nf2csv
456     print "\n\n";
457     &logr("[+] Verifying compilation of nf2csv script:\n");
458     unless (((system "$Cmds{'perl'} -c nf2csv")>>8) == 0) {
459         die "[*] nf2csv does not compile with \"perl -c\".  Download ",
460             "the latest sources from:\n\nhttp://www.cipherdyne.org/\n";
461     }
462
463     ### put the nf2csv script in place
464     unlink '/usr/sbin/nf2csv' if -e '/usr/sbin/nf2csv'### old path
465     &logr("[+] Copying nf2csv -> ${USRBIN_DIR}/nf2csv\n");
466     unlink "${USRBIN_DIR}/nf2csv" if -e "${USRBIN_DIR}/nf2csv";
467     copy 'nf2csv', "${USRBIN_DIR}/nf2csv" or die "[*] Could ",
468         "not copy nf2csv -> ${USRBIN_DIR}/nf2csv: $!";
469     &perms_ownership("${USRBIN_DIR}/nf2csv", 0755);
470
471     ### put the fwcheck_psad.pl script in place
472     &logr("[+] Copying fwcheck_psad.pl -> ${USRSBIN_DIR}/fwcheck_psad\n");
473     unlink "${USRSBIN_DIR}/fwcheck_psad" if -e "${USRSBIN_DIR}/fwcheck_psad";
474     copy 'fwcheck_psad.pl', "${USRSBIN_DIR}/fwcheck_psad" or die "[*] Could ",
475         "not copy fwcheck_psad.pl -> ${USRSBIN_DIR}/fwcheck_psad: $!";
476     &perms_ownership("${USRSBIN_DIR}/fwcheck_psad", 0500);
477
478     ### put the psad daemons in place
479     &logr("[+] Copying psad -> ${USRSBIN_DIR}/psad\n");
480     unlink "${USRSBIN_DIR}/psad" if -e "${USRSBIN_DIR}/psad";
481     copy 'psad', "${USRSBIN_DIR}/psad" or die "[*] Could not copy ",
482         "psad -> ${USRSBIN_DIR}/psad: $!";
483     &perms_ownership("${USRSBIN_DIR}/psad", 0500);
484
485     &logr("[+] Copying psadwatchd -> ${USRSBIN_DIR}/psadwatchd\n");
486     unlink "${USRSBIN_DIR}/psadwatchd" if -e "${USRSBIN_DIR}/psadwatchd";
487     copy 'psadwatchd', "${USRSBIN_DIR}/psadwatchd" or die "[*] Could not ",
488         "copy psadwatchd -> ${USRSBIN_DIR}/psadwatchd: $!";
489     &perms_ownership("${USRSBIN_DIR}/psadwatchd", 0500);
490
491     &logr("[+] Copying kmsgsd -> ${USRSBIN_DIR}/kmsgsd\n");
492     unlink "${USRSBIN_DIR}/kmsgsd" if -e "${USRSBIN_DIR}/kmsgsd";
493     copy 'kmsgsd', "${USRSBIN_DIR}/kmsgsd" or die "[*] Could not copy ",
494         "kmsgsd -> ${USRSBIN_DIR}/kmsgsd: $!";
495     &perms_ownership("${USRSBIN_DIR}/kmsgsd", 0500);
496
497     unless (-d $PSAD_CONFDIR) {
498         &logr("[+] Creating $PSAD_CONFDIR\n");
499         mkdir $PSAD_CONFDIR,0500;
500     }
501
502     ### get syslog daemon (e.g. syslog, syslog-ng, or metalog)
503     my $syslog_str = &query_syslog();
504
505     my $preserve_rv = 0;
506     if (-e "${PSAD_CONFDIR}/psad.conf") {
507         $preserve_rv = &query_preserve_config();
508     }
509
510     ### the order of the config files is important (legacy FW_MSG_SEARCH
511     ### vars in psad.conf).
512     for my $file qw(psad.conf psadwatchd.conf
513             kmsgsd.conf fw_search.conf alert.conf) {
514         if (-e "${PSAD_CONFDIR}/$file") {
515             &archive("${PSAD_CONFDIR}/$file") unless $noarchive;
516             if ($preserve_rv) {
517                 &preserve_config($file);
518             } else {
519                 &logr("[+] Copying $file -> ${PSAD_CONFDIR}/$file\n");
520                 copy $file, "${PSAD_CONFDIR}/$file" or die "[*] Could not ",
521                     "copy $file -> ${PSAD_CONFDIR}/$file: $!";
522             }
523             if ($file eq 'fw_search.conf' and @old_fw_msg_search) {
524                 &logr("[-] Warning: psad.conf contains FW_MSG_SEARCH vars, " .
525                     "but fw_search.conf also exists!\n");
526             }
527         } else {
528             &logr("[+] Copying $file -> ${PSAD_CONFDIR}/$file\n");
529             copy $file, "${PSAD_CONFDIR}/$file" or die "[*] Could not copy ",
530                 "$file -> ${PSAD_CONFDIR}/$file: $!";
531
532             ### Deal with legacy FW_MSG_SEARCH in psad.conf.  Note that
533             ### this will only preserve old search strings if 1) they already
534             ### existed within psad.conf and 2) the file fw_search.conf does
535             ### not already exist in /etc/psad/.
536             if ($file eq 'fw_search.conf' and @old_fw_msg_search) {
537                 &preserve_old_fw_msg_search();
538             }
539         }
540
541         if ($force_path_update or not $preserve_rv) {
542             &update_command_paths("$PSAD_CONFDIR/$file")
543                 if ($file eq 'psad.conf' or $file eq 'psadwatchd.conf');
544         }
545
546         &perms_ownership("${PSAD_CONFDIR}/$file", 0600);
547     }
548
549     ### deal with any legacy diskmond.conf file
550     if (-e "${PSAD_CONFDIR}/diskmond.conf") {
551         &archive("${PSAD_CONFDIR}/diskmond.conf") unless $noarchive;
552         unlink "${PSAD_CONFDIR}/diskmond.conf";
553     }
554
555     ### install auto_dl, signatures, icmp_types, posf, and pf.os files
556     for my $file qw(signatures icmp_types
557             posf auto_dl snort_rule_dl pf.os ip_options) {
558         if (-e "${PSAD_CONFDIR}/$file") {
559             &archive("${PSAD_CONFDIR}/$file") unless $noarchive;
560 ### FIXME, need a real config preservation routine for these files.
561 #            unless (&query_preserve_sigs_autodl("${PSAD_CONFDIR}/$file")) {
562         }
563         &logr("[+] Copying $file -> ${PSAD_CONFDIR}/$file\n");
564         copy $file, "${PSAD_CONFDIR}/$file" or die "[*] Could not ",
565             "copy $file -> ${PSAD_CONFDIR}/$file: $!";
566         &perms_ownership("${PSAD_CONFDIR}/$file", 0600);
567     }
568     &logr("\n");
569
570     unless ($preserve_rv) {  ### we want to preserve the existing config
571
572         ### get email address(es)
573         my $email_str = &query_email();
574         if ($email_str) {
575             for my $file qw(psad.conf psadwatchd.conf) {
576                 &put_string('EMAIL_ADDRESSES', $email_str,
577                     "${PSAD_CONFDIR}/$file");
578             }
579         }
580
581         ### Give the admin the opportunity to set the strings that are
582         ### parsed out of iptables messages.  This is useful since the
583         ### admin may have configured the firewall to use a logging prefix
584         ### of "Audit" or something else other than the default string
585         ### "DROP".
586         my $fw_search_aref = &get_fw_search_strings();
587         if ($fw_search_aref) {
588             open F, "< ${PSAD_CONFDIR}/fw_search.conf"
589                 or die "[*] Could not open ${PSAD_CONFDIR}/fw_search.conf: $!";
590             my @lines = <F>;
591             close F;
592             open T, "> ${PSAD_CONFDIR}/fw_search.conf.tmp"
593                 or die "[*] Could not open ${PSAD_CONFDIR}/fw_search.conf.tmp: $!";
594             for my $line (@lines) {
595                 if ($line =~ /^\s*FW_MSG_SEARCH/) {
596                     last;
597                 } else {
598                     print T $line;
599                 }
600             }
601             for my $fw_str (@$fw_search_aref) {
602                 &logr(qq{[+] Setting FW_MSG_SEARCH to "$fw_str" } .
603                     "in ${PSAD_CONFDIR}/fw_search.conf\n");
604                 printf T "%-28s%s;\n", 'FW_MSG_SEARCH', $fw_str;
605             }
606             close T;
607             move "${PSAD_CONFDIR}/fw_search.conf.tmp",
608                 "${PSAD_CONFDIR}/fw_search.conf" or die "[*] Could not move ",
609                 "${PSAD_CONFDIR}/fw_search.conf.tmp -> ",
610                 "${PSAD_CONFDIR}/fw_search.conf: $!";
611         }
612         ### Give the admin the opportunity to set the HOME_NET variable.
613         &set_home_net("${PSAD_CONFDIR}/psad.conf");
614
615         ### see if the admin would like to have psad send info to
616         ### DShield
617         if (&query_dshield()) {
618             &put_string('ENABLE_DSHIELD_ALERTS', 'Y',
619                 "${PSAD_CONFDIR}/psad.conf");
620         }
621
622         ### Set the hostname
623         for my $file ("${PSAD_CONFDIR}/psad.conf",
624                 "${PSAD_CONFDIR}/kmsgsd.conf",
625                 "${PSAD_CONFDIR}/psadwatchd.conf") {
626             &logr("[+] Setting hostname to \"$HOSTNAME\" in $file\n");
627             &set_hostname($file);
628         }
629     }
630
631     &put_string('SYSLOG_DAEMON', $syslog_str,
632         "${PSAD_CONFDIR}/psad.conf");
633
634     if ($syslog_str ne 'ulogd') {
635         my $restarted_syslog = 0;
636         if ($syslog_str eq 'syslogd') {
637             if (-e $syslog_conf) {
638                 &append_fifo_syslog($syslog_conf);
639                 if (((system "$Cmds{'killall'} -HUP syslogd 2> /dev/null")>>8) == 0) {
640                     &logr("[+] HUP signal sent to syslogd.\n");
641                     $restarted_syslog = 1;
642                 }
643             }
644         } elsif ($syslog_str eq 'syslog-ng') {
645             if (-e $syslog_conf) {
646                 &append_fifo_syslog_ng($syslog_conf);
647                 if (((system "$Cmds{'killall'} -HUP syslog-ng 2> /dev/null")>>8) == 0) {
648                     &logr("[+] HUP signal sent to syslog-ng.\n");
649                     $restarted_syslog = 1;
650                 }
651             }
652         } elsif ($syslog_str eq 'metalog') {
653             if (-e $syslog_conf) {
654                 &config_metalog($syslog_conf);
655                 &logr("[-] Metalog support is shaky in psad.  " .
656                     "Use at your own risk.\n");
657                 ### don't send warning about not restarting metalog daemon
658                 $restarted_syslog = 1;
659             }
660         }
661
662         unless ($restarted_syslog) {
663             &logr("[-] Could not restart any syslog daemons.\n");
664         }
665     }
666
667     if (-x $Cmds{'iptables'} and not $skip_syslog_test) {
668         &logr("[+] Found iptables. Testing syslog configuration:\n");
669         ### make sure we actually see packets being logged by
670         ### the firewall.
671         if ($syslog_str ne 'ulogd') {
672             if (&test_syslog_config($syslog_str)) {
673                 &logr("[+] Successful $syslog_str reconfiguration.\n\n");
674             } else {
675                 if (&query_init_script_restart_syslog()) {
676
677                     my $restarted = 0;
678                     if (-e "$INIT_DIR/sysklogd") {
679                         system "$INIT_DIR/sysklogd restart";
680                         $restarted = 1;
681                     } elsif (-e "$INIT_DIR/syslog") {
682                         system "$INIT_DIR/syslogd restart";
683                         $restarted = 1;
684                     }
685                     ### test syslog config again now that we
686                     ### have restarted syslog via the init script
687                     ### instead of relying on a HUP signal to
688                     ### syslog
689                     if ($restarted) {
690                         if (&test_syslog_config($syslog_str)) {
691                             &logr("[+] Successful $syslog_str reconfiguration.\n\n");
692                         } else {
693                             &logr("[-] Unsuccessful $syslog_str reconfiguration.\n");
694                             &logr("    Consult the psad man page for the basic " .
695                                 "$syslog_str requirement to get psad to work.\n\n");
696                         }
697                     }
698                 } else {
699                     &logr("[-] Ok, hoping that psad can get packet data anyway.\n");
700                 }
701             }
702         }
703     }
704
705     ### download signatures?
706     &download_signatures() if &query_signatures();
707
708     ### make sure the PSAD_DIR and PSAD_FIFO variables are correctly defined
709     ### in psad.conf and kmsgsd.conf
710     &put_string('PSAD_DIR', $PSAD_DIR, "${PSAD_CONFDIR}/psad.conf");
711     &put_string('PSAD_FIFO', $PSAD_FIFO, "${PSAD_CONFDIR}/kmsgsd.conf");
712
713     &install_manpage('psad.8');
714     &install_manpage('psadwatchd.8');
715     &install_manpage('kmsgsd.8');
716     &install_manpage('nf2csv.1');
717
718     my $init_file = '';
719     if ($distro eq 'redhat') {
720         $init_file = 'init-scripts/psad-init.redhat';
721     } elsif ($distro eq 'fedora') {
722         $init_file = 'init-scripts/psad-init.fedora';
723     } elsif ($distro eq 'gentoo') {
724         $init_file = 'init-scripts/psad-init.gentoo';
725     } else {
726         $init_file = 'init-scripts/psad-init.generic';
727     }
728
729     if ($init_dir) {
730         &logr("[+] Copying $init_file -> ${init_dir}/psad\n");
731         copy $init_file, "${init_dir}/psad" or die "[*] Could not copy ",
732             "$init_file -> ${init_dir}/psad: $!";
733         &perms_ownership("${init_dir}/psad", 0744);
734         &enable_psad_at_boot($distro);
735     }
736
737     &logr("\n========================================================\n");
738     if ($archived_old) {
739         &logr("[+] Copies of your original configs have been made " .
740             "in: $CONF_ARCHIVE\n");
741     }
742     if ($preserve_rv) {
743         &logr("\n[+] Psad has been installed (with your original config merged).\n");
744     } else {
745         &logr("\n[+] Psad has been installed.\n");
746     }
747     if ($init_dir) {
748         &logr("\n[+] To start psad, run \"${init_dir}/psad start\"\