187 lines
3.1 KiB
Perl
Executable File
187 lines
3.1 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
||
|
||
=head1 NAME
|
||
|
||
passwd - xen-tools role-script to setup root password for new guests.
|
||
|
||
=head1 AUTHOR
|
||
|
||
Steve
|
||
--
|
||
http://www.steve.org.uk/
|
||
|
||
=cut
|
||
|
||
|
||
|
||
use strict;
|
||
use warnings;
|
||
use Digest::MD5;
|
||
use Expect;
|
||
|
||
|
||
|
||
#
|
||
# Get the arguments our role script was passed.
|
||
#
|
||
my( $prefix, $passwd ) = ( @ARGV );
|
||
|
||
#
|
||
# Make sure they are valid.
|
||
#
|
||
if ( ! -d $prefix )
|
||
{
|
||
print "Prefix not found: $prefix\n";
|
||
exit;
|
||
}
|
||
|
||
if ( ! length( $passwd ) )
|
||
{
|
||
print "Password missing.\n";
|
||
exit;
|
||
}
|
||
|
||
|
||
#
|
||
# Now make sure we have the module we require.
|
||
#
|
||
eval "use Expect;";
|
||
if ( $@ )
|
||
{
|
||
print "Expect.pm not found. Aborting.\n";
|
||
print "(For Debian systems run:\n\tapt-get install libexpect-perl\n";
|
||
exit;
|
||
}
|
||
|
||
|
||
#
|
||
# OK now we're good to go: Continue until it succeeds.
|
||
#
|
||
my $count = 0;
|
||
while( $count < 10 )
|
||
{
|
||
changePassword( $prefix, $passwd );
|
||
$count += 1;
|
||
}
|
||
|
||
print "Failed to setup root password\n";
|
||
print "-----------------------------\n";
|
||
|
||
|
||
|
||
#
|
||
# Don't look at this code.
|
||
#
|
||
# OK. Expect sometimes fails. It sucks.
|
||
#
|
||
# So how do we know if a password change operation fails? We take
|
||
# an MD5(/etc/passwd + /etc/shadow) and if they don't change we've
|
||
# failed.
|
||
#
|
||
# Upon success we will simply exit();
|
||
#
|
||
#
|
||
sub changePassword
|
||
{
|
||
my ( $prefix, $passwd ) = ( @_ );
|
||
|
||
#
|
||
# Find current checksum.
|
||
#
|
||
my $orig = checksum( $prefix );
|
||
|
||
#
|
||
# Create the expect object.
|
||
#
|
||
my $exp = Expect->spawn( "/usr/sbin/chroot",
|
||
$prefix,
|
||
"/usr/bin/passwd",
|
||
"root" )
|
||
or die "Cannot spawn the password under chroot: $!\n";
|
||
|
||
# prompt
|
||
unless ($exp->expect(5,"Enter new"))
|
||
{
|
||
print "Failed 1st prompt\n";
|
||
$exp->hard_close();
|
||
return;
|
||
}
|
||
|
||
# send + wait.
|
||
$exp->send( $passwd . "\n" );
|
||
sleep( 1 );
|
||
|
||
# confirm
|
||
unless ($exp->expect(5,"Retype new"))
|
||
{
|
||
print "Failed 2nd prompt\n";
|
||
$exp->hard_close();
|
||
return;
|
||
}
|
||
|
||
# send.
|
||
$exp->send( $passwd . "\n" );
|
||
|
||
|
||
# Closeup.
|
||
$exp->soft_close();
|
||
|
||
#
|
||
# Did it work?
|
||
#
|
||
my $updated = checksum( $prefix );
|
||
|
||
if ( $updated ne $orig )
|
||
{
|
||
print "Password setup correctly.\n";
|
||
exit;
|
||
}
|
||
else
|
||
{
|
||
print "Setting password failed.\n";
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#
|
||
# Checksum /etc/passwd + /etc/shadow if they exist in the
|
||
# given chroot()
|
||
#
|
||
sub checksum
|
||
{
|
||
my( $prefix ) = ( @_ );
|
||
|
||
my $sum = '';
|
||
|
||
foreach my $file ( qw! /etc/passwd /etc/shadow ! )
|
||
{
|
||
if ( -e $prefix . "/" . $file )
|
||
{
|
||
#
|
||
# Open the file.
|
||
#
|
||
open(FILE, $prefix . "/" . $file)
|
||
or die "Can<61><6E>t open <20><>$prefix/$file<6C><65>: $!";
|
||
binmode(FILE);
|
||
|
||
#
|
||
# Add the data
|
||
#
|
||
my $md5 = Digest::MD5->new;
|
||
while (<FILE>)
|
||
{
|
||
$md5->add($_);
|
||
}
|
||
close(FILE);
|
||
|
||
#
|
||
# Update the sum
|
||
#
|
||
$sum .= $md5->b64digest;
|
||
}
|
||
}
|
||
|
||
return $sum;
|
||
}
|