#!/usr/bin/perl -w ##=====================================================================## ## Copyright (C) 2001-2002 Stephen Zarkos. All rights reserved. ## Obsid@Sentry.net ## ## Please see file: COPYRIGHT for further copyright information and ## disclaimer. Or online at http://www.SentryFirewall.com/files/COPYRIGHT ##=====================================================================## ## File: do_config.pl $ENV{PATH} = "/bin:/sbin"; umask 022; ##-------------------------------------------------------------------------## ## Sub do_config() ## Parses config in @conf and sets things up. sub do_config { my ($status,$filename,$rclink,$uname,$uid,$gid) = ''; ## Hash lists startup scripts present in /etc/rc.d/init.d associated with their ## init start/stop order. ## Filename Start/Stop my %services = ('innd' => { 'start' => 'S95', 'stop' => 'K05', 'default' => 'stop' }, 'mysqld' => { 'start' => 'S78', 'stop' => 'K12', 'default' => 'stop' }, 'gpm' => { 'start' => 'S85', 'stop' => 'K15', 'default' => 'stop' }, 'httpd' => { 'start' => 'S85', 'stop' => 'K15', 'default' => 'stop' }, 'rarpd' => { 'start' => 'S82', 'stop' => 'K16', 'default' => 'stop' }, 'bootparamd' => { 'start' => 'S60', 'stop' => 'K20', 'default' => 'stop' }, 'nfs' => { 'start' => 'S60', 'stop' => 'K20', 'default' => 'stop' }, 'rstatd' => { 'start' => 'S60', 'stop' => 'K20', 'default' => 'stop' }, 'rusersd' => { 'start' => 'S60', 'stop' => 'K20', 'default' => 'stop' }, 'rwhod' => { 'start' => 'S60', 'stop' => 'K20', 'default' => 'stop' }, 'squid' => { 'start' => 'S90', 'stop' => 'K25', 'default' => 'stop' }, 'amd' => { 'start' => 'S72', 'stop' => 'K28', 'default' => 'stop' }, 'yppasswdd' => { 'start' => 'S66', 'stop' => 'K34', 'default' => 'stop' }, 'dhcpd' => { 'start' => 'S65', 'stop' => 'K35', 'default' => 'stop' }, 'smb' => { 'start' => 'S91', 'stop' => 'K35', 'default' => 'stop' }, 'mars-nwe' => { 'start' => 'S60', 'stop' => 'K40', 'default' => 'stop' }, 'named' => { 'start' => 'S55', 'stop' => 'K45', 'default' => 'stop' }, 'arpwatch' => { 'start' => 'S55', 'stop' => 'K45', 'default' => 'stop' }, 'radvd' => { 'start' => 'S54', 'stop' => 'K46', 'default' => 'stop' }, 'snmpd' => { 'start' => 'S50', 'stop' => 'K50', 'default' => 'stop' }, 'routed' => { 'start' => 'S55', 'stop' => 'K55', 'default' => 'stop' }, 'identd' => { 'start' => 'S35', 'stop' => 'K65', 'default' => 'stop' }, 'ntpd' => { 'start' => 'S26', 'stop' => 'K74', 'default' => 'stop' }, 'ups' => { 'start' => 'S26', 'stop' => 'K74', 'default' => 'stop' }, 'ypserv' => { 'start' => 'S26', 'stop' => 'K74', 'default' => 'stop' }, 'ypxfrd' => { 'start' => 'S26', 'stop' => 'K74', 'default' => 'stop' }, 'gated' => { 'start' => 'S32', 'stop' => 'K75', 'default' => 'stop' }, 'sendmail' => { 'start' => 'S80', 'stop' => 'K30', 'default' => 'stop' }, 'iscsi' => { 'start' => 'S83', 'stop' => 'K20', 'default' => 'stop' }, 'apmd' => { 'start' => 'S26', 'stop' => 'K74', 'default' => 'stop' }, 'bgpd' => { 'start' => 'S16', 'stop' => 'K84', 'default' => 'stop' }, 'ospf6d' => { 'start' => 'S16', 'stop' => 'K84', 'default' => 'stop' }, 'ospfd' => { 'start' => 'S16', 'stop' => 'K84', 'default' => 'stop' }, 'ripd' => { 'start' => 'S16', 'stop' => 'K84', 'default' => 'stop' }, 'ripngd' => { 'start' => 'S16', 'stop' => 'K84', 'default' => 'stop' }, 'zebra' => { 'start' => 'S15', 'stop' => 'K85', 'default' => 'stop' }, 'bcm5820' => { 'start' => 'S11', 'stop' => 'K89', 'default' => 'stop' }, 'irda' => { 'start' => 'S45', 'stop' => 'K96', 'default' => 'stop' }, 'kudzu' => { 'start' => 'S05', 'stop' => 'K95', 'default' => 'start' }, 'ipchains' => { 'start' => 'S08', 'stop' => 'K92', 'default' => 'start' }, 'iptables' => { 'start' => 'S08', 'stop' => 'K92', 'default' => 'start' }, 'isdn' => { 'start' => 'S09', 'stop' => 'K91', 'default' => 'start' }, 'network' => { 'start' => 'S10', 'stop' => 'K90', 'default' => 'start' }, 'syslog' => { 'start' => 'S12', 'stop' => 'K88', 'default' => 'start' }, 'portmap' => { 'start' => 'S13', 'stop' => 'K87', 'default' => 'start' }, 'nfslock' => { 'start' => 'S14', 'stop' => 'K86', 'default' => 'start' }, 'keytable' => { 'start' => 'S17', 'stop' => 'K05', 'default' => 'start' }, 'random' => { 'start' => 'S20', 'stop' => 'K80', 'default' => 'start' }, 'netfs' => { 'start' => 'S25', 'stop' => 'K75', 'default' => 'start' }, 'autofs' => { 'start' => 'S28', 'stop' => 'K72', 'default' => 'start' }, 'snortd' => { 'start' => 'S40', 'stop' => 'K60', 'default' => 'start' }, 'sshd' => { 'start' => 'S55', 'stop' => 'K25', 'default' => 'start' }, 'rawdevices' => { 'start' => 'S56', 'stop' => 'K44', 'default' => 'start' }, 'xinetd' => { 'start' => 'S56', 'stop' => 'K50', 'default' => 'start' }, 'lpd' => { 'start' => 'S60', 'stop' => 'K60', 'default' => 'start' }, 'crond' => { 'start' => 'S90', 'stop' => 'K60', 'default' => 'start' }, 'anacron' => { 'start' => 'S95', 'stop' => 'K05', 'default' => 'start' }, 'atd' => { 'start' => 'S95', 'stop' => 'K05', 'default' => 'start' }, 'local' => { 'start' => 'S99', 'stop' => '', 'default' => 'start' } ); ## rc and configuration file directives. To add a new directive, simply ## add a new array variable. You may have to also add elements into %specdir ## to tell the config scripts where that file should go. By default files ## matching /^rc\./ are put in /etc/rc.d, and all others will just go in /etc, ## unless otherwise specified in %specdir. my (@etc_vars) = ('rc.local', 'rc.news', 'rc.firewall', 'rc.firewall.nat', 'passwd', 'shadow', 'group', 'fstab', 'hosts.equiv', 'profile', 'xinetd.conf', 'snort.conf', 'resolv.conf', 'hosts', 'proftpd.conf', 'shells', 'ftpusers', 'syslog.conf', 'named.conf', 'squid.conf', 'pptpd.conf', 'gated.conf', 'zebra.conf', 'syslog-ng.conf', 'pppoe.conf', 'smb.conf', 'httpd.conf', 'openssl.cnf', 'sysconf_dir', 'xinetd_dir', 'inittab'); ## SSH host keys are created by rc.sshd if not supplied here, there are NO ## default ssh host keys on the rootdisk, for obvious reasons. my (@ssh_vars) = ('shosts.equiv', 'ssh_config', 'sshd_config', 'ssh_host_dsa_key', 'ssh_host_dsa_key.pub', 'ssh_host_rsa_key', 'ssh_host_rsa_key.pub', 'ssh_host_key', 'ssh_host_key.pub', 'ssh_known_hosts', 'ssh_known_hosts2'); ## Hash to tell me where certain config files should go, otherwise they'll just end ## up in /etc. ## Filename Directory my %specdir = ( 'squid.conf', '/etc/squid', 'smb.conf', '/etc/samba', 'zebra.conf', '/etc/zebra', 'httpd.conf', '/etc/httpd/conf', 'pppoe.conf', '/etc/ppp', 'pptpd.conf', '/etc/pptpd', 'syslog-ng.conf', '/etc/syslog-ng', 'openssl.cnf', '/etc/ssl'); ## "device" directive stuff. Setup networking. $net += &networking('NET_UP'); ## Process 'nameserver' directive. if (exists($prefs{'nameserver'})) { &do_log("Processing \'nameserver\' directive..."); if ($prefs{'nameserver'} ne '') { my(@resolv_cnf) = (); $status = ''; if (-f "/etc/resolv.conf") { if (open(FH,"; close(FH); } } if (open(FH,">/etc/resolv.conf")) { flock(FH,2); print FH "nameserver $prefs{nameserver}\n"; foreach(@resolv_cnf) { print FH "$_"; } close(FH); } else { &do_log("ERROR: Unable to open /etc/resolv.conf"); } } delete($prefs{'nameserver'}); } ## Call include() to retrieve any include files. if (exists($prefs{'include'})) { if ($prefs{'include'} eq '') { delete($prefs{'include'}); } else { &do_include($net); } } ## Mount cdrom, saves a possible headache instead of relying on rc.cdrom. if (exists($prefs{'cdrom'})) { $prefs{'cdrom'} =~ s/^(\/.+\/)+//; if (($prefs{'cdrom'} =~ /^\w+\d*$/) && (-b "/dev/$prefs{cdrom}")) { if (open(FH, ">/etc/_CDROM_")) { flock(FH,2); ## Request Exclusive Lock print FH "$prefs{cdrom}"; close(FH); if (!(-l "/etc/rc.d/rc.cdrom")) { chmod 0444, "/etc/rc.d/rc.cdrom"; } else { chmod 0444, "/etc/default/rc.d/rc.cdrom"; } } if (open(FH, ">>/etc/fstab")) { flock(FH,2); print FH "\n/dev/$prefs{cdrom} /cdrom iso9660 defaults,ro 0 0\n"; close(FH); } } else { &do_log("Syntax error in $prefs{cdrom}."); } delete($prefs{'cdrom'}); } ## Check to see if $prefs{"$_"} is a valid file, and retrieve file ## if destination looks like a http(s)/(s)ftp/scp URL. my $var = ""; foreach $var (keys %prefs) { next if (($prefs{$var} eq '') || ($var eq '')); next if ("$var" =~ /^device\d$/); next if ("$var" =~ /^(http|ftp)_proxy$/); next if ("$var" =~ /^proxy\-(user|passwd)$/); if (($prefs{"$var"} =~ /^[hH]{1}[tT]{2}[pP]{1}[sS]?:\/\//) || ($prefs{"$var"} =~ /^[sS]?[fF]{1}[tT]{1}[pP]{1}:\/\//) || ($prefs{"$var"} =~ /^[sS]{1}[cC]{1}[pP]{1}:\/\//)) { if ($net > "0") { $status = 'NULL'; $status = &retr_file($var, $prefs{"$var"}); if (($status !~ /^\d$/) && ($status ne 'NULL')) { $prefs{$var} = "$status"; } else { if ($status eq "2") { print "ERROR: Unable to retrieve ${var}, request timed out.\n"; &do_log("ERROR: Unable to retrieve ${var}, request timed out."); } else { ## $status == 0 print "ERROR: Unable to retrieve ${var}.\n"; &do_log("ERROR: Unable to retrieve ${var}."); } delete($prefs{"$var"}); next; } } else { print "ERROR: Unable to retrieve ${var}, device not configured.\n"; &do_log("ERROR: Unable to retrieve ${var}, device not configured."); delete($prefs{$var}); } next; } ## Check to see if $prefs{"$var"} is a valid file. if (!(-e "$prefs{$var}")) { if ((-d "${m_point}/$prefs{$var}") && (($var eq 'sysconf_dir') || ($var eq 'xinetd_dir'))) { $prefs{$var} =~ s/^\/+//; &do_log("WARNING: Using \"${m_point}/$prefs{$var}\" instead of \"$prefs{$var}\""); $prefs{"$var"} = "${m_point}/$prefs{$var}"; $prefs{"$var"} =~ s/\/{2,}/\//g; } elsif (-f "${m_point}/$prefs{$var}") { $prefs{$var} =~ s/^\/+//; &do_log("WARNING: Using \"${m_point}/$prefs{$var}\" instead of \"$prefs{$var}\""); $prefs{"$var"} = "${m_point}/$prefs{$var}"; $prefs{"$var"} =~ s/\/{2,}/\//g; } else { &do_log("ERROR: \"$prefs{$var}\" does not exist."); delete($prefs{"$var"}); next; } } } ## End foreach ## If /etc/shadow is not replaced, display a warning about using default passwords. ## Also, do not utilize user's xinetd.conf and sshd_config if declared. Use more ## restictive default ones instead to prevent sshd, telnetd, and ftpd from listening ## for external connections. if (!(exists($prefs{'shadow'}))) { print "WARNING: /etc/shadow not replaced, default passwords are inherently insecure!\n"; &do_log("WARNING: /etc/shadow not replaced, default passwords are inherently insecure!"); ## If user is using default /etc/shadow, don't allow xinetd to run services. ## This may irritate some people... oh well, *tear* if (exists($prefs{'xinetd.conf'})) { system("cp -p $prefs{'xinetd.conf'} /etc/xinetd.conf.user 1>/dev/null 2>/dev/null"); delete($prefs{'xinetd.conf'}); &do_log("WARNING: Directive \"xinetd.conf\" ignored, using strict defaults."); } if (exists($prefs{'sshd_config'})) { system("cp -p $prefs{'sshd_config'} /etc/ssh/sshd_config.user 1>/dev/null 2>/dev/null"); delete($prefs{'sshd_config'}); &do_log("WARNING: Directive \"sshd_config\" ignored, using strict defaults."); } ## Use system default xinetd.conf(/etc/default/xinetd.conf). if (-f '/etc/default/xinetd.conf') { symlink('/etc/default/xinetd.conf', '/etc/xinetd.conf'); } ## If specified, put user specified "xinetd.d" directory in /etc/xinetd.d.user if (exists($prefs{'xinetd_dir'})) { &do_log("WARNING: Directive \"xinetd_dir\" ignored, using strict defaults."); if ((-d "$prefs{'xinetd_dir'}") && !(-l "$prefs{'xinetd_dir'}")) { mkdir('/etc/xinetd.d.user', 0755); system("cp -Rdp $prefs{'xinetd_dir'}/* /etc/xinetd.d.user/ 1>/dev/null 2>/dev/null"); if ($prefs{'xinetd_dir'} =~ /^\/tmp\//) { system('rm', '-rf', "$prefs{'xinetd_dir'}"); } } delete($prefs{'xinetd_dir'}); } if (opendir(DIR, '/etc/default/xinetd.d.none')) { while (defined($filename = readdir(DIR))) { next if ($filename =~ /^\.\.?$/); if (!(-e "/etc/xinetd.d/${filename}")) { symlink("/etc/default/xinetd.d.none/${filename}", "/etc/xinetd.d/${filename}"); } } } else { &do_log("ERROR: Cannot open directory \"/etc/default/xinetd.d.none\""); } ## Use more restrictive sshd_config that only listens on localhost. if (-f '/etc/default/ssh/sshd_config.local') { symlink('/etc/default/ssh/sshd_config.local', '/etc/ssh/sshd_config'); } } ## End if (no shadow). else { ## Remove /etc/default/xinetd.d.none. Not needed now, and we don't want ## it wasting space. system('rm', '-rf', '/etc/default/xinetd.d.none'); } ## Clean up bare passwd/shadow/group files. foreach ('passwd', 'shadow', 'group') { if (-f "/etc/$_") { system('rm', '-f', "/etc/$_"); } } ## Copy important config files from $m_point to /etc/ ## At this time we're assuming $prefs{$_} contains full path, including ## mount point. foreach (@etc_vars) { if (exists($prefs{$_})) { if (!(-e "$prefs{$_}") || ($prefs{$_} eq '')) { delete($prefs{$_}); next; } &do_log("\'$_\' directive found."); ## Merge user's fstab with system default. ## This isn't perfect, but we do this because there are certain ## fstab entries that should exist by default. if ("$_" eq 'fstab') { my @usr_fstab = (); my @def_fstab = (); my ($tmpdev,$tmpmnt) = ''; my $entry = ''; if (-f "$prefs{$_}") { if (open(FH,"<$prefs{$_}")) { flock(FH,1); @usr_fstab = ; close(FH); } else { $status = "0"; } } else { print "Error: $prefs{$_}, file does not exist.\n"; $status = "0"; } ## Copy default fstab to /etc. if (-f "/etc/default/fstab") { system("cp -p /etc/default/fstab /etc/fstab 1>/dev/null 2>/dev/null"); } ## No need to go through all this if we cannot get user's fstab. if (!(-f "$prefs{$_}") || ($status eq "0")) { delete($prefs{'fstab'}); next; } ## Read contents to @def_fstab. if (-f "/etc/fstab") { if (open(FH,"; close(FH); } } foreach (@def_fstab) { chomp($_); $_ =~ s/#.*//; $_ =~ s/^[\s\t]+//; next if ($_ eq ''); $_ =~ s/[\s\t]+/ /g; $_ =~ s/^[\w\d\/\-\.]+\s[\w\d\/\-\.]+//; $_ = "$&"; } if (open(FH,">>/etc/fstab")) { flock(FH,2); ## Request Exclusive Lock print FH "\n"; foreach $entry (@usr_fstab) { chomp($entry); $entry =~ s/#.*//; $entry =~ s/^[\s\t]+//; $entry =~ s/[\s\t]+$//; next if ($entry eq ''); foreach (@def_fstab) { next if ($_ eq ''); ($tmpdev,$tmpmnt) = split(/\s/,$_,2); if (($entry =~ /^${tmpdev}[\s\t]/) || ($entry =~ /[\s\t]${tmpmnt}[\s\t]/) || ($entry =~ /[\s\t]\/usr[\s\t]/)) { $entry = ''; last; } } if ($entry ne '') { print FH "$entry\n"; } } ## End foreach close(FH); } else { &do_log("ERROR: Unable to open /etc/fstab while processing 'fstab' directive."); } } ## End If (fstab) ## Merge user's shadow/passwd/group file with system default. elsif (("$_" eq 'shadow') || ("$_" eq 'passwd') || ("$_" eq 'group')) { if (!(-f "$prefs{$_}")) { &do_log("ERROR: $prefs{$_} not found, /etc/$_ not replaced."); print "WARNING: /etc/$_ not replaced.\n"; symlink("/etc/default/$_", "/etc/$_"); delete($prefs{$_}); next; } ## Put /etc/default/{passwd,shadow,group} into @sysfile, process @sysfile. my(@sysfile,@usr_sysfile) = (); my($tmp,$tmp2,$compare) = ''; if (open(FH,"; close(FH); foreach $tmp (@sysfile) { chomp($tmp); $tmp =~ s/^[\s\t]+//; $tmp =~ s/[\s\t]+$//; } } else { &do_log("ERROR: Unable to open /etc/default/$_"); system("cp -p $prefs{$_} /etc/$_ 1>/dev/null 2>/dev/null"); (chmod 0600, "/etc/$_") if ($_ eq 'shadow'); if ($prefs{$_} =~ /^\/tmp\//) { system("rm -f $prefs{$_} 1>/dev/null 2>/dev/null"); } delete($prefs{$_}); next; } ## Put user's {passwd,shadow,group} into @usr_sysfile, process @usr_sysfile. if (open(FH,"<$prefs{$_}")) { flock(FH,1); @usr_sysfile = ; close(FH); foreach $tmp (@usr_sysfile) { chomp($tmp); $tmp =~ s/^[\s\t]+//; $tmp =~ s/[\s\t]+$//; } } else { &do_log("ERROR: Unable to open $prefs{$_}"); symlink("/etc/default/$_", "/etc/$_"); @sysfile = (); if ($prefs{$_} =~ /^\/tmp\//) { system("rm -f $prefs{$_} 1>/dev/null 2>/dev/null"); } delete($prefs{$_}); next; } ## Compare passwd/shadow/group entries with user's. Only the ## first part, the user or group name, is matched. In this case, ## unlike above with /etc/fstab, if there is a match the user's ## entry replaces the system default. foreach $tmp (@usr_sysfile) { $compare = "${tmp}"; $compare =~ s/\:.*//; next if ($compare eq ''); foreach $tmp2 (@sysfile) { if (${tmp2} =~ /^${compare}\:/) { ${tmp2} = ''; last; } } } if (open(FH,">/etc/${_}")) { flock(FH,2); foreach $tmp (@sysfile,@usr_sysfile) { next if ($tmp eq ''); print FH "${tmp}\n"; } close(FH); (chmod 0600, "/etc/$_") if ($_ eq 'shadow'); } else { system("cp -p $prefs{$_} /etc/$_ 1>/dev/null 2>/dev/null"); (chmod 0600, "/etc/$_") if ($_ eq 'shadow'); } (@sysfile,@usr_sysfile) = (); } ## End elsif (passwd,shadow,group). ## Deal with the 'hostname' directive. ## Unlike the Slackware version, the system's hostname is kept in ## /etc/sysconfig/network on a RedHat box. So if the hostname is ## placed in that file, it will override what is done here. ## If $prefs{'hostname'} points to a regular file, it will be copied ## to /etc/HOSTNAME, otherwise it is assumed to be an actual hostname, ## and will be placed in /etc/HOSTNAME. elsif ("$_" eq 'hostname') { if (!(-f "$prefs{$_}")) { if (open(FH,">/etc/HOSTNAME")) { flock(FH,2); print FH "$prefs{$_}"; close(FH); } else { system("rm -f /etc/HOSTNAME 1>/dev/null 2>/dev/null") if (-f "/etc/HOSTNAME"); } } else { system("cp -p $prefs{$_} /etc/HOSTNAME 1>/dev/null 2>/dev/null"); } } ## Take care of sysconf_dir and xinetd_dir directives. These differ from the ## norm in that they are directories instead of plain files. elsif ("$_" eq 'xinetd_dir') { if (-d "$prefs{xinetd_dir}") { system("cp -Rdp $prefs{xinetd_dir}/* /etc/xinetd.d/ 1>/dev/null 2>/dev/null"); } } elsif ("$_" eq 'sysconf_dir') { if (-d "$prefs{sysconf_dir}") { system("cp -Rdp $prefs{sysconf_dir}/* /etc/sysconfig/ 1>/dev/null 2>/dev/null"); } } ## Reread inittab if declared in config. elsif ("$_" eq 'inittab') { system("cp -p $prefs{$_} /etc/inittab 1>/dev/null 2>/dev/null"); system("/sbin/telinit q 1>/dev/null 2>/dev/null"); &do_log("INFO: \`inittab\' replaced, running \`telinit q\' to reread inittab."); } ## Finally, just copy the files that don't need any special treatment. else { if (exists($specdir{$_}) && (-d "$specdir{$_}")) { ## Copy file to proper directory as specified in $specdir{$_} variable system("cp -p $prefs{$_} $specdir{$_}/${_} 1>/dev/null 2>/dev/null"); } else { if ($_ =~ /^rc\./) { system("cp -p $prefs{$_} /etc/rc.d/$_ 1>/dev/null 2>/dev/null"); } else { system("cp -p $prefs{$_} /etc/$_ 1>/dev/null 2>/dev/null"); if ($prefs{$_} eq 'named.conf') { ## For chrooted named. system("cp -p $prefs{$_} /var/chroot/etc/$_ 1>/dev/null 2>/dev/null"); } } } } ## Clean up tmp stuff(used when retrieving files via ftp/http). if ($prefs{$_} =~ /^\/tmp\//) { system('rm', '-rf', "$prefs{$_}"); } delete($prefs{$_}); ## Remove hash entry, done with it. } ## End if ## File not declared in config, just pull it from /etc/default. else { if ($_ =~ /^rc\./) { if ((-f "/etc/default/rc.d/${_}") && (!(-f "/etc/rc.d/${_}"))) { symlink("/etc/default/rc.d/${_}", "/etc/rc.d/${_}"); } } elsif ((-f "/etc/default/${_}") && (!(-f "/etc/${_}"))) { symlink("/etc/default/${_}", "/etc/${_}"); } } } ## End foreach loop foreach (@ssh_vars) { if (exists($prefs{$_})) { if (($prefs{$_} eq '') || !(-f "$prefs{$_}")) { delete($prefs{$_}); next; } &do_log("\'$_\' directive found."); system("cp -p $prefs{$_} /etc/ssh/$_ 1>/dev/null 2>/dev/null"); if (($prefs{$_} =~ /^ssh_host_rsa_key$/) || ($prefs{$_} =~ /^ssh_host_dsa_key$/) || ($prefs{$_} =~ /^ssh_host_key$/)) { chmod 0400, "/etc/ssh/$_"; } ## Clean up tmp stuff. if (($prefs{$_} =~ /^\/tmp\//) && (-f "$prefs{$_}")) { system("rm -f $prefs{$_} 1>/dev/null 2>/dev/null"); } delete($prefs{$_}); ## Remove hash entry. } } ## Iterate through hash, take care of cron: directive, ## services: directive, and the ## (nonexisting_filename = file_location) copy directive. foreach (keys %prefs) { next if ($_ eq ''); next if ("$_" =~ /^device\d$/); next if ("$_" =~ /^(http|ftp)_proxy$/); next if ("$_" =~ /^proxy\-(user|passwd)$/); ## Check to see if $prefs{"$_"} is a valid file. # if (($_ ne 'sysconf_dir') && ($_ ne 'xinetd_dir')) { # if (!(-f "$prefs{$_}")) { # if (-f "${m_point}/$prefs{$_}") { # $prefs{$_} =~ s/^\/+//; # &do_log("WARNING: Using \"${m_point}/$prefs{$_}\" instead of \"$prefs{$_}\""); # $prefs{"$_"} = "${m_point}/$prefs{$_}"; # $prefs{"$_"} =~ s/\/{2,}/\//g; # } # else { # &do_log("ERROR: $prefs{$_} does not exist."); # delete($prefs{"$_"}); # next; # } # } # } ## Make symlinks to start/stop services, files located in /etc/rc.d/init.d. ## Most of these files will never need to be replaced, but we give the user ## the option to do so anyhow. if (($_ =~ /\:/) && ($_ !~ /^cron(tab)?\:/)) { my($tmpservice,$onoff) = ''; ($tmpservice,$onoff) = split(/\:/, $_, 2); next if !(exists($services{$tmpservice})); $onoff = lc($onoff); ## Copy init.d file to /etc/rc.d/init.d/ if (-f "$prefs{$_}") { system("cp -p $prefs{$_} /etc/rc.d/init.d/${tmpservice} 1>/dev/null 2>/dev/null"); if (!(-x "/etc/rc.d/init.d/${tmpservice}")) { chmod 0755, "/etc/rc.d/init.d/${tmpservice}"; } } else { symlink("/etc/default/rc.d/init.d/${tmpservice}", "/etc/rc.d/init.d/${tmpservice}"); } if (($onoff eq 'start') || ($onoff eq 'on')) { ## Redefine the default(will be symlinked later). $services{$tmpservice}->{'default'} = 'start'; delete($prefs{$_}); next; } elsif (($onoff eq 'stop') || ($onoff eq 'off')) { ## Redefine the default(will be symlinked later). $services{$tmpservice}->{'default'} = 'stop'; delete($prefs{$_}); next; } else { delete($prefs{$_}); next; } } ## End if(services) ## Crontab directive. Perhaps a bit messy right now. if ($_ =~ /^cron(tab)?\:/) { if (!(-f "$prefs{$_}")) { &do_log("ERROR: $_, crontab file does not exist."); delete($prefs{$_}); next; } $uname = "$_"; $uname =~ s/^cron(tab)?\://; $uid = (defined(getpwnam($uname))) ? getpwnam($uname) : "-1"; $gid = (defined(getgrnam($uname))) ? getgrnam($uname) : "0"; if ($uid >= 0) { system("cp -p $prefs{$_} /var/spool/cron/${uname} 1>/dev/null 2>/dev/null"); chown(0, $gid, "/var/spool/cron/${uname}"); chmod 0600, "/var/spool/cron/${uname}"; } else { &do_log("ERROR: Syntax error in crontab directive: $_"); } } else { if ("$prefs{$_}" ne "$_") { system('cp', '-p', "$prefs{$_}", "$_"); } } delete($prefs{$_}); } ## End foreach(keys %prefs) foreach (keys %services) { ## Now we must iterate through %services and make sure there are ## associated symlinks in /etc/rc.d/rc3.d/ for each entry. $rclink = "$services{$_}->{$services{$_}->{'default'}}" . "$_"; if ($_ eq 'local') { if (!(-l "/etc/rc.d/rc3.d/${rclink}")) { symlink("/etc/rc.d/rc.local", "/etc/rc.d/rc3.d/${rclink}"); } } elsif (!(-l "/etc/rc.d/rc3.d/${rclink}")) { symlink("/etc/rc.d/init.d/${_}", "/etc/rc.d/rc3.d/${rclink}"); } ## *Note: /etc/rc.d/init.d/${_} may not yet exist at this point. ## If it doesn't it will be symlinked to /etc/default/rc.d/init.d/${_} ## below. } ## Take down networking stuff. if ($net ne "0") { &networking('NET_DOWN'); } ## That's it for the config. ## Make rest of the symlinks from /etc to /etc/default. print "Completing configuration, using: /etc/default\n"; @dirs = ('/etc/default'); ## Call recurse_dirs(), recurses through /etc/default and fills @dirs with directory ## names. Kind of an expensive operation, but useful when we start making symlinks ## from /etc/{dir} to /etc/default/{dir}. &recurse_dirs('/etc', 'default'); foreach (@dirs) { next if ($_ eq ''); next if !(-d "$_"); ## Note: $_ should always be a valid directory. if (opendir(DIR, "$_")) { ## Get rid of '/etc/default/' in directory name. if ($_ ne '/etc/default') { $_ =~ s/^\/etc\/default\///; } ## Obviously, if the directory exists in /etc/default/$_ but not ## in /etc/$_, then we shouldn't try to make symlinks from ## /etc/$_/ to /etc/default/$_/. next if (($_ ne '/etc/default') && !(-d "/etc/${_}")); while (defined($filename = readdir(DIR))) { next if $filename =~ /^\.\.?$/; if ($_ ne '/etc/default') { next if (-d "/etc/${_}/${filename}"); } else { next if (-d "/etc/${filename}"); } ## Files we don't want symlinks to. next if ($filename eq 'sentry.conf'); next if ($filename eq 'sshd_config.local'); ## Finally, make the symlinks... if ($_ eq '/etc/default') { if (!(-e "/etc/${filename}") && !(-l "/etc/${filename}")) { symlink("/etc/default/${filename}", "/etc/${filename}"); } } elsif (!(-e "/etc/${_}/${filename}") && !(-l "/etc/${_}/${filename}")) { symlink("/etc/default/${_}/${filename}", "/etc/${_}/${filename}"); } } closedir(DIR); } else { &do_log("ERROR: Unable to open directory \"$_\"."); } } ## End foreach loop. } ## End sub do_config() ##-------------------------------------------------------------------------## ##-------------------------------------------------------------------------## ## Sub recurse_dirs() sub recurse_dirs { my($path) = $_[0]; my($dir) = $_[1]; my($filename) = ''; my($filehandle) = rand(500); if (opendir($filehandle, "${path}/${dir}")) { while (defined($filename = readdir($filehandle))) { next if $filename =~ /^\.\.?$/; next if ((-l "${path}/${dir}/$filename") || !(-d "${path}/${dir}/$filename")); push(@dirs, "${path}/${dir}/${filename}"); &recurse_dirs("${path}/${dir}", "${filename}"); } closedir($filehandle); } } ## End sub recurse_dirs() ##-------------------------------------------------------------------------## ## _EOF_ ##