From 0b92ad02c87b9eff8dbc45cc4221289d737d29a6 Mon Sep 17 00:00:00 2001 From: Rickard Nilsson Date: Wed, 5 Feb 2014 15:07:20 +0100 Subject: [PATCH] Re-introduce security.initialRootPassword, and add a new option users.extraUsers..hashedPassword --- nixos/modules/config/users-groups.nix | 83 ++++++++++++++----- nixos/modules/virtualisation/amazon-image.nix | 2 +- .../virtualisation/virtualbox-image.nix | 2 +- 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 97bf6726279..e38593d5602 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -7,6 +7,24 @@ let ids = config.ids; cfg = config.users; + passwordDescription = '' + The options hashedPassword, + password and passwordFile + controls what password is set for the user. + hashedPassword overrides both + password and passwordFile. + password overrides passwordFile. + If none of these three options are set, no password is assigned to + the user, and the user will not be able to do password logins. + If the option users.mutableUsers is true, the + password defined in one of the three options will only be set when + the user is created for the first time. After that, you are free to + change the password with the ordinary user management commands. If + users.mutableUsers is false, you cannot change + user passwords, they will always be set according to the password + options. + ''; + userOpts = { name, config, ... }: { options = { @@ -76,24 +94,24 @@ let ''; }; + hashedPassword = mkOption { + type = with types; uniq (nullOr str); + default = null; + description = '' + Specifies the (hashed) password for the user. + ${passwordDescription} + ''; + }; + password = mkOption { type = with types; uniq (nullOr str); default = null; description = '' - The user's password. If undefined, no password is set for - the user. Warning: do not set confidential information here - because it is world-readable in the Nix store. This option - should only be used for public accounts such as - guest. - The option password overrides - passwordFile, if both are specified. - If none of the options password or - passwordFile are specified, the user account will - be locked for password logins. This is the default behavior except - for the root account, which has an empty password by default. If you - want to lock the root account for password logins, set - users.extraUsers.root.password to - null. + Specifies the (clear text) password for the user. + Warning: do not set confidential information here + because it is world-readable in the Nix store. This option + should only be used for public accounts. + ${passwordDescription} ''; }; @@ -105,8 +123,7 @@ let file is read on each system activation. The file should contain exactly one line, which should be the password in an encrypted form that is suitable for the chpasswd -e command. - See the password for more details on how passwords - are assigned. + ${passwordDescription} ''; }; @@ -297,6 +314,26 @@ in options = [ groupOpts ]; }; + security.initialRootPassword = mkOption { + type = types.str; + default = ""; + example = "!"; + description = '' + The (hashed) password for the root account set on initial + installation. The empty string denotes that root can login + locally without a password (but not via remote services such + as SSH, or indirectly via su or + sudo). The string ! + prevents root from logging in using a password. + Note, setting this option sets + users.extraUsers.root.hashedPassword. + Note, if users.mutableUsers is false + you cannot change the root password manually, so in that case + the name of this option is a bit misleading, since it will define + the root password beyond the user initialisation phase. + ''; + }; + }; @@ -311,7 +348,7 @@ in home = "/root"; shell = cfg.defaultUserShell; group = "root"; - password = mkDefault ""; + hashedPassword = config.security.initialRootPassword; }; nobody = { uid = ids.uids.nobody; @@ -351,17 +388,21 @@ in test "$(getent shadow '${u.name}' | cut -d: -f2)" != "x" && setpw=no ''} if [ "$setpw" == "yes" ]; then - ${if u.password == "" + ${if !(isNull u.hashedPassword) + then '' + echo "${u.name}:${u.hashedPassword}" | \ + ${pkgs.shadow}/sbin/chpasswd -e'' + else if u.password == "" then "passwd -d '${u.name}' &>/dev/null" - else if (isNull u.password && isNull u.passwordFile) - then "passwd -l '${u.name}' &>/dev/null" else if !(isNull u.password) then '' echo "${u.name}:${u.password}" | ${pkgs.shadow}/sbin/chpasswd'' - else '' + else if !(isNull u.passwordFile) + then '' echo -n "${u.name}:" | cat - "${u.passwordFile}" | \ ${pkgs.shadow}/sbin/chpasswd -e '' + else "passwd -l '${u.name}' &>/dev/null" } fi ''; diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 701e95af7d3..abd2a1084bd 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -164,5 +164,5 @@ with pkgs.lib; # Prevent logging in as root without a password. This doesn't really matter, # since the only PAM services that allow logging in with a null # password are local ones that are inaccessible on EC2 machines. - users.extraUsers.root.password = null; + security.initialRootPassword = "!"; } diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index a89c8264a33..71bdf31a98d 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -111,5 +111,5 @@ with pkgs.lib; # Prevent logging in as root without a password. For NixOps, we # don't need this because the user can login via SSH, and for the # demo images, there is a demo user account that can sudo to root. - users.extraUsers.root.password = null; + security.initialRootPassword = "!"; }