root/fwknop/tags/fwknop-1.8.2-pre7/install.pl

Revision 738, 56.5 kB (checked in by mbr, 1 year ago)

added OS X startup files

  • 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 $cygwin_install = 0;
69 my $homedir = '';
70 my $distro  = '';
71 my $print_help  = 0;
72 my $uninstall   = 0;
73 my $syslog_conf = '';
74 my $data_method = '';
75 my $runlevel;
76 my $force_install_re  = '';
77 my $force_path_update = 0;
78 my $cmdline_force_install = 0;
79 my $skip_module_install   = 0;
80 my $force_defaults  = 0;
81 my $cmdline_os_type = '';
82 my $os_type = 0;
83
84 ### unless --OS-type is used, install.pl will try to figure out the
85 ### OS where fwknop is being installed (this is usually best).
86 my $OS_LINUX  = 1;
87 my $OS_BSD    = 2;
88 my $OS_CYGWIN = 3;
89 my $OS_DARWIN = 4;  ### Mac OS X
90
91 my %os_types = (
92     'linux'  => $OS_LINUX,
93     'bsd'    => $OS_BSD,
94     'cygwin' => $OS_CYGWIN,
95     'darwin' => $OS_DARWIN
96 );
97
98 my %exclude_cmds = (
99     'mail'        => '',
100     'fwknop'      => '',
101     'fwknopd'     => '',
102     'fwknop_serv' => '',
103     'knopmd'      => '',
104     'knoptm'      => '',
105     'knopwatchd'  => '',
106 );
107
108 ### perl module directories
109 my @required_perl_modules = (
110     {   'module'              =>'Class::MethodMaker', ### GnuPG::Interface dependency
111         'force-install'       => 0,
112         'client-mode-install' => 1,
113         'mod-dir'             => 'Class-MethodMaker'
114     },
115     {   'module'              => 'GnuPG::Interface',
116         'force-install'       => 0,
117         'client-mode-install' => 1,
118         'mod-dir'             => 'GnuPG-Interface'
119     },
120     {   'module'              => 'Unix::Syslog',
121         'force-install'       => 0,
122         'client-mode-install' => 0,
123         'mod-dir'             => 'Unix-Syslog'
124     },
125     {   'module'              => 'Net::IPv4Addr',
126         'force-install'       => 0,
127         'client-mode-install' => 1,
128         'mod-dir'             => 'Net-IPv4Addr'
129     },
130     {   'module'              => 'Net::Pcap',
131         'force-install'       => 0,
132         'client-mode-install' => 0,
133         'mod-dir'             => 'Net-Pcap'
134     },
135     {   'module'              => 'List::MoreUtils'### Net::RawIP dependency
136         'force-install'       => 0,
137         'client-mode-install' => 1,
138         'mod-dir'             => 'List-MoreUtils'
139     },
140     {   'module'              => 'Net::RawIP',
141         'force-install'       => 0,
142         'client-mode-install' => 1,
143         'mod-dir'             => 'Net-RawIP'
144     },
145     {   'module'              => 'Net::Ping::External',
146         'force-install'       => 0,
147         'client-mode-install' => 1,
148         'mod-dir'             => 'Net-Ping-External'
149     },
150     {   'module'              => 'Crypt::Rijndael',
151         'force-install'       => 0,
152         'client-mode-install' => 1,
153         'mod-dir'             => 'Crypt-Rijndael'
154     },
155     {   'module'              => 'Crypt::CBC',
156         'force-install'       => 0,
157         'client-mode-install' => 1,
158         'mod-dir'             => 'Crypt-CBC'
159     },
160     {   'module'              => 'Term::ReadKey',
161         'force-install'       => 0,
162         'client-mode-install' => 1,
163         'mod-dir'             => 'TermReadKey'
164     },
165     {   'module'              => 'IPTables::Parse',
166         'force-install'       => 1,
167         'client-mode-install' => 0,
168         'mod-dir'             => 'IPTables-Parse'
169     },
170     {   'module'              => 'IPTables::ChainMgr',
171         'force-install'       => 1,
172         'client-mode-install' => 0,
173         'mod-dir'             => 'IPTables-ChainMgr'
174     }
175 );
176
177 my %cmds = (
178     'make'     => $makeCmd,
179     'perl'     => $perlCmd,
180     'gzip'     => $gzipCmd,
181     'killall'  => $killallCmd,
182     'mknod'    => $mknodCmd,
183     'ifconfig' => $ifconfigCmd,
184 );
185
186 my @cmd_search_paths = qw(
187     /bin
188     /sbin
189     /usr/bin
190     /usr/sbin
191     /usr/local/bin
192     /usr/local/sbin
193 );
194
195 ### for user answers
196 my $ACCEPT_YES_DEFAULT = 1;
197 my $ACCEPT_NO_DEFAULT  = 2;
198 my $NO_ANS_DEFAULT     = 0;
199
200 ### make Getopts case sensitive
201 Getopt::Long::Configure('no_ignore_case');
202
203 &usage(1) unless (GetOptions(
204     'force-mod-install' => \$cmdline_force_install,  ### force install of all modules
205     'Force-mod-regex=s' => \$force_install_re, ### force specific mod install with regex
206     'Skip-mod-install'  => \$skip_module_install,
207     'OS-type=s'         => \$cmdline_os_type,
208     'Cygwin-install'    => \$cygwin_install,
209     'BSD-install'   => \$bsd_install,
210     'Defaults'      => \$force_defaults,
211     'client-only'   => \$client_install, # Force client-only installation
212     'path-update'   => \$force_path_update,
213     'uninstall'     => \$uninstall,      # Uninstall fwknop.
214     'syslog-conf=s' => \$syslog_conf,    # Specify path to syslog config file.
215     'help'          => \$print_help      # Display help.
216 ));
217 &usage(0) if $print_help;
218
219 &handle_cmd_line();
220
221 ### import paths from default fwknopd.conf
222 &import_config();
223
224 ### check to see if we are installing as a non-root user
225 &check_non_root_user() unless $client_install;
226
227 if ($client_install) {
228
229     ### we are installing as a normal user instead of root, so see
230     ### if it is ok to install within the user's home directory
231     $homedir = '';
232     if ($config_homedir) {
233         $homedir = $config_homedir;
234     } else {
235         $homedir = $ENV{'HOME'} or die '[*] Could not get home ',
236             "directory, set the $config_homedir var.";
237     }
238
239     print
240 "    The fwknop client will be installed at $homedir/bin/fwknop, and a few\n",
241 "    perl modules needed by fwknop will be installed in $homedir/lib/fwknop/.\n\n",
242
243     $config{'FWKNOP_MOD_DIR'} = "$homedir/lib/fwknop";
244     $USRBIN_DIR = "$homedir/bin";
245 }
246
247 ### get the OS type
248 &get_os() unless $os_type;
249
250 if ($os_type == $OS_LINUX) {
251     print "[+] OS: Linux\n";
252 } elsif ($os_type == $OS_CYGWIN) {
253     print "[+] OS: Cygwin\n";
254 } elsif ($os_type == $OS_DARWIN) {
255     print "[+] OS: Darwin\n";
256 } elsif ($os_type == $OS_BSD) {
257     print "[+] OS: BSD\n";
258 }
259
260 if ($os_type == $OS_LINUX) {
261
262     $distro = &get_linux_distro();
263
264     if ($distro eq 'redhat' or $distro eq 'fedora') {
265         ### add chkconfig only if we are runing on a redhat distro
266         $cmds{'chkconfig'} = $chkconfigCmd;
267     } elsif ($distro eq 'gentoo') {
268         ### add rc-update if we are running on a gentoo distro
269         $cmds{'rc-update'} = $rcupdateCmd;
270     }
271 }
272
273 ### make sure the system binaries are where we expect
274 ### them to be.
275 &check_commands();
276
277 my $hostname = hostname();
278
279 my $src_dir = getcwd() or die "[*] Could not get current working directory.";
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 $mod_href (@required_perl_modules) {
378             &install_perl_module($mod_href);
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/docs/manpages/index.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 ($os_type == $OS_BSD or $os_type == $OS_DARWIN) {
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
604             if ($os_type == $OS_BSD or $os_type == $OS_DARWIN) {
605                 ### update to use the ipfw firewall on *BSD systems
606                 &put_string('FIREWALL_TYPE', 'ipfw',
607                     "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
608             }
609
610             ### we are using a pcap method
611             if ($data_method eq 'ulogd' or $data_method eq 'file_pcap') {
612                 print
613 "[+] By default, fwknop uses the file /var/log/sniff.pcap in order to\n",
614 "    acquire packet data logged via a sniffer (or ulogd) to a pcap file,\n",
615 "    but this path may be changed by altering the PCAP_PKT_FILE keyword\n",
616 "    in $config{'FWKNOP_CONF_DIR'}/fwknop.conf.\n\n";
617
618                 if ($data_method eq 'file_pcap') {
619                     &put_string('AUTH_MODE', 'FILE_PCAP',
620                         "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
621                 } else {
622                     &put_string('AUTH_MODE', 'ULOG_PCAP',
623                         "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
624                 }
625             } else {
626                 my $intf = &get_pcap_intf();
627                 if ($intf) {
628                     &put_string('PCAP_INTF', $intf,
629                         "$config{'FWKNOP_CONF_DIR'}/fwknop.conf");
630                 } else {
631 print "[-] Could not get sniffing interface, need to set this manually in\n",
632     "    config{'FWKNOP_CONF_DIR'}/fwknop.conf\n";
633                 }
634             }
635         } else {
636             ### it is a client-only install, so don't reconfigure syslog
637             ### or anything.
638         }
639
640         unless ($preserve_rv) {
641             my $email_str = &query_email();
642             if ($email_str) {
643                 for my $file qw(fwknop.conf) {
644                     &put_string('EMAIL_ADDRESSES', $email_str,
645                         "$config{'FWKNOP_CONF_DIR'}/$file");
646                 }
647             }
648         }
649
650
651         if ($client_install) {
652             print "\n[+] fwknop has been installed!\n\n";
653         } else {
654
655             &get_init_dir();
656             if (-d $INIT_DIR) {
657                 &enable_fwknop_at_boot($distro);
658             }
659
660             print
661 "\n[+] fwknop has been installed!  To start in server mode, run\n\n",
662 "    \"/etc/init.d/fwknop start\"\n\n",
663 "    Note: You will need to edit $config{'FWKNOP_CONF_DIR'}/access.conf for fwknop to\n",
664 "    function properly in server mode.  More information can be found in\n",
665 "    the fwknopd(8) manpage.\n\n";
666             if ($os_type == $OS_BSD or $os_type == $OS_DARWIN) {
667                 print
668 "    You may need to update your /etc/syslog.conf file to log local info\n",
669 "    messages to a file in the /var/log/ directory in order to see syslog\n",
670 "    messages from the fwknop daemons.\n\n";
671             }
672         }
673
674     }
675     return;
676 }
677
678 sub uninstall() {
679
680     print "[+] Uninstalling fwknop\n";
681
682     ### stop any running fwknop daemons.
683     &stop_fwknop();
684
685     ### get the init directory
686     &get_init_dir();
687
688     unlink "$USRBIN_DIR/fwknop" if -e "$USRBIN_DIR/fwknop";
689     unlink "$URRSBIN_DIR/knopmd" if -e "$URRSBIN_DIR/knopmd";
690     unlink "$URRSBIN_DIR/knopwatchd" if -e "$URRSBIN_DIR/knopwatchd";
691     unlink "$INIT_DIR/fwknop" if -e "$INIT_DIR/fwknop";
692     rmtree $config{'FWKNOP_CONF_DIR'}, 1, 1 if -d $config{'FWKNOP_CONF_DIR'};
693     rmtree $config{'FWKNOP_LIB_DIR'}, 1, 1 if -d $config{'FWKNOP_LIB_DIR'};
694     rmtree $config{'FWKNOP_MOD_DIR'}, 1, 1 if -d $config{'FWKNOP_MOD_DIR'};
695
696     return;
697 }
698
699 sub get_init_dir() {
700     return if $client_install;
701
702     if ($os_type == $OS_DARWIN) {
703
704         ### Mac OS X init directory for user programs
705         $INIT_DIR = '/Library/StartupItems';
706         die "[*] The $INIT_DIR directory does not exist."
707             unless -d $INIT_DIR;
708         return;
709     }
710
711     ### acommodates Linux and BSD systems
712     unless (-d $INIT_DIR) {
713         if (-d '/etc/rc.d/init.d') {
714             $INIT_DIR = '/etc/rc.d/init.d';
715         } elsif (-d '/etc/rc.d') {
716             $INIT_DIR = '/etc/rc.d';
717         } elsif (-d '/etc/init.d') {
718             $INIT_DIR = '/etc/init.d';
719         } else {
720             die "[*] Cannot find the init script directory, edit ",
721                 "the \$INIT_DIR variable.\n";
722         }
723     }
724     return;
725 }
726
727 ### check paths to commands and attempt to correct if any are wrong.
728 sub check_commands() {
729
730     return if $client_install;
731
732     if ($os_type == $OS_LINUX or $os_type == $OS_CYGWIN) {
733         $exclude_cmds{'ipfw'} = '';
734     } else {
735         ### we are installing on BSD or Mac OS X
736         $exclude_cmds{'iptables'} = '';
737     }
738
739     CMD: for my $cmd (keys %cmds) {
740         unless (-x $cmds{$cmd}) {
741             my $found = 0;
742             PATH: for my $dir (@cmd_search_paths) {
743                 if (-x "${dir}/${cmd}") {
744                     $cmds{$cmd} = "${dir}/${cmd}";
745                     $found = 1;
746                     last PATH;
747                 }
748             }
749             unless ($found) {
750