#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;

use File::Basename;
use lib dirname(__FILE__) . '/../../../lib/perl';
use OVH::Result;
use OVH::Bastion;
use OVH::Bastion::Plugin qw( :DEFAULT help );

my $remainingOptions = OVH::Bastion::Plugin::begin(
    argv   => \@ARGV,
    header => "setup a UNIX password for your local account",
    # we don't want to have this plugin staying in the background waiting for user input
    # when there's no longer a terminal attached:
    exitOnSignal => 1,
    options      => {'yes' => \my $yes},
    helptext     => <<'EOF'
Setup an additional credential (UNIX password) to access your account

Usage: --osh SCRIPT_NAME [--yes]

  --yes  Don't ask for confirmation
EOF
);

my $fnret;
my @command;

if (OVH::Bastion::config('accountMFAPolicy')->value eq 'disabled') {
    osh_exit('ERR_DISABLED_BY_POLICY',
        "Sorry, Multi-Factor Authentication has been disabled by policy on this bastion");
}

if ($ENV{'OSH_IN_INTERACTIVE_SESSION'}) {
    osh_exit('ERR_PRECONDITIONS_FAILED',
        "For security reasons, this plugin can't be used in interactive mode.\nTo ensure you're the owner of the account, please call it the regular way (i.e. --osh $scriptName)"
    );
}

# check if we have a valid password or an invalid/locked one
@command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-selfMFASetupPassword';
push @command, '--account', $self, '--step', '0';
$fnret = OVH::Bastion::helper(cmd => \@command);
$fnret or osh_exit $fnret;

if ($fnret->value->{'password'} ne 'set') {

    # ok, we need to set the password to a temporary valid one, but as people don't read,
    # tell them what we'll do and expect them to say 'y'
    if (!$yes) {
        osh_info
          "As you currently don't have any password set,\nwe'll setup a temporary one that you'll be asked to change right away.";
        osh_info
          "\nType 'y' and press ENTER to proceed, anything else to abort.\nNote that what you type will NOT be echoed on the terminal.";
        chomp(my $ans = <STDIN>);
        if ($ans ne 'y') {
            osh_exit(R('OK_NO_CHANGE', msg => "Aborted per user request"));
        }
    }

    @command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
    push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-selfMFASetupPassword';
    push @command, '--account', $self, '--step', '1';

    $fnret = OVH::Bastion::helper(cmd => \@command);
    $fnret or osh_exit $fnret;

    osh_info "We've set a temporary password so you can change it.";
    osh_info "On the prompt for your current UNIX password, enter this: " . $fnret->value->{'password'};
}

osh_info "Changing your MFA password.";

while (1) {

    # BSD doesn't attach our caller tty correctly when using OVH::Bastion::execute, so using system() here
    system('passwd');
    if ($? != 0) {
        osh_warn("Error while changing your password! Try again:");
        sleep(1);
        next;
    }

    last;
}

# apply password policy parameters (expiration, etc)
@command = qw{ sudo -n -u root -- /usr/bin/env perl -T };
push @command, $OVH::Bastion::BASEPATH . '/bin/helper/osh-selfMFASetupPassword';
push @command, '--account', $self, '--step', '2';

$fnret = OVH::Bastion::helper(cmd => \@command);
$fnret or osh_exit $fnret;

osh_ok;
