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¡Çt open ¡Ç$prefix/$file¡Ç: $!";
|
|
binmode(FILE);
|
|
|
|
#
|
|
# Add the data
|
|
#
|
|
my $md5 = Digest::MD5->new;
|
|
while (<FILE>)
|
|
{
|
|
$md5->add($_);
|
|
}
|
|
close(FILE);
|
|
|
|
#
|
|
# Update the sum
|
|
#
|
|
$sum .= $md5->b64digest;
|
|
}
|
|
}
|
|
|
|
return $sum;
|
|
}
|