From a9f5e77e2f9b0e27ff6d3998b3c29c88dede1a7d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 31 Oct 2014 17:39:19 +0100 Subject: [PATCH] update-users-groups.pl: Generate hashed passwords internally I.e. don't call "passwd" to update /etc/shadow from the "password" option. This has the side-effect of not updating the password if mutableUsers = true (since the code path for "hashedPassword" has a check for mutableUsers). Fixes #4747. --- nixos/modules/config/update-users-groups.pl | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl index 197b65e27c4b..abcb082af8e5 100644 --- a/nixos/modules/config/update-users-groups.pl +++ b/nixos/modules/config/update-users-groups.pl @@ -6,6 +6,15 @@ use JSON; make_path("/var/lib/nixos", { mode => 0755 }); +sub hashPassword { + my ($password) = @_; + my $salt = ""; + my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z'); + $salt .= $chars[rand 64] for (1..8); + return crypt($password, '$6$' . $salt . '$'); +} + + # Functions for allocating free GIDs/UIDs. FIXME: respect ID ranges in # /etc/login.defs. sub allocId { @@ -174,6 +183,8 @@ foreach my $u (@{$spec->{users}}) { } else { warn "warning: password file ‘$u->{passwordFile}’ does not exist\n"; } + } elsif (defined $u->{password}) { + $u->{hashedPassword} = hashPassword($u->{password}); } $u->{fakePassword} = $existing->{fakePassword} // "x"; @@ -208,32 +219,21 @@ my %shadowSeen; foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow") : ()) { chomp $line; - my ($name, $password, @rest) = split(':', $line, -9); + my ($name, $hashedPassword, @rest) = split(':', $line, -9); my $u = $usersOut{$name};; next if !defined $u; - $password = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME - push @shadowNew, join(":", $name, $password, @rest) . "\n"; + $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME + push @shadowNew, join(":", $name, $hashedPassword, @rest) . "\n"; $shadowSeen{$name} = 1; } foreach my $u (values %usersOut) { next if defined $shadowSeen{$u->{name}}; - my $password = "!"; - $password = $u->{hashedPassword} if defined $u->{hashedPassword}; + my $hashedPassword = "!"; + $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword}; # FIXME: set correct value for sp_lstchg. - push @shadowNew, join(":", $u->{name}, $password, "1::::::") . "\n"; + push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::::") . "\n"; } write_file("/etc/shadow.tmp", { perms => 0600 }, @shadowNew); rename("/etc/shadow.tmp", "/etc/shadow") or die; - - -# Call chpasswd to apply password. FIXME: generate the hashes directly -# and merge into the /etc/shadow updating above. -foreach my $u (@{$spec->{users}}) { - if (defined $u->{password}) { - my $pid = open(PW, "| chpasswd") or die; - print PW "$u->{name}:$u->{password}\n"; - close PW or die "unable to change password of user ‘$u->{name}’: $?\n"; - } -}