root/fwknop/tags/fwknop-1.8/install.pl

Revision 686, 52.4 kB (checked in by mbr, 2 years ago)

minor Netfilter -> iptables wording update

  • 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 # URL: http://www.cipherdyne.org/fwknop
8 #
9 # Purpose: Installer for fwknop
10 #
11 # Credits:  (see the CREDITS file)
12 #
13 # Copyright (C) 2004-2007 Michael Rash (mbr@cipherdyne.org)
14 #
15 # License (GNU Public License):
16 #
17 #    This program is distributed in the hope that it will be useful,
18 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
19 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 #    GNU General Public License for more details.
21 #
22 #    You should have received a copy of the GNU General Public License
23 #    along with this program; if not, write to the Free Software
24 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
25 #    USA
26 #
27 #############################################################################
28 #
29 # $Id$
30 #
31
32 use Cwd;
33 use File::Copy;
34 use File::Path;
35 use Getopt::Long;
36 use Sys::Hostname;
37 use strict;
38
39 #========================== config ===========================
40 my $INIT_DIR    = '/etc/init.d';
41 my $USRBIN_DIR  = '/usr/bin';
42 my $URRSBIN_DIR = '/usr/sbin';
43
44 my $RUNLEVEL;    ### This should only be set if install.pl
45                  ### cannot determine the correct runlevel
46
47 ### only used it $ENV{'HOME'} is not set for some reason
48 my $config_homedir = '';
49
50 my $fwknop_conf_file = 'fwknop.conf';
51
52 ### system binaries
53 my $chkconfigCmd = '/sbin/chkconfig';
54 my $rcupdateCmd  = '/sbin/rc-update'### Gentoo
55 my $makeCmd      = '/usr/bin/make';
56 my $perlCmd      = '/usr/bin/perl';
57 my $gzipCmd      = '/bin/gzip';
58 my $killallCmd   = '/usr/bin/killall';
59 my $mknodCmd     = '/bin/mknod';
60 my $ifconfigCmd  = '/sbin/ifconfig';
61 #======================== end config =========================
62
63 ### main configuration hash
64 my %config = ();
65
66 my $client_install  = 0;
67 my $bsd_install = 0;
68 my $homedir = '';
69 my $distro = '';
70 my $print_help = 0;
71 my $uninstall  = 0;
72 my $syslog_conf = '';
73 my $data_method = '';
74 my $runlevel;
75 my $force_install_re  = '';
76 my $force_path_update = 0;
77 my $cmdline_force_install = 0;
78 my $skip_module_install   = 0;
79 my $force_defaults = 0;
80
81 my %exclude_cmds = (
82     'mail'        => '',
83     'fwknop'      => '',
84     'fwknopd'     => '',
85     'fwknop_serv' => '',
86     'knopmd'      => '',
87     'knoptm'      => '',
88     'knopwatchd'  => '',
89 );
90
91 ### perl module directories
92 my %required_perl_modules = (
93     'Class::MethodMaker' => {  ### GnuPG::Interface dependency
94         'force-install'       => 0,
95         'client-mode-install' => 1,
96         'mod-dir'             => 'Class-MethodMaker'
97     },
98     'GnuPG::Interface' => {
99         'force-install'       => 0,
100         'client-mode-install' => 1,
101         'mod-dir'             => 'GnuPG-Interface'
102     },
103     'Unix::Syslog' => {
104         'force-install'       => 0,
105         'client-mode-install' => 0,
106         'mod-dir'             => 'Unix-Syslog'
107     },
108     'Net::IPv4Addr' => {
109         'force-install'       => 0,
110         'client-mode-install' => 1,
111         'mod-dir'             => 'Net-IPv4Addr'
112     },
113     'List::MoreUtils' => {  ### Net::RawIP dependency
114         'force-install'       => 0,
115         'client-mode-install' => 0,
116         'mod-dir'             => 'List-MoreUtils'
117     },
118     'Net::RawIP' => {
119         'force-install'       => 0,
120         'client-mode-install' => 1,
121         'mod-dir'             => 'Net-RawIP'
122     },
123     'Net::Ping::External' => {
124         'force-install'       => 0,
125         'client-mode-install' => 1,
126         'mod-dir'             => 'Net-Ping-External'
127     },
128     'Net::Pcap' => {
129         'force-install'       => 0,
130         'client-mode-install' => 0,
131         'mod-dir'             => 'Net-Pcap'
132     },
133     'Crypt::Rijndael' => {
134         'force-install'       => 0,
135         'client-mode-install' => 1,
136         'mod-dir'             => 'Crypt-Rijndael'
137     },
138     'Crypt::CBC' => {
139         'force-install'       => 0,
140         'client-mode-install' => 1,
141         'mod-dir'             => 'Crypt-CBC'
142     },
143     'Term::ReadKey' => {
144         'force-install'       => 0,
145         'client-mode-install' => 1,
146         'mod-dir'             => 'TermReadKey'
147     },
148     'IPTables::Parse' => {
149         'force-install'       => 1,
150         'client-mode-install' => 0,
151         'mod-dir'             => 'IPTables-Parse'
152     },
153     'IPTables::ChainMgr' => {
154         'force-install'       => 1,
155         'client-mode-install' => 0,
156         'mod-dir'             => 'IPTables-ChainMgr'
157     }
158 );
159
160 my %cmds = (
161     'make'     => $makeCmd,
162     'perl'     => $perlCmd,
163     'gzip'     => $gzipCmd,
164     'killall'  => $killallCmd,
165     'mknod'    => $mknodCmd,
166     'ifconfig' => $ifconfigCmd,
167 );
168
169 my @cmd_search_paths = qw(
170     /bin
171     /sbin
172     /usr/bin
173     /usr/sbin
174     /usr/local/bin
175     /usr/local/sbin
176 );
177
178 ### for user answers
179 my $ACCEPT_YES_DEFAULT = 1;
180 my $ACCEPT_NO_DEFAULT  = 2;
181 my $NO_ANS_DEFAULT     = 0;
182
183 ### make Getopts case sensitive
184 Getopt::Long::Configure('no_ignore_case');
185
186 &usage(1) unless (GetOptions(
187     'force-mod-install' => \$cmdline_force_install,  ### force install of all modules
188     'Force-mod-regex=s' => \$force_install_re, ### force specific mod install with regex
189     'Skip-mod-install'  => \$skip_module_install,
190     'BSD-install'   => \$bsd_install,
191     'Defaults'      => \$force_defaults,
192     'client-only'   => \$client_install, # Force client-only installation
193     'path-update'   => \$force_path_update,
194     'uninstall'     => \$uninstall,      # Uninstall fwknop.
195     'syslog-conf=s' => \$syslog_conf,    # Specify path to syslog config file.
196     'help'          => \$print_help      # Display help.
197 ));
198 &usage(0) if $print_help;
199
200 ### import paths from default fwknopd.conf
201 &import_config();
202
203 ### check to see if we are installing on an ipfw system (freebsd, etc.)
204 if (&is_ipfw()) {
205
206     print
207 "[+] It looks like you are installing fwknop on a *BSD system. Installation\n",
208 "    of iptables perl modules will be skipped.\n";
209     $bsd_install = 1;
210
211 } elsif (&is_cygwin()) { ### check to see if we are installing on Cygwin
212
213     print
214 "[+] It looks like you are installing fwknop in a Cygwin environment, so the\n",
215 "    fwknop client will be installed (the fwknopd server does not yet\n",
216 "    function with a Windows-based firewall).\n\n";
217
218     $client_install = 1;
219
220 }
221
222 ### check to see if we are installing as a non-root user
223 &check_non_root_user() unless $client_install;
224
225 if ($client_install) {
226
227     ### we are installing as a normal user instead of root, so see
228     ### if it is ok to install within the user's home directory
229     $homedir = '';
230     if ($config_homedir) {
231         $homedir = $config_homedir;
232     } else {
233         $homedir = $ENV{'HOME'} or die '[*] Could not get home ',
234             "directory, set the $config_homedir var.";
235     }
236
237     print
238 "    The fwknop client will be installed at $homedir/bin/fwknop, and a few\n",
239 "    perl modules needed by fwknop will be installed in $homedir/lib/fwknop/.\n\n",
240
241     $config{'FWKNOP_MOD_DIR'} = "$homedir/lib/fwknop";
242     $USRBIN_DIR = "$homedir/bin";
243
244 } else {
245
246     unless ($bsd_install) {
247
248         $distro = &get_distro();
249
250         if ($distro eq 'redhat' or $distro eq 'fedora') {
251             ### add chkconfig only if we are runing on a redhat distro
252             $cmds{'chkconfig'} = $chkconfigCmd;
253         } elsif ($distro eq 'gentoo') {
254             ### add rc-update if we are running on a gentoo distro
255             $cmds{'rc-update'} = $rcupdateCmd;
256         }
257     }
258 }
259
260 ### make sure the system binaries are where we expect
261 ### them to be.
262 &check_commands();
263
264 my $hostname = hostname();
265
266 my $src_dir = getcwd() or die "[*] Could not get current working directory.";
267
268 unless ($client_install) {
269     unless (-d $INIT_DIR) {
270         if (-d '/etc/rc.d/init.d') {
271             $INIT_DIR = '/etc/rc.d/init.d';
272         } elsif (-d '/etc/rc.d') {  ### for Slackware
273             $INIT_DIR = '/etc/rc.d';
274         } else {
275             die "[*] Cannot find the init script directory, edit ",
276                 "the \$INIT_DIR variable.\n";
277         }
278     }
279 }
280
281 if (not $uninstall) {
282     &install();
283 } else {
284     &uninstall();
285 }
286 exit 0;
287 #======================= end main ==========================
288
289 sub install() {
290     print "[+] Installing fwknop on $hostname\n";
291
292     my $preserve_rv = 0;
293     unless ($client_install) {
294         if (&ask_to_stop_fwknop()) {
295             &stop_fwknop();
296         }
297
298         for my $dir qw| /usr/lib /var/run /var/log /var/lib | {
299             unless (-d $dir) {
300                 mkdir $dir or die "[*] Could not mkdir $dir: $!";
301             }
302         }
303         unless (-d $URRSBIN_DIR) {
304             mkdir $URRSBIN_DIR or die "[*] Could not mkdir $URRSBIN_DIR: $!";
305         }
306         for my $dir qw/FWKNOP_RUN_DIR FWKNOP_LIB_DIR FWKNOP_MOD_DIR/ {
307             unless (-d $config{$dir}) {
308                 mkdir $config{$dir} or
309                     die "[*] Could not mkdir $config{$dir}: $!";
310             }
311         }
312     }
313     unless (-d $USRBIN_DIR) {
314         print "[+] Creating: $USRBIN_DIR\n";
315         mkdir $USRBIN_DIR or die "[*] Could not mkdir $USRBIN_DIR: $!";
316     }
317
318     ### config directory
319     unless ($client_install) {
320         if (-d $config{'FWKNOP_CONF_DIR'}) {
321             print "[-] Config directory ",
322                 "$config{'FWKNOP_CONF_DIR'} already exists.\n";
323         } else {
324             ### Note that root will only be able to view files in
325             ### /etc/fwknop since fwknop only needs to view fwknop.conf
326             ### when being run as a daemon.
327             print "[+] Creating config directory: ",
328                 "$config{'FWKNOP_CONF_DIR'}\n";
329             mkdir $config{'FWKNOP_CONF_DIR'}, 0500
330                 or die "[*] Could not mkdir $config{'FWKNOP_CONF_DIR'}: $!";
331         }
332
333         if (-d $config{'FWKNOP_DIR'}) {
334             print "[-] Cache directory $config{'FWKNOP_DIR'} already exists.\n";
335         } else {
336             print "[+] Creating cache directory: $config{'FWKNOP_DIR'}\n";
337             mkdir $config{'FWKNOP_DIR'}, 0500
338                 or die "[*] Could not mkdir $config{'FWKNOP_DIR'}: $!";
339         }
340
341         ### archive directory for previously installed config files
342         if (-d "$config{'FWKNOP_CONF_DIR'}/archive") {
343             print "[-] Archive directory ",
344                 "$config{'FWKNOP_CONF_DIR'}/archive already exists.\n";
345         } else {
346             print "[+] Creating config{'FWKNOP_CONF_DIR'}/archive ",
347                 "directory: $config{'FWKNOP_CONF_DIR'}/archive\n";
348             mkdir "$config{'FWKNOP_CONF_DIR'}/archive", 0500 or die
349                 "[*] Could not mkdir $config{'FWKNOP_CONF_DIR'}/archive: $!";
350         }
351     }
352
353     print "[+] Several perl modules needed by fwknop will be installed in\n",
354         "    $config{'FWKNOP_MOD_DIR'}. Installing them here will keep the ",
355         "system perl\n    library tree clean.\n";
356
357     ### make our library directory (for perl modules)
358     if ($client_install) {
359         if (-d "$homedir/lib") {
360             print "[-] Directory $homedir/lib already exists.\n";
361         } else {
362             print "[+] Creating directory $homedir/lib\n";
363             mkdir "$homedir/lib", 0755
364                 or die "[*] Could not mkdir $homedir/lib: $!";
365         }
366     }
367     if (-d $config{'FWKNOP_MOD_DIR'}) {
368         print "[-] Lib directory $config{'FWKNOP_MOD_DIR'} already exists.\n";
369     } else {
370         print "[+] Creating directory $config{'FWKNOP_MOD_DIR'}\n";
371         mkdir $config{'FWKNOP_MOD_DIR'}, 0755
372             or die "[*] Could not mkdir $config{'FWKNOP_MOD_DIR'}: $!";
373     }
374
375     ### install perl modules
376     unless ($skip_module_install) {
377         for my $module (keys %required_perl_modules) {
378             &install_perl_module($module);
379         }
380     }
381
382     ### special case the NetPacket::<proto> modules since the NetPacket
383     ### directory is just for the base class, and we need to make sure
384     ### we have each of the NetPacket::IP, NetPacket::ICMP, NetPacket::UDP,
385     ### and NetPacket::TCP modules.
386     unless ($skip_module_install or $client_install) {
387         chdir 'NetPacket' or die "[*] Could not chdir NetPacket directory: $!";
388         unless (-e 'Makefile.PL') {
389             die "[*] Your NetPacket source directory appears to be incomplete!\n",
390                 "    Download the latest sources from ",
391                 "http://www.cipherdyne.org\n";
392         }
393         system "$cmds{'make'} clean" if -e 'Makefile';
394         system "$cmds{'perl'} Makefile.PL PREFIX=$config{'FWKNOP_MOD_DIR'} " .
395             "LIB=$config{'FWKNOP_MOD_DIR'}";
396         system $cmds{'make'};
397 #        system "$cmds{'make'} test";
398         system "$cmds{'make'} install";
399         chdir $src_dir or die "[*] Could not chdir $src_dir: $!";
400     }
401
402     unless ($client_install) {
403
404         ### install man pages
405         &install_manpage('knopmd.8');
406         &install_manpage('knopwatchd.8');
407         &install_manpage('fwknop.8');
408         &install_manpage('fwknopd.8');
409
410         if (-e "$config{'FWKNOP_CONF_DIR'}/fwknop.conf") {
411             $preserve_rv = &query_preserve_config();
412         }
413
414         print "[+] Compiling knopmd and knopwatchd daemons:\n";
415
416         ### remove any previously compiled knopmd
417         unlink 'knopmd' if -e 'knopmd';
418
419         ### remove any previously compiled knopwatchd
420         unlink 'knopwatchd' if -e 'knopwatchd';
421
422         ### compile the C fwknop daemons
423         system $cmds{'make'};
424
425         unless (-e 'knopmd' and -e 'knopwatchd') {
426             die "[*] Compilation failed.";
427         }
428
429         ### install fwknop server-side daemons/programs
430         for my $daemon qw(fwknopd knopmd knopwatchd knoptm fwknop_serv) {
431             if ($daemon eq 'fwknopd' or $daemon eq 'knoptm') {
432                 unless (((system "$cmds{'perl'} -c $daemon")>>8) == 0) {
433                     die "[*] $daemon does not compile with \"perl -c\".  ",
434                         "Download the latest sources ",
435                         "from:\n\nhttp://www.cipherdyne.org/\n";
436                 }
437             }
438             print "[+] Copying $daemon -> $URRSBIN_DIR\n";
439             copy $daemon, $URRSBIN_DIR or
440                 die "[*] Could not cp $daemon to $URRSBIN_DIR: $!";
441             chmod 0500, "$URRSBIN_DIR/$daemon" or
442                 die "[*] Could not chmod 500 $URRSBIN_DIR/$daemon: $!";
443         }
444     }
445
446     print "[+] Copying fwknop -> $USRBIN_DIR\n";
447     copy 'fwknop', $USRBIN_DIR or
448         die "[*] Could not cp fwknop to $USRBIN_DIR: $!";
449
450     if ($client_install) {
451         open F, "< $USRBIN_DIR/fwknop" or die "[*] Could not open ",
452             "$USRBIN_DIR/fwknop: $!";
453         my @lines = <F>;
454         close F;
455         open P, "> $USRBIN_DIR/fwknop.tmp" or die "[*] Could not open ",
456             "$USRBIN_DIR/fwknop.tmp: $!";
457         for my $line (@lines) {
458             ### change the lib dir to new homedir path
459             if ($line =~ m|^\s*use\s+lib\s+\'/usr/lib/fwknop\';|) {
460                 print P "use lib '", $config{'FWKNOP_MOD_DIR'}, "';\n";
461             } else {
462                 print P $line;
463             }
464         }
465         close P;
466         move "$USRBIN_DIR/fwknop.tmp", "$USRBIN_DIR/fwknop" or die "[*] Could ",
467             "not move $USRBIN_DIR/fwknop.tmp -> $USRBIN_DIR/fwknop: $!";
468         chmod 0700, "$USRBIN_DIR/fwknop" or
469             die "[*] Could not chmod 755 $USRBIN_DIR/fwknop: $!";
470     } else {
471         chmod 0755, "$USRBIN_DIR/fwknop" or
472             die "[*] Could not chmod 755 $USRBIN_DIR/fwknop: $!";
473     }
474
475     unless (((system "$cmds{'perl'} -c $USRBIN_DIR/fwknop")>>8) == 0) {
476         die "[*] $USRBIN_DIR/fwknop does not compile with \"perl -c\".  ",
477             "Download the latest sources ",
478             "from:\n\nhttp://www.cipherdyne.org/\n";
479     }
480
481
482     if ($client_install) {
483         print
484 "\n[+] fwknop has been installed at $USRBIN_DIR/fwknop.  Since this is a\n",
485 "    client-only install, the man pages could not be installed.  For more\n",
486 "    information about how to use fwknop, execute \"$USRBIN_DIR/fwknop -h\" or\n",
487 "    refer to:\n\n",
488 "        http://www.cipherdyne.org/fwknop/manpage.html\n\n";
489
490     } else {
491
492         ### install config and access files
493         for my $file qw(fwknop.conf access.conf pf.os) {
494             if (-e "$config{'FWKNOP_CONF_DIR'}/$file") {
495                 &archive("$config{'FWKNOP_CONF_DIR'}/$file");
496                 if ($preserve_rv) {
497                     if ($file eq 'access.conf') {
498                         ### access.conf can have missing fields (i.e.
499                         ### REQUIRE_OS_REGEX and REQUIRE_USERNAME),
500                         ### and also it can have multiple sequences
501                         ### defined.  Hence we just use the old one.
502                         print "[+] Using original access.conf\n";
503                     } elsif ($file ne 'pf.os') {
504                         &preserve_config($file);
505                     }
506                 } else {
507                     print "[+] Copying $file -> $config{'FWKNOP_CONF_DIR'}\n";
508                     copy $file, $config{'FWKNOP_CONF_DIR'} or
509                         die "[*] Could not cp $file to $config{'FWKNOP_CONF_DIR'}";
510                 }
511             } else {
512                 print "[+] Copying $file -> $config{'FWKNOP_CONF_DIR'}\n";
513                 copy $file, $config{'FWKNOP_CONF_DIR'} or
514                     die "[*] Could not cp $file to $config{'FWKNOP_CONF_DIR'}";
515             }
516
517             if ($force_path_update or not $preserve_rv) {
518                 &update_command_paths("$config{'FWKNOP_CONF_DIR'}/$file")
519                     if ($file eq 'fwknop.conf');
520             }
521
522             if ($file eq 'fwknop.conf') {
523                 &set_hostname("$config{'FWKNOP_CONF_DIR'}/$file");
524             }
525             chmod 0600, "$config{'FWKNOP_CONF_DIR'}/$file" or die
526                 "[*] Could not chmod(600, $config{'FWKNOP_CONF_DIR'}/$file: $!";
527             chown 0, 0, "$config{'FWKNOP_CONF_DIR'}/$file" or die
528                 "[*] Could not chown 0,0, $config{'FWKNOP_CONF_DIR'}/$file: $!";
529         }
530
531         ### get data acquisition method (e.g. syslogd, sysylog-ng, ulogd
532         ### or pcap)
533         $data_method = &query_data_method();
534
535         if ($data_method =~ /syslog/) {
536
537             ### create the named pipe
538             unless (-e $config{'KNOPMD_FIFO'} and -p $config{'KNOPMD_FIFO'}) {
539                 unlink $config{'KNOPMD_FIFO'} if -e $config{'KNOPMD_FIFO'};
540                 print "[+] Creating named pipe $config{'KNOPMD_FIFO'}\n";
541                 my $created_pipe = 1;
542                 unless (((system "$cmds{'mknod'} -m 600 $config{'KNOPMD_FIFO'} p")>>8)
543                         == 0) {
544                     $created_pipe = 0;
545                 }
546                 unless (-e $config{'KNOPMD_FIFO'} and -p $config{'KNOPMD_FIFO'}) {
547                     $created_pipe = 0;
548                 }
549                 unless ($created_pipe) {
550                     die
551 "[*] Could not create the named pipe \"$config{'KNOPMD_FIFO'}\"!\n",
552 "[*] fwknop requires this file to exist!  Aborting install.\n";
553                 }
554             }
555
556             unless (-e "$config{'FW_DATA_FILE'}") {
557                 print "[+] Creating $config{'FW_DATA_FILE'} file\n";
558                 open F, "> $config{'FW_DATA_FILE'}" or die "[*] Could not open ",
559                     "$config{'FW_DATA_FILE'}: $!";
560                 close F;
561                 chmod 0600, "$config{'FW_DATA_FILE'}";
562                 &perms_ownership("$config{'FW_DATA_FILE'}", 0600);
563             }
564
565             ### we are acquiring data via syslog
566             &put_string('AUTH_MODE', 'KNOCK',
567                 "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
568
569             if ($bsd_install) {
570                 ### update to use the ipfw firewall on *BSD systems
571                 &put_string('FIREWALL_TYPE', 'ipfw',
572                     "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
573             }
574
575             &put_string('SYSLOG_DAEMON', $data_method,
576                 "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
577
578             my $restarted_syslog = 0;
579             if ($data_method eq 'syslogd') {
580                 if (-e $syslog_conf) {
581                     &append_fifo_syslog($syslog_conf);
582                     if (((system "$cmds{'killall'} -HUP syslogd " .
583                             "2> /dev/null")>>8) == 0) {
584                         print "[+] HUP signal sent to syslogd.\n";
585                         $restarted_syslog = 1;
586                     }
587                 }
588             } elsif ($data_method eq 'syslog-ng') {
589                 if (-e $syslog_conf) {
590                     &append_fifo_syslog_ng($syslog_conf);
591                     if (((system "$cmds{'killall'} -HUP syslog-ng " .
592                             "2> /dev/null")>>8) == 0) {
593                         print "[+] HUP signal sent to syslog-ng.\n";
594                         $restarted_syslog = 1;
595                     }
596                 }
597             }
598
599             unless ($restarted_syslog) {
600                 print "[-] Could not restart any syslog daemons.\n";
601             }
602         } elsif ($data_method =~ /pcap/i or $data_method =~ /ulog/i) {
603             ### we are using a pcap method
604             if ($data_method eq 'ulogd' or $data_method eq 'file_pcap') {
605                 print
606 "[+] By default, fwknop uses the file /var/log/sniff.pcap in order to\n",
607 "    acquire packet data logged via a sniffer (or ulogd) to a pcap file,\n",
608 "    but this path may be changed by altering the PCAP_PKT_FILE keyword\n",
609 "    in $config{'FWKNOP_CONF_DIR'}/fwknop.conf.\n\n";
610
611                 if ($data_method eq 'file_pcap') {
612                     &put_string('AUTH_MODE', 'FILE_PCAP',
613                         "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
614                 } else {
615                     &put_string('AUTH_MODE', 'ULOG_PCAP',
616                         "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
617                 }
618             } else {
619                 my $intf = &get_pcap_intf();
620                 if ($intf) {
621                     &put_string('PCAP_INTF', $intf,
622                         "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
623                 } else {
624 print "[-] Could not get sniffing interface, need to set this manually in\n",
625     "    config{'FWKNOP_CONF_DIR'}/fwknop.conf\n";
626                 }
627             }
628         } else {
629             ### it is a client-only install, so don't reconfigure syslog
630             ### or anything.
631         }
632
633         unless ($preserve_rv) {
634             my $email_str = &query_email();
635             if ($email_str) {
636                 for my $file qw(fwknop.conf) {
637                     &put_string('EMAIL_ADDRESSES', $email_str,
638                         "$config{'FWKNOP_CONF_DIR'}/$file");
639                 }
640             }
641         }
642
643         if (-d $INIT_DIR) {
644             &enable_fwknop_at_boot($distro) unless $data_method =~ /client/i;
645         }
646
647         if ($data_method =~ /client/i) {
648             print "\n[+] fwknop has been installed!\n\n";
649         } else {
650             print
651 "\n[+] fwknop has been installed!  To start in server mode, run\n\n",
652 "    \"/etc/init.d/fwknop start\"\n\n",
653 "    Note: You will need to edit $config{'FWKNOP_CONF_DIR'}/access.conf for fwknop to\n",
654 "    function properly in server mode.  More information can be found in\n",
655 "    the fwknop manpage.\n\n";
656             if ($bsd_install) {
657                 print
658 "    You may need to updated your /etc/syslog.conf file to log local info\n",
659 "    messages to a file in the /var/log/ directory in order to see syslog\n",
660 "    messages from the fwknop daemons.\n\n";
661             }
662         }
663
664     }
665     return;
666 }
667
668 sub uninstall() {
669
670     print "[+] Uninstalling fwknop\n";
671
672     ### stop any running fwknop daemons.
673     &stop_fwknop();
674
675     unlink "$USRBIN_DIR/fwknop" if -e "$USRBIN_DIR/fwknop";
676     unlink "$URRSBIN_DIR/knopmd" if -e "$URRSBIN_DIR/knopmd";
677     unlink "$URRSBIN_DIR/knopwatchd" if -e "$URRSBIN_DIR/knopwatchd";
678     unlink "$INIT_DIR/fwknop" if -e "$INIT_DIR/fwknop";
679     rmtree $config{'FWKNOP_CONF_DIR'}, 1, 1 if -d $config{'FWKNOP_CONF_DIR'};
680     rmtree $config{'FWKNOP_LIB_DIR'}, 1, 1 if -d $config{'FWKNOP_LIB_DIR'};
681     rmtree $config{'FWKNOP_MOD_DIR'}, 1, 1 if -d $config{'FWKNOP_MOD_DIR'};
682
683     return;
684 }
685
686 ### check paths to commands and attempt to correct if any are wrong.
687 sub check_commands() {
688
689     return if $client_install;
690
691     unless ($bsd_install) {
692         $exclude_cmds{'ipfw'} = '';
693     }
694
695     CMD: for my $cmd (keys %cmds) {
696         if ($bsd_install) {
697             next CMD if $cmd eq 'iptables';
698         }
699         next CMD if defined $exclude_cmds{$cmd};
700         unless (-x $cmds{$cmd}) {
701             my $found = 0;
702             PATH: for my $dir (@cmd_search_paths) {
703                 if (-x "${dir}/${cmd}") {
704                     $cmds{$cmd} = "${dir}/${cmd}";
705                     $found = 1;
706                     last PATH;
707                 }
708             }
709             unless ($found) {
710                 die "[*] Could not find $cmd anywhere!!!  ",
711                     "Please edit the config section to include the path to ",
712                     "$cmd.\n";
713             }
714         }
715         unless (-x $cmds{$cmd}) {
716             die "[*] $cmd is located at ",
717                 "$cmds{$cmd} but is not executable by uid: $<\n";
718         }
719     }
720     return;
721 }
722
723 sub archive() {
724     my $file = shift;
725     return unless -e $file;
726     my $curr_pwd = cwd();
727     chdir "$config{'FWKNOP_CONF_DIR'}/archive" or die $!;
728     my ($filename) = ($file =~ m|.*/(.*)|);
729     my $base = "${filename}.old";
730     for (my $i = 5; $i > 1; $i--) {  ### keep five copies of old config files
731         my $j = $i - 1;
732         unlink "${base}${i}.gz" if -e "${base}${i}.gz";
733         move "${base}${j}.gz", "${base}${i}.gz" if -e "${base}${j}.gz";
734     }
735     print "[+] Archiving $file -> ${base}1\n";
736     unlink "${base}1.gz" if -e "${base}1.gz";
737     copy $file, "${base}1";   ### move $file into the archive directory
738     system "$cmds{'gzip'} ${base}1";
739     chdir $curr_pwd or die $!;
740     return;
741 }
742
743 sub preserve_config() {
744     my $file = shift;
745     open C, "< $file" or die "[*] Could not open $file: $!";
746     my @new_lines = <C>;
747     close C;
748
749     open CO, "< $config{'FWKNOP_CONF_DIR'}/$file" or die "[*] Could not open ",
750         "$config{'FWKNOP_CONF_DIR'}}/$file: $!&qu