#!/usr/bin/perl

use strict;
use warnings;

sub execpipe {
    my $cmd = shift;
    my $ret;

    open OP, '-|' or exec "$cmd 2>&1" or die "$!";
    while (<OP>) {
        $ret .= $_;
    }
    close OP;
    return $ret;
}

sub find_all_sshd {
    print "Attempting to locate sshd binaries installed on the system ...<br />\n";
    my @sshds;
    my @locations = qw( /usr/sbin /usr/local/sbin /usr/bin /usr/local/bin );
    foreach my $loc (@locations) {
        if ( -e $loc . '/sshd' ) {
            print "Located $loc/sshd<br />\n";
            push @sshds, $loc . '/sshd';
        }
    }
    print "Done.<br />\n";
    return @sshds;
}

#print "Content-type: text/html\n\n";

my @sshd_binaries = find_all_sshd();
if ( !@sshd_binaries ) {
    print "Sorry, no sshd binary was located on your system. Exiting ...<br />\n";
    exit;
}

print "Killing existing sshd processes...<br />\n";

if ( -e '/etc/init.d/sshd' ) {
    system '/etc/init.d/sshd', 'stop';
    print "<br />\n";
}

open OP, '-|' or exec "ps aux" or die "$!";
while (<OP>) {
    if (m/^\S+\s+(\d+)\s+.+sshd/) {
        next if $1 == $$;
        if ( kill( 9, $1 ) ) {
            print "killed $1 ";
        }
    }
}
close OP;

print "Done.<br />\n";

my $netstat = execpipe "netstat -an";
my $port    = 22;

# search for next available port above $port, in the event that a zombie or another existing process
# are using the defined port.

if ( $netstat =~ m/:$port\s/m ) {
    print "Attempting to locate available port ...<br />\n";
    print "port $port is already in use<br />\n";
    while ( $port < 65356 ) {
        $port++;
        last if $netstat !~ m/:$port\s/m;
    }
    if ( $port == 65356 ) {
        print "Failed to find an available port. Exiting ...<br />\n";
        exit;
    }
}

if ( !-d '/var/cpanel' ) {
    print "That's weird, /var/cpanel does not exist. Creating now.<br />\n";
    mkdir '/var/cpanel', 0750;
    if ( !-d '/var/cpanel' ) {
        print "Could not create /var/cpanel. Cannot continue.<br />\n";
        exit;
    }
}

print "configuring sshd to run on port $port<br />\n";
if ( open my $sshsafe_fh, '>', '/var/cpanel/safe_sshd' ) {
    print {$sshsafe_fh} <<"EOM";

PasswordAuthentication yes
Port $port

EOM
    close $sshsafe_fh;
}
else {
    print "Failed to write new sshd configuration: $!<br /><br />\nExiting ...<br />\n";
    exit;
}

foreach my $sshd (@sshd_binaries) {
    if ( !-x $sshd ) {
        print "$sshd is not executable... Turning on executable bits.<br />\n";
        chmod 0755, $sshd;
    }
    my $ret = system $sshd, '-f', '/var/cpanel/safe_sshd';
    if ( $ret == 0 ) {
        print "$sshd successfully started!<br />\n";

        open OP, '-|' or exec "ps aux" or die "$!";
        while (<OP>) {
            if (m/^\S+\s+(\d+)\s+.+sshd/) {
                print $_ . "<br />\n";
            }
        }
        close OP;

        exit;
    }
    else {
        print "failed to start $sshd ...<br />\n";
    }
}

exit;
