diff --git a/roles/passwd b/roles/passwd new file mode 100755 index 0000000..213f048 --- /dev/null +++ b/roles/passwd @@ -0,0 +1,188 @@ +#!/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/ + + $Id: passwd,v 1.1 2007-04-03 00:01:18 steve Exp $ + +=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 () + { + $md5->add($_); + } + close(FILE); + + # + # Update the sum + # + $sum .= $md5->b64digest; + } + } + + return $sum; +}