1
0
mirror of synced 2026-04-15 15:49:48 +00:00

Added a genpass flag to generate a password and install it in the guest

* We could use the same functions to set a password via a --password flag
* It would nice to move more functionality to subroutines
* The current generatePassword subroutine, only generates alphanum passwords and hashes
This commit is contained in:
Dmitry Nedospasov
2010-06-07 17:35:52 +02:00
parent ef0eb41e3b
commit 39806f8ad0
2 changed files with 91 additions and 193 deletions

View File

@@ -104,8 +104,10 @@ xen-create-image - Easily create new Xen instances with networking and OpenSSH.
fs, size, swap and noswap are ignored when using this
option.
--genpass Generate a random root password
--passwd Ask for a root password during setup.
NOTE: This is done interactively.
NOTE: This is done interactively and overrides --genpass
--role=role Run the specified role script(s) post-install.
Role scripts are discussed later in this manpage.
@@ -732,6 +734,7 @@ use Digest::MD5 qw/ md5_hex /;
use Env;
use File::Path qw/ mkpath /;
use File::Temp qw/ tempdir /;
use File::Copy qw/ cp /;
use Getopt::Long;
use Pod::Usage;
@@ -784,6 +787,11 @@ my $RELEASE = '4.2beta1';
my $IP_ADDRESSES = '';
#
# Variable for generated password
#
my $PASSWORD = '';
#
# Setup default options.
#
@@ -1018,7 +1026,7 @@ runXenConfigCreation();
#
# Setup the password if the user wanted that.
#
setupRootPassword() if ( $CONFIG{ 'passwd' } );
setupRootPassword() if ( $CONFIG{ 'passwd' } or $CONFIG{ 'genpass' } );
#
@@ -1342,6 +1350,13 @@ sub setupDefaultOptions
$CONFIG{ 'install-method' } = 'debootstrap';
$CONFIG{ 'debootstrap-cmd' } = '';
#
# Default values for passwords
#
$CONFIG{ 'genpass' } = 1;
$CONFIG{ 'genpass_len' } = 8;
$CONFIG{ 'password' } = '';
#
# The program to run to create a filesystem.
#
@@ -1551,6 +1566,9 @@ sub parseCommandLineArguments
"hooks=i", \$CONFIG{ 'hooks' },
"pygrub", \$CONFIG{ 'pygrub' },
"passwd", \$CONFIG{ 'passwd' },
"genpass=i", \$CONFIG{ 'genpass' },
"genpass-len=i", \$CONFIG{ 'genpass_len' },
"password=s", \$CONFIG{ 'password' },
"partitions=s", \$CONFIG{ 'partitions' },
"role=s", \$CONFIG{ 'role' },
"role-args=s", \$CONFIG{ 'role-args' },
@@ -3729,16 +3747,81 @@ sub setupRootPassword
{
logprint("Setting up root password\n");
if ( -x $MOUNT_POINT . "/usr/bin/passwd" )
if ( $CONFIG{ 'passwd' } )
{
system("chroot $MOUNT_POINT /usr/bin/passwd");
if ( -x $MOUNT_POINT . "/usr/bin/passwd" )
{
system("chroot $MOUNT_POINT /usr/bin/passwd");
}
else
{
logprint("'passwd' command not found in the new install.\n");
}
}
else
{
logprint("'passwd' command not found in the new install.\n");
logprint("Generating a password for the new guest.\n");
#
# Replace the password in the /etc/shadow file
#
my $shadow_path = $MOUNT_POINT . '/etc/shadow';
if ( -e $shadow_path )
{
#
# Generate a password, salt and use that to generating a hash
#
my $salt = generatePassword(8);
$PASSWORD = generatePassword( $CONFIG{ 'genpass_len' } );
my $hash = `echo -n $PASSWORD | openssl passwd -stdin -1 -salt $salt`;
$hash =~ s/\s+$//;
#
# Copy the file to ensure the original retains the correct
# permissions set by the System
#
my $tmp_shadow_path = "$shadow_path.tmp";
cp("$shadow_path","$tmp_shadow_path");
open(TMP, "<", $tmp_shadow_path) or die $!;
open(SHADOW, ">", $shadow_path) or die $!;
my $line;
while(defined($line = <TMP>))
{
chomp $line;
$line =~ s#^root:[^:]*:#root:$hash:#;
print SHADOW "$line\n";
}
#
# Close the files and delete the temporary file
#
close(SHADOW);
close(TMP);
unlink($tmp_shadow_path);
}
else
{
logprint("Failed to find /etc/passwd in the install.\n");
}
}
}
=begin doc
create a random "string"
=end doc
=cut
sub generatePassword {
my $length = $_[0];
my $possible = 'abcdefghijkmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
my $password = '';
while (length($password) < $length) {
$password .= substr($possible, (int(rand(length($possible)))), 1);
}
return $password
}
=begin doc
@@ -4010,7 +4093,8 @@ sub END
logprint( $IP_ADDRESSES );
}
logprint("\n");
logprint("RSA Fingerprint : $host_rsa_key");
logprint("\n\n");
logprint("RSA Fingerprint : $host_rsa_key\n");
logprint("Root Password : $PASSWORD\n");
logprint("\n");
}
}

View File

@@ -1,186 +0,0 @@
#!/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;
}