blob: af148b6eca2ba56313eb1c4748fba7fd250cffef [file] [log] [blame]
#!/usr/bin/perl -w
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################
# $Id: vclclientd 1954 2008-12-12 14:46:02Z arkurth $
##############################################################################
=head1 NAME
vclclientd
=head1 SYNOPSIS
perl vclclientd
=head1 DESCRIPTION
This is the executable module for running the VCL client daemon on Linux lab
machines.
=cut
##############################################################################
use strict;
use Getopt::Long;
use diagnostics;
use Symbol;
use POSIX;
$|=1; # turning off autoflush
# -- DEVELOPMENT testing
#my $PIDFILE = "/var/run/vcldev.pid";
#our $LOG = "/var/log/vcldev.log";
# GLOBALS
our $HOME = "/home/vclstaff";
our $VCLFLAG = "$HOME/flag";
our $CLIENTDATA = "$HOME/clientdata";
our $PIDFILE ="/var/run/vclclientd.pid";
our %children = (); # keys are current child process IDs
our $children = 0; # current number of children
our $LOG = "/var/log/vclclientd.log";
our %ERRORS=('DEPENDENT'=>4,'UNKNOWN'=>3,'OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'MAILMASTERS'=>5);
our $opt_d='';
Getopt::Long::Configure('bundling', 'no_ignore_case');
GetOptions('d|debug' => \$opt_d );
if(!$opt_d){
#daemonize
&daemonize;
}
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";
defined(my $pid = fork) or die "Can't fork $!";
exit if $pid;
#production
$0 = "vclclientd";
print "Created process $$ renamed to $0 ...\n";
setsid or die "Can't start a new session: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null $!";
open STDOUT, '>>$LOG' or die "Can't write $LOG $!";
open STDERR, '>>$LOG' or die "Can't write $LOG $!";
umask 0;
open(PIDFILE, ">$PIDFILE"); # so I can kill myself easily
print PIDFILE $$;
close(PIDFILE);
}
#------- Subroutine declarations -------
sub main(); # main calls primary subroutines
sub flag;
sub processdata;
sub startsshd;
sub makedatestring;
sub reboot;
sub fetch;
sub store;
sub sshdstatus;
sub createnewssh_config_vcl;
sub restartsshd;
sub REAPER { # takes care of dead children
$SIG{CHLD} = \&REAPER;
my $pid = wait;
if(exists $children{$pid}){
$children--;
notify($ERRORS{'OK'},"$pid -- child process exiting, deleting $pid ");
delete $children{$pid};
}
else{
notify($ERRORS{'OK'},"$pid -- sub process exiting");
}
}
sub HUNTSMAN { # signal handler for SIGINT
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our child processes
kill 'INT' => keys %children;
notify($ERRORS{'OK'},"$$ -- process exiting");
exit; # clean up with dignity
}
# Install signal handlers.
$SIG{CHLD} = \&REAPER;
$SIG{INT} = \&HUNTSMAN;
$SIG{QUIT} = \&HUNTSMAN;
$SIG{HUP} = \&HUNTSMAN;
$SIG{TERM} = \&HUNTSMAN;
main();
sub main () {
#preplogfile;
#my @hostinfo = hostname;
#make sure vclstaff owns authorized_keys and log file
if(open(AUTHFILE,"chown vclstaff:root /home/vclstaff/authorized_keys 2>&1 |")){
notify($ERRORS{'OK'},"main: setting vclstaff ownership of /home/vclstaff/authorized_keys");
close(AUTHFILE);
}
if(open(LOGFILE,"chown vclstaff:root /var/log/vclclientd.log 2>&1 |")){
notify($ERRORS{'OK'},"main: setting vclstaff ownership of /var/log/vclclientd.log");
close(LOGFILE);
}
if(!(-r "/etc/users.local.admin")){
notify($ERRORS{'OK'},"main: /etc/users.local.admin does not exist creating");
if(open(COPY, "/bin/cp /etc/users.local /etc/users.local.admin |")){
close(COPY);
if(-r "/etc/users.local.admin"){
notify($ERRORS{'OK'},"main: /etc/users.local.admin exist now");
}
}
}
#on startup check to see if someone has rebooted us. this is a hack
#we just need to figure out if this a reboot or a restart
#for now we are just going to look at the output of last -- there has
#to be a better way
if(open(LAST,"/usr/bin/last 2>&1 |")){
my @last =<LAST>;
close(LAST);
if($last[0] =~ /reboot/ || $last[1] =~ /reboot/){
if( -r "$CLIENTDATA"){
if(open(CLD, "$CLIENTDATA")){
my @file = <CLD>;
close(CLD);
if($file[0] =~ /new/){
if(open(FLAG, ">$VCLFLAG")){
print FLAG 1;
close(FLAG);
notify($ERRORS{'OK'},"main: possibly a reboot setting flag to 1 for reinitializing");
}#flag
}#new
}#CLD
else{
notify($ERRORS{'OK'},"main: could not open $CLIENTDATA");
}
}# readable
}# last -- reboot
}
while(1){
if( flag ){
notify($ERRORS{'OK'},"main: flag is set proceed to process");
#make sure clientdata is readable
if(-r $CLIENTDATA){
#process data
if(open(CLIENTDATA,"$CLIENTDATA")){
my %request=();
my @lines = <CLIENTDATA>;
close(CLIENTDATA);
$request{"state"}=$lines[0];
$request{"unityid"}=$lines[1];
$request{"remoteIP"}=$lines[2];
chomp($request{"state"});
chomp($request{"unityid"});
chomp($request{"remoteIP"});
make_new_child(%request) if($request{"state"} =~ /new|timeout|delete/);
reboot() if($request{"state"} =~ /reboot/);
fetch() if($request{"state"} =~ /fetch/);
store() if($request{"state"} =~ /store/);
}
else{
notify($ERRORS{'OK'},"main: could not open $CLIENTDATA: $!");
}
} #if -r
} #if flag
else{
#check for any hung children
#kill fork process and reset flag? does this create a race condition
#could keep track of killed processes in children hash when number exceeds X (reboot machine?)
#notify($ERRORS{'OK'},"main: number of children $children");
foreach my $p (keys %children) {
next if($p=~ /hung/);
notify($ERRORS{'OK'},"main: pid = $p");
$children{"hungtries"}{"count"}+=1;
if(open(KILL,"kill -9 $p 2>&1 |")){
notify($ERRORS{'OK'},"main: stopping forked process in an attempt to reset");
my $k = <KILL>;
close(KILL);
if($k =~ /No such process/){
#not found maybe I was too guick to judge
#let it ride
}
else{
if($children{"hungtries"}{"count"} > 4){
notify($ERRORS{'OK'},"main: hung process attempts are greater than 4 rebooting");
reboot();
}
if(open(ECHO,"echo 1 > /home/vclstaff/flag |")){
notify($ERRORS{'OK'},"main: attempt to reset initiated");
close(ECHO);
}
}
}
}
}
sleep 5;
} #while
}
sub flag {
if(!(-e $VCLFLAG)){
# warning flag does not exist
#create it and continue
if(open(FLAG, ">$VCLFLAG")){
print FLAG 0;
notify($ERRORS{'OK'}, "had to create $VCLFLAG");
close(FLAG);
if(open(LOGFILE,"chown vclstaff:root /home/vclstaff/flag 2>&1 |")){
notify($ERRORS{'OK'},"main: setting vclstaff ownership of /home/vclstaff/flag");
close(LOGFILE);
}
if(open(LOGFILE,"chmod 640 /home/vclstaff/flag 2>&1 |")){
notify($ERRORS{'OK'},"main: setting 640 perms /home/vclstaff/flag");
close(LOGFILE);
}
}
else{
notify($ERRORS{'OK'},"could not create $VCLFLAG $! will try to delete");
unlink $VCLFLAG;
return 0;
}
}
my @lines;
# VCLFLAG file exists, check contents
if(open(FLAG, "$VCLFLAG")){
@lines = <FLAG>;
close(FLAG);
# clear flag
if(open(FLAG, ">$VCLFLAG")){
print FLAG 0;
close(FLAG);
}
else{
unlink $VCLFLAG;
}
return $lines[0];
}
else{
notify($ERRORS{'OK'},"flag: could not open $VCLFLAG $!");
return 0;
}
}
sub make_new_child {
my (%request_data) = @_;
my $pid;
my $sigset;
# block signal for fork
$sigset = POSIX::SigSet->new(SIGINT);
sigprocmask(SIG_BLOCK, $sigset) or die "Can't block SIGINT for fork: $!\n";
#die "fork: $!" unless defined ($pid = fork);
FORK: {
if ($pid = fork) {
# Parent records the child's birth
# and returns.
sigprocmask(SIG_UNBLOCK, $sigset) or die "Can't unblock SIGINT for fork: $!\n";
$children{$pid} = 1;
$children++;
notify($ERRORS{'OK'},"vclclientd current number of forked kids: $children");
return;
} elsif(defined $pid) {
# Child can *not* return from this subroutine.
$SIG{INT} = 'DEFAULT';
# make SIGINT kill us as it did before unblock signals
sigprocmask(SIG_UNBLOCK, $sigset) or die "Can't unblock SIGINT for fork: $!\n";
notify($ERRORS{'OK'},"processdata: new request child process $request_data{state} $request_data{unityid},$request_data{remoteIP} ");
#do something that may take a long time or needs to be monitored
#based on the case lets do something
if($request_data{state} =~ /new/){
notify($ERRORS{'OK'},"processdata: new request $request_data{unityid},$request_data{remoteIP} ");
if(new_state($request_data{unityid},$request_data{remoteIP})){
notify($ERRORS{'OK'},"processdata: connection for $request_data{unityid}\@$request_data{remoteIP} successfully opened");
}
}
elsif($request_data{"state"} =~ /timeout|deleted/){
if(timeout_state($request_data{unityid},$request_data{remoteIP})){
notify($ERRORS{'OK'},"vclclientd: connection for $request_data{unityid}\@$request_data{remoteIP} successfully terminated");
}
}
exit;
} elsif ($! =~ /No more process/){
sleep 5;
redo FORK;
}
else {
# strange error
die "Can't fork: $!\n";
}
}
}
sub new_state {
my ($user,$remoteIP) =@_;
# assumuption user and IP are valid
# add user to users.local, sshd_config_vcl
# on acknowledgemment turn on sshd on port 22
my @file;
my $line;
my ($userset,$remoteIPset) = 0;
#test for sshd_config_vcl
if(!(-r "$HOME/sshd_config_vcl")){
#hrmm. were did sshd_config_vcl go
#let try to create another from the orignal
if(createnewssh_config_vcl){
notify($ERRORS{'OK'},"new_state: sshd_config_vcl missing created a new one");
}
else{
notify($ERRORS{'OK'},"new_state: sshd_config_vcl missing failed to create a new one");
return 0;
}
}
if(open(CONFIG,"$HOME/sshd_config_vcl")){
@file = <CONFIG>;
close(CONFIG);
foreach $line (@file){
if($line =~ /AllowUsers/){
$line = "AllowUsers $user\n";
$userset=1;
notify($ERRORS{'OK'},"new_state: adding AllowUsers $user to sshd_config_vcl");
}
}
if(!$userset){
push @file, "AllowUsers $user\n";
notify($ERRORS{'OK'},"new_state: hrmm, had to add AllowUsers $user to sshd_config_vcl");
}
if(open(CONFIG,">$HOME/sshd_config_vcl")){
print CONFIG @file;
close(CONFIG);
}
}
# append to users.local
if(open(USERSLOCAL,"/etc/users.local")){
my @users = <USERSLOCAL>;
close(USERSLOCAL);
push @users,"\n$user\n";
if(open(USERSLOCAL,">/etc/users.local")){
print USERSLOCAL @users;
notify($ERRORS{'OK'},"new_state: adding $user to users.local");
close(USERSLOCAL);
}
}
else{
notify($ERRORS{'WARNING'},"new_state: could not open /etc/users.local $!");
return 0;
}
#start sshd
if(startsshd){
notify($ERRORS{'OK'},"new_state: startsshd returned and successful");
return 1;
}
return 0;
}
sub timeout_state{
# time to close non-admin ssh sessions and clean up users.local,
# sshd_config_vcl
my ($user,$remoteIP) =@_;
my $os = lc($^O);
#notify($ERRORS{'OK'},"timeout_state: OSname is $os");
my @file;
my $l;
my $sshd_admin_pid =0;
my ($pgrep,$pkill);
# get admin pid
if($os eq "solaris"){
$pgrep="/bin/pgrep";
$pkill="/bin/pkill";
if(open(SSH,"/local/openssh/etc/sshd.admin.pid")){
@file = <SSH>;
close(SSH);
$sshd_admin_pid=$file[0];
notify($ERRORS{'OK'},"timeout_state: sshd_admin_pid set $sshd_admin_pid");
}
else{
notify($ERRORS{'OK'},"timeout_state: could not open /local/openssh/etc/sshd.admin.pid $!");
}
}
elsif($os eq "linux"){
$pgrep="/usr/bin/pgrep";
$pkill="/usr/bin/pkill";
if(open(SSH,"ps -ef \| grep /usr/sbin/sshd |")){
@file = <SSH>;
close(SSH);
$sshd_admin_pid=$file[0];
foreach $l (@file){
chomp ($l);
next if($l =~ /grep/);
if($l =~ /(\/usr\/sbin\/sshd$)/){
my $blah;
($blah,$sshd_admin_pid,$blah) = split(/\s+/,$l,3);
notify($ERRORS{'OK'},"timeout_state: sshd_admin_pid set $sshd_admin_pid");
}
}
}
else{
notify($ERRORS{'OK'},"timeout_state: execute ps -ef $!");
}
}
else{
notify($ERRORS{'OK'},"timeout_state: $os not supported");
# we'll just let this ride and get a restart
}
# clean up users.local
# collect members of users.admin,users.base, and users.cluster
my @users_admin;
my @users_base;
my @users_cluster;
my $u;
#this one should exist
if(open(USERSLOCAL,"cat /etc/users.local.admin > /etc/users.local |")){
close(USERSLOCAL);
notify($ERRORS{'OK'},"timeout_state: dumped contents of /etc/users.local.admin /etc/users.local");
}
if(-r "/etc/users.local.base"){
if(open(USERSLOCAL,"cat /etc/users.local.base >> /etc/users.local |")){
close(USERSLOCAL);
notify($ERRORS{'OK'},"timeout_state: dumped contents of /etc/users.local.base /etc/users.local");
}
}
if(-r "/etc/users.local.cluster"){
if(open(USERSLOCAL,"cat /etc/users.local.cluster >> /etc/users.local |")){
close(USERSLOCAL);
notify($ERRORS{'OK'},"timeout_state: dumped contents of /etc/users.local.cluster /etc/users.local");
}
}
if(open(USERSLOCAL,"/etc/users.local")){
@users_admin=<USERSLOCAL>;
close(USERSLOCAL);
}
# check users.local add vclstaff if is does not exist
my $vclstaff=0;
my $i;
for $i (@users_admin){
$vclstaff =1 if($i =~ "vclstaff");
}
if(!$vclstaff){
push @users_admin, "\nvclstaff\n";
if(open(USERSLOCAL,"> /etc/users.local")){
print USERSLOCAL @users_admin;
close(USERSLOCAL);
}
}
# clean up our sshd_config_vcl
my @SSH;
my $s;
if(open(SSHDCONFIG, "$HOME/sshd_config_vcl")){
@SSH = <SSHDCONFIG>;
close(SSHDCONFIG);
foreach $s (@SSH){
if($s =~ s/AllowUsers $user/AllowUsers/g){
notify($ERRORS{'OK'},"timeout_state: $user\@$remoteIP removed from sshd_config_vcl");
}
}
# write back out to sshd_config_vcl
if(open(SSHDCONFIG, ">$HOME/sshd_config_vcl")){
print SSHDCONFIG @SSH;
close (SSHDCONFIG);
}
else{
notify($ERRORS{'OK'},"timeout_state: could not open $HOME/sshd_config_vcl for writing");
}
}
#kill off any user processes
if(open(PKILL, "$pkill -9 -U $user 2>&1 |")){
my @pkill=<PKILL>;
close(PKILL);
notify($ERRORS{'OK'},"timeout_state: stopped user processes");
#check for user
notify($ERRORS{'OK'},"timeout_state: confirming user processes are stopped");
if(open(PGREP, "ps -ef \| grep $user|")){
my @pgrep=<PGREP>;
close(PGREP);
foreach my $pid (@pgrep){
next if($pid =~ /grep/);
my($userblah,$userpid) = split(/\s+/,$pid,3);
if($userpid){
if(open(KILL, "kill -9 $userpid |")){
notify($ERRORS{'OK'},"timeout_state: killed user process $userpid");
close(KILL);
}
}
}
}
}
notify($ERRORS{'OK'},"timeout_state: checking for all sshd processes");
# use pgrep to get all sshd pids
if(open(PGREP,"ps -ef \|grep sshd 2>&1|")){
my @pfile = <PGREP>;
close(PGREP);
foreach $l (@pfile){
next if($l =~ /grep/);
next if($l =~ /ps -ef/);
notify($ERRORS{'OK'},"timeout_state: pgrep sshd = $l");
my ($b,$sshpid);
($b,$b,$sshpid,$b) = split(/\s+/,$l,4) if($os eq "solaris");
($b,$sshpid) = split(/\s+/,$l,3) if($os eq "linux");
next if($sshpid == $sshd_admin_pid);
if(open(KILL, "kill -9 $sshpid |")){
notify($ERRORS{'OK'},"timeout_state: killed sshd process $sshpid");
close(KILL);
}
}
notify($ERRORS{'OK'},"timeout_state: checking if I accidentially killed all sshd processes");
# did we kill all sshd sessions?
if(open(PGREP,"ps -ef \|grep sshd \|grep -v grep |")){
notify($ERRORS{'OK'},"timeout_state: executed ps -ef \|grep sshd \|grep -v grep");
@file = <PGREP>;
notify($ERRORS{'OK'},"timeout_state: @file");
close(PGREP);
if(!($file[0])){
notify($ERRORS{'OK'},"timeout_state: killed all sshd processes, will try to restart");
if(open(SSHD,"/etc/inet.d/sshd start |")){
@file = <SSHD>;
close(SSHD);
notify($ERRORS{'OK'},"timeout_state: sshd admin restarted @file");
}
}
}
}
else{
notify($ERRORS{'WARNING'},"timeout_state: could not execute /usr/bin/pgrep sshd");
}
notify($ERRORS{'OK'},"timeout_state: looking for sshd_config_vcl");
#look for sshd_config_vcl in case we killed the sshd_admin pid
if(open(SSH,"ps -ef \| grep /usr/sbin/sshd |")){
my @sshfile = <SSH>;
close(SSH);
foreach $l (@sshfile) {
if($l =~ /(\/home\/vclstaff\/sshd_config_vcl\/)/){
# for some reason sshd with the vcl config file did not get stopped
#initiate a restart/reload
notify($ERRORS{'OK'},"timeout_state: sshd_config_vcl not stopped for some reason, prhaps the wrong sshd pid");
my ($b,$sshpid) = split(/\s+/,$l,3);
if($sshpid == $sshd_admin_pid){
notify($ERRORS{'OK'},"timeout_state: killed the wrong sshd pid");
#kill this pid
if(open(KILL, "kill -9 $sshpid |")){
notify($ERRORS{'OK'},"timeout_state: killed sshd process $l");
close(KILL);
}
#stop and start sshd service.
if(open(SSHSTOP,"/etc/inet.d/sshd stop |")){
@file = <SSHSTOP>;
close(SSHSTOP);
notify($ERRORS{'OK'},"timeout_state: sshd admin stopped @file");
if(open(SSHSTART, "/etc/inet.d/sshd start |")){
@file=<SSHSTART>;
close(SSHSTART);
notify($ERRORS{'OK'},"timeout_state: sshd admin started @file");
}
}
}
}
}
}
if(sshdstatus){
notify($ERRORS{'OK'},"timeout_state: sshd core process is running");
}
else{
notify($ERRORS{'CRITICAL'},"timeout_state: sshd is not running or could not be restarted");
}
return 1;
}
sub reboot {
#simply reboot the client when called
my $os = lc($^O);
my $reboot;
if($os eq "solaris"){
$reboot = "/usr/sbin/shutdown -y -g 0 -i 6";
}
else{
$reboot = "/sbin/shutdown -r now";
}
notify($ERRORS{'OK'},"reboot: starting reboot sequence");
if(open(REBOOT,"$reboot 2>&1 |")){
my @reboot=<REBOOT>;
close(REBOOT);
notify($ERRORS{'OK'},"reboot: @reboot");
return 1;
}
}
sub fetch {
#collect host ssh keys and save for MN to pick up
notify($ERRORS{'OK'},"fetch: copying ssh keys to $HOME");
my $os = lc($^O);
my $sshdir;
if($os eq "solaris"){
$sshdir = "/local/openssh/etc";
}
else{
$sshdir = "/etc/ssh/";
}
if(open(CP, "/bin/cp $sshdir/ssh_host\* $HOME 2>&1 |")){
my @cp=<CP>;
close(CP);
if(@cp){
notify($ERRORS{'OK'},"fetch: copy problems - @cp");
}
if(open(CHOWN,"/bin/chown vclstaff $HOME/ssh_host\* 2>&1 |")){
my @chown=<CHOWN>;
close(CHOWN);
if(@chown){
notify($ERRORS{'OK'},"fetch: chown problems - @cp");
}
}
}
notify($ERRORS{'OK'},"fetch: fetch complete");
return 1;
}
sub store {
# take host ssh keys stored in my home directory and place them into the /etc/sshd directory
#create an orig directory in $sshdir
#copy original keys to orig dir
#cp given keys to proper location
#set correct ownership and premissions on keys
#unlink/remove locally stored keys from vclstaff dir
my $os = lc($^O);
my $sshdir;
if($os eq "solaris"){
$sshdir = "/local/openssh/etc";
}
else{
$sshdir = "/etc/ssh";
}
notify($ERRORS{'OK'},"store: copying ssh keys to $sshdir");
my %filelist;
$filelist{"dsa"}="ssh_host_dsa_key";
$filelist{"dsapub"}="ssh_host_dsa_key.pub";
$filelist{"rsa"}="ssh_host_rsa_key";
$filelist{"rsapub"}="ssh_host_rsa_key.pub";
$filelist{"key"}="ssh_host_key";
$filelist{"keypub"}="ssh_host_key.pub";
if(!(-d "$sshdir/origkeys")){
if(mkdir("$sshdir/origkeys", 755)){
notify($ERRORS{'OK'},"store: mkdir successfully created $sshdir/origkeys");
}
else{
notify($ERRORS{'OK'},"store: mkdir $sshdir/origkeys $! ");
}
}
else{
#hrmm $sshdir/origkeys already exists
}
#copy system generated keys to orig dir
#copy stored keys to ssh dir
#set perms,ownership,unlink local copy
foreach my $f(sort keys %filelist) {
if(!(-f "$HOME/$filelist{$f}")){
notify($ERRORS{'OK'},"store: does not exist $HOME/$filelist{$f}");
next;
}
if(open(CP,"/bin/cp $sshdir/$filelist{$f} $sshdir/origkeys 2>&1 |")){
my @cp=<CP>;
close(CP);
if(@cp){
notify($ERRORS{'OK'},"store: copy orig keys problem on $filelist{$f} - @cp");
}
}
#copy given keys to ssh dir
if(open(CP,"/bin/cp $HOME/$filelist{$f} $sshdir/$filelist{$f} 2>&1 |")){
my @cp=<CP>;
close(CP);
if(@cp){
notify($ERRORS{'OK'},"store: copy given keys problem on $filelist{$f} - @cp");
}
else{
notify($ERRORS{'OK'},"store: copied $filelist{$f} to $sshdir");
if(open(CHOWN, "/bin/chown root:root $sshdir/$filelist{$f} 2>&1 |")){
close(CHOWN);
}
my $p;
if($f =~ /pub/){
$p = 644;
}
else{
$p = 600;
}
if(open(CHMOD, "/bin/chmod $p $sshdir/$filelist{$f} 2>&1|")){
my @chmod=<CHMOD>;
close(CHMOD);
if(@chmod){
notify($ERRORS{'OK'},"store: chmod problem on $filelist{$f} - @chmod");
}
}#chmod
}#else no cp problems
}#CP
#unlink
if(unlink "$HOME/$filelist{$f}"){
notify($ERRORS{'OK'},"store: deleted $HOME/$filelist{$f}");
}
else{
notify($ERRORS{'OK'},"store: unable to delete $HOME/$filelist{$f}");
}
}#foreach
#restart sshd
if(restartsshd){
notify($ERRORS{'OK'},"store: sshd restarted");
return 1;
}
else{
notify($ERRORS{'OK'},"store: sshd restart failed");
return 0;
}
return 1;
}
sub restartsshd {
my $os = lc($^O);
notify($ERRORS{'OK'},"restartsshd: attempting to restart sshd on $os");
if($os eq "solaris"){
if(open(STOP,"/bin/pkill -f sshd_admin.cfg 2>&1 |")){
my @stop=<STOP>;
close(STOP);
foreach my $r (@stop) {
if($r =~ /failed/i){
notify($ERRORS{'WARNING'},"restartsshd: sshd stop failed @stop");
}
}
if(open(START,"/etc/init.d/sshd start 2>&1 |")){
my @start=<START>;
close(START);
foreach my $r (@start) {
#notify($ERRORS{'OK'},"restartsshd: output $r");
if($r =~ /failed/i){
notify($ERRORS{'WARNING'},"restartsshd: sshd start failed @start");
}
return 1 if($r =~ /ok/i);
}
}#if start
} # pkill
}
elsif($os =~ /linux/){
if(open(RESTART,"/etc/init.d/sshd restart 2>&1 |")){
my @restart=<RESTART>;
close(RESTART);
foreach my $r (@restart) {
if($r =~ /failed/i){
notify($ERRORS{'WARNING'},"restartsshd: sshd restart failed $r @restart");
}
if($r =~ /Starting/){
return 1 if($r =~ /ok/i);
}
}
}
}
return 1;
}
sub startsshd {
my @lines;
#figure out OS solaris or linux
my $os= lc($^O);
my @output;
my $l;
if($os eq "solaris"){
if(open(SSHD,"/local/openssh/sbin/sshd -f $HOME/sshd_config_vcl 2>&1 |")){
notify($ERRORS{'OK'},"startsshd: starting sshd");
@output = <SSHD>;
close(SSHD);
foreach $l (@output){
notify($ERRORS{'OK'},"startsshd output: $l");
}
return 1;
}
else{
notify($ERRORS{'OK'},"startsshd: could not execute /local/openssh/sbin/sshd -f $HOME/sshd_config_vcl $!");
return 0;
}
}
elsif($os eq "linux"){
if(open(SSHD, "/usr/sbin/sshd -f $HOME/sshd_config_vcl |")){
notify($ERRORS{'OK'},"startsshd: starting sshd");
@output = <SSHD>;
close(SSHD);
foreach $l (@output){
notify($ERRORS{'OK'},"startsshd output: $l");
}
return 1;
}
else{
notify($ERRORS{'OK'},"startsshd: could not execute /usr/sbin/sshd -f $HOME/sshd_config_vcl $!");
return 0;
}
}
}
sub notify {
my ($error,$string) = @_;
my $currenttime = makedatestring;
if(open(LOGIT, ">>$LOG")){
if( !$error ){
print LOGIT "$currenttime - $$: $string\n";
close(LOGIT);
return;
}
if ($error == 2 ) { #CRITICAL something bad happened, exiting
print LOGIT "\n$string\n";
print LOGIT "exiting\n";
close(LOGIT);
exit;
}
elsif( $error == 1 ){
# WARNING should prompt admin to
# continue or exit
# need to disable for cron
print LOGIT "\n---- WARNING ---- \n$string\n";
close(LOGIT);
}
# mail us, this is to be used for cron jobs
elsif( $error == 5 ){
print LOGIT "\n---- sending mail -- $currenttime - - $$ $string\n";
my $from = "root";
my $to = "fapeeler\@engr.ncsu.edu";
my $subject = "PROBLEM -- $0";
my $mailer = Mail::Mailer->new("sendmail");
if($mailer->open({From => $from,
To => $to,
Subject => $subject,
})){
print $mailer "vclclientd $currenttime - - process $$ \n\n\n$string";
$mailer->close();
}
return 1;
}
}
}
sub makedatestring {
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime( );
$year += 1900;
$mon++;
my $datestring = sprintf("%04d-%02d-%02d %02d:%02d:%02d",$year,$mon,$mday,$hour,$min,$sec);
return $datestring;
}
sub sshdstatus {
my $os = lc($^O);
if($os eq "solaris"){
my $sshd_admin_pid;
if(open(SSH,"/local/openssh/etc/sshd.admin.pid")){
my @file = <SSH>;
close(SSH);
chomp($file[0]);
$sshd_admin_pid=$file[0];
}
else{
notify($ERRORS{'OK'},"sshdstatus: could not open /local/openssh/etc/sshd.admin.pid $!");
return 0;
}
if(open(STAT,"/bin/pgrep -f sshd 2>&1 |")){
my @stat=<STAT>;
close(STAT);
foreach my $r (@stat) {
if($r =~ /$sshd_admin_pid/){
#notify($ERRORS{'OK'},"sshdstatus: sshd is running");
return 1;
}
}
notify($ERRORS{'OK'},"sshdstatus: sshd is NOT running trying to restart");
if(open(START,"/etc/init.d/sshd start 2>&1 |")){
my @start=<START>;
close(START);
foreach my $r (@start) {
if($r =~ /failed/i){
notify($ERRORS{'WARNING'},"store: sshd start failed @start");
return 0;
}
}
}#if start
}#STAT
return 1;
} #os=solaris
elsif($os =~ /linux/){
my $sshd_admin_pid;
if(open(SSH,"/var/run/sshd.pid")){
my @file = <SSH>;
close(SSH);
chomp($file[0]);
$sshd_admin_pid=$file[0];
}
else{
notify($ERRORS{'WARNING'},"sshdstatus: could not open /var/run/sshd.pid $!");
return 0;
}
my $running=0;
if(open(SSH,"pgrep -f sshd 2>&1|")){
my @lines = <SSH>;
close(SSH);
foreach my $l (@lines){
if($l =~ /$sshd_admin_pid/){
#ok it's running
$running=1; #not that this matters
return 1;
}
}
}#if pgrep
if(!$running){
#start sshd
notify($ERRORS{'WARNING'},"sshdstatus: not running trying to restart");
if(open(STAT,"/etc/init.d/sshd start 2>&1 |")){
my @stat = <STAT>;
close(STAT);
foreach my $s (@stat) {
if($s =~ /ok/i){
notify($ERRORS{'OK'},"sshdstatus: restarted core sshd process, @stat");
return 1;
}
}
#in case I don't return in above check
notify($ERRORS{'OK'},"sshdstatus: restart attempt may of had issues, @stat");
return 0;
}#if sshd start
}#if ! running
}#elsif linux
}
sub createnewssh_config_vcl {
#check for .orig from /etc/ssh dir
#if orig then just need to add port 22 and AllowUsers directive
my ($port22,$AU,$port24)=0;
my @file;
if(-e "/etc/sshd/sshd_config.orig"){
#good slurp it in
if(open(CONFIG,"$HOME/sshd_config_vcl")){
@file = <CONFIG>;
close(CONFIG);
foreach my $line (@file){
#check for port 22 and AllowUsers
if($line =~ /^Port 22/){
$port22=1;
}
if($line =~ /^AllowUsers/){
$AU=1;
}
if($line =~ s/^Port 24/Port 22/g){
$port22=1;
}
}
}
}
else{
#ok /etc/sshd/sshd_config.orig does not exist
#try to create from the /etc/sshd/sshd_config
}
#write out to $HOME/sshd_config_vcl
if(open(SC,">$HOME/sshd_config_vcl")){
print SC @file;
close(SC);
}
else{
notify($ERRORS{'CRITICAL'},"createnewssh_config_vcl: sshd_config_vcl was reported to not exists, in repairing I failed to create a new $HOME/sshd_config_vcl $!");
return 0;
}
}