/ag-passwd
#!/usr/bin/perl

use AwesomeGrid::User;

use Crypt::PasswdMD5;			# Linux, FreeBSD
use Digest::SHA1 qw/sha1_hex/;		# OS X 10.4
use Crypt::Eksblowfish::Bcrypt;		# OpenBSD

sub getsalt {
	my $length = shift;
	open RAND, "/dev/urandom";	# For production, this should be
					# /dev/random
	my $data;
	read(RAND, $data, $length);
	close RAND;
	return $data;
}

sub unix_MD5 {
	my $passwd = shift;
	my $salt = unpack("h8",getsalt(8));
	return unix_md5_crypt($passwd, $salt);
}

sub apache_MD5 {
	my $passwd = shift;
	my $salt = unpack("h8",getsalt(8));
	return apache_md5_crypt($passwd, $salt);
}

sub OSX_SHA1 {
	my $passwd = shift;
	my $v = getsalt(4);
	my $hash = sha1_hex("$v$passwd");
	my $salt = unpack("H8",$v);
	return uc("$salt$hash");
}

sub OpenBSD_Bcrypt {
	my $passwd = shift;
	my $salt = Crypt::Eksblowfish::Bcrypt::en_base64(getsalt(16));
	my $p = Crypt::Eksblowfish::Bcrypt::bcrypt($passwd, '$2a$08$' . $salt);

	return $p;
}

my $user;
if (exists $ENV{SUDO_USER}) {
	$user = $ENV{SUDO_USER};
} else {
	$user = shift;
	if (!$user) {
		if ($> == 0) {
			print "When used by root, you must specify a username\n";
		} else {
			chomp(my $sudo = `which sudo`);
			if ($sudo) {
				print "Attempting to sudo myself...\n";
				exec "$sudo $0";
			} else {
				print "You are not root and you don't have sudo installed. Sorry.\n";
			}
		}
		exit 1;
	}
}

if (!AwesomeGrid::User::exists($user)) {
	print "User $user does not exist\n";
	exit 1;
}

print "Changing password for $user\n";

my $aguser = AwesomeGrid::User->load($user) || exit 1;

# Restore sanity in case of emergency
END { system("stty echo") }

system("stty -echo");
print STDERR "New Password: ";
my $passwd1 = <STDIN>;
chomp $passwd1;
print STDERR "\n";

print STDERR "Repeat new password: ";
my $passwd2 = <STDIN>;
chomp $passwd2;
print STDERR "\n";

system("stty echo");

if ($passwd1 != $passwd1) {
	print "Passwords don't match.\n";
	exit 1;
}

$aguser->{'passwd-unix-md5'} = unix_MD5($passwd1);
$aguser->{'passwd-apache-md5'} = apache_MD5($passwd1);
$aguser->{'passwd-osx-sha1'} = OSX_SHA1($passwd1);
$aguser->{'passwd-bcrypt'} = OpenBSD_Bcrypt($passwd1);

$aguser->save();
print "Password updated.\n";