#!/usr/bin/perl
# cpanel - autofixer2/deauthorize                 Copyright(c) 2013 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

use strict;

our $VERSION = 1.4;

BEGIN {
    unshift @INC, '/usr/local/cpanel';
}

{
    local $| = 1;
    my ( $ticket_id, $user ) = get_args();
    $user ||= 'root';

    usage() if !defined $ticket_id;

    setuids_if_needed($user);

    fix_permissions_on_authorized_keys($user);
    my $status = remove_key_authorized_keys( $user, $ticket_id );

    if ( $ticket_id eq '0' ) {
        if ($status) {
            print "DeAuthorized key all tickets.cpanel.net keys for $user\n";
        }
        else {
            print "No keys for tickets.cpanel.net for $user were found.\n";
        }

    }
    else {
        if ($status) {
            print "DeAuthorized key $ticket_id\@tickets.cpanel.net for $user\n";
        }
        else {
            print "Key $ticket_id\@tickets.cpanel.net for $user was not found so it could not be DeAuthorized.\n";
        }
    }

    exit 0;
}

sub fix_permissions_on_authorized_keys {
    my ($user) = @_;

    my $homedir = ( getpwnam($user) )[7];

    if ( !$homedir ) {
        print "Failed to fetch homedir for $user\n";
        exit 1;
    }

    mkdir "$homedir/.ssh", 0700;
    system 'touch', "$homedir/.ssh/authorized_keys";
    chmod 0600, "$homedir/.ssh/authorized_keys";

    return 1;
}

sub remove_key_authorized_keys {
    my ( $user, $ticket_id ) = @_;

    if ( $ticket_id eq '0' ) {
        $ticket_id = '';
    }
    my $homedir = ( getpwnam($user) )[7];
    eval { local $SIG{__DIE__}; local $SIG{__WARN__}; require Cpanel::SafeFile; };

    my $key_comment = sprintf( '%d[_server_\d]*@tickets.cpanel.net_\d+\s*$', $ticket_id );
    my $authorized_keys_file = "$homedir/.ssh/authorized_keys";
    my $lock;
    my $fh;
    if ( $INC{'Cpanel/SafeFile.pm'} ) {
        if ( !( $lock = Cpanel::SafeFile::safeopen( $fh, '+<', $authorized_keys_file ) ) ) {
            print "Failed to open + lock $authorized_keys_file: $1\n";
            exit 1;
        }
    }
    else {
        if ( !open( $fh, '+<', $authorized_keys_file ) ) {
            print "Failed to open $authorized_keys_file: $1\n";
            exit 1;
        }
    }
    my $txt;
    {
        local $/ = undef;
        $txt = readline($fh);
    }
    my $status = ( grep { m/$key_comment/ } split( /\n/, $txt ) ) ? 1 : 0;
    my @all_keys_line = grep { !m/$key_comment/ } split( /\n/, $txt );
    seek( $fh, 0, 0 );
    print {$fh} join( "\n", @all_keys_line ) . "\n";
    truncate( $fh, tell($fh) );
    if ( $INC{'Cpanel/SafeFile.pm'} ) {
        Cpanel::SafeFile::safeclose( $fh, $lock );
    }
    else {
        close($fh);
    }
    return $status;
}

sub setuids_if_needed {
    my ($user) = @_;
    if ( $user ne ( getpwuid($>) )[0] ) {
        my ( $uid, $gid ) = ( getpwnam($user) )[ 2, 3 ];
        if ( !$uid ) { die "Failed for fetch uids for $user"; }
        setuids( $uid, $gid ) || die "Could not setuid to $user to modify authorized_keys";
    }

    return 1;
}

sub setuids {
    my ( $uid, $gid ) = @_;
    $) = join( ' ', $gid, $gid );
    if ( $gid != int($)) ) {
        die("setuids failed: Error setting EGID ($gid) [$uid]");
    }

    $( = $gid;
    if ( $gid != $( ) {
        die("setuids failed: Error setting RGID ($gid) [$uid]");
    }

    $> = $uid;
    if ( $> != $uid ) {
        die("setuids failed: Error setting EUID ($uid) [$uid]");
    }

    $< = $uid;
    if ( $< != $uid ) {
        die("setuids failed: Error setting RUID ($uid) [$uid]");
    }
    return 1;
}

sub usage {
    print "\n" x 3;
    print "Usage: deauthorize <ticketid>          - DeAuthorize the cPanel ticket system key for root\n";
    print "Usage: deauthorize <user> <ticketid>   - DeAuthorize the cPanel ticket system key for a user\n";

    print "Usage: deauthorize 0                   - DeAuthorize all cPanel ticket system keys for root\n";
    print "Usage: deauthorize <user> 0            - DeAuthorize all cPanel ticket system keys for a user\n";

    print "Enviorment variables are accepted for execution though the autorepair system.\n";
    print "AUTHUSER=<user> TICKET=<ticketid> /scripts/autorepair authorize\n";
    print "\n\n";
    exit 1;
}

sub get_args {

    my $ticket_id;
    my $user;
    my @ARGS = @ARGV;

    if ( defined $ENV{'AUTHUSER'} ) {
        @ARGS = ( $ENV{'AUTHUSER'}, $ENV{'TICKET'} );
    }
    elsif ( defined $ENV{'TICKET'} ) {
        @ARGS = ( $ENV{'TICKET'} );
    }
    $ARGS[0] =~ s/\s+//g;
    $ARGS[1] =~ s/\s+//g;

    if ( ( getpwnam( $ARGS[0] ) )[0] ) {
        $user = $ARGS[0];
        ($ticket_id) = ( $ARGS[1] =~ /([0-9]+)/ );
    }
    elsif ( $ARGS[0] =~ /([0-9]+)/ ) {
        $ticket_id = $1;
    }

    return ( $ticket_id, $user ) if defined $ticket_id;

    print "\n\ncPanel Ticket System authorized_keys uninstaller.\n\n";
    if ( !$ticket_id ) {
        open( STDIN, '<&STDOUT' ) || die "Failed to open STDOUT";    # required to escape autorepair's stdin redirection
        print "Which ticket number would you like to deauthorize (0 for all)? ";
        $ticket_id = <>;
        chomp($ticket_id);
        if ( $ticket_id !~ /^[0-9]+$/ ) {
            print "Invalid ticket id.\n";
            usage();
        }
        print "Which user would you like to remove the key from [root] ? ";
        $user = <>;
        chomp($user);
        $user ||= 'root';
        if ( !( getpwnam($user) )[0] ) {
            print "Invalid user.\n";
            usage();
        }
    }
    return ( $ticket_id, $user );
}
