From a6ed7d4845f1142f36b2c461d5a721bc68eb7d48 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sun, 21 Jun 2020 15:28:54 +0200 Subject: [PATCH 1/5] nixos/users-groups: remove ancient security.initialRootPassword option This option has been deprecated for a long time because is redundant (users.users.root.initialHashedPassword exists). Moreover, being of type string, it required to handle the special value "!" separately, instead of using just `null`. --- nixos/modules/config/users-groups.nix | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index c2f16e5ed8e..83296a54bc4 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -415,6 +415,12 @@ in { imports = [ (mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ]) (mkAliasOptionModule [ "users" "extraGroups" ] [ "users" "groups" ]) + (mkChangedOptionModule + [ "security" "initialRootPassword" ] + [ "users" "users" "root" "initialHashedPassword" ] + (cfg: if cfg.security.initialHashedPassword == "!" + then null + else cfg.security.initialHashedPassword)) ]; ###### interface @@ -486,14 +492,6 @@ in { ''; }; - # FIXME: obsolete - will remove. - security.initialRootPassword = mkOption { - type = types.str; - default = "!"; - example = ""; - visible = false; - }; - }; @@ -508,7 +506,6 @@ in { home = "/root"; shell = mkDefault cfg.defaultUserShell; group = "root"; - initialHashedPassword = mkDefault config.security.initialRootPassword; }; nobody = { uid = ids.uids.nobody; @@ -597,7 +594,7 @@ in { || cfg.group == "wheel" || elem "wheel" cfg.extraGroups) && - ((cfg.hashedPassword != null && cfg.hashedPassword != "!") + (cfg.hashedPassword != null || cfg.password != null || cfg.passwordFile != null || cfg.openssh.authorizedKeys.keys != [] From 900ae9756902e4a3c53f32d4dee9ba1d995722df Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sun, 21 Jun 2020 16:55:45 +0200 Subject: [PATCH 2/5] nixos/users-groups: clearly document special hash values This explanation was contained in the description of security.initialRootPassword but got lost when it was deprecated a long ago (f496c3c) and removed. --- nixos/modules/config/users-groups.nix | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 83296a54bc4..c2b8b6b3163 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -25,17 +25,19 @@ let ''; hashedPasswordDescription = '' - To generate hashed password install mkpasswd + To generate a hashed password install the mkpasswd package and run mkpasswd -m sha-512. - For password-less logins without password prompt, use - the empty string "". + If set to an empty string (""), this user will + be able to log in without being asked for a password (but not via remote + services such as SSH, or indirectly via su or + sudo). This should only be used for e.g. bootable + live systems. Note: this is different from setting an empty password, + which ca be achieved using . - For logins with a fixed password (including the empty-string password with - prompt), use one of the un-hashed password options instead, such as - . - - Such unprotected logins should only be used for e.g. bootable live systems. + If set to null (default) this user will not + be able to log in using a password (i.e. via login + command). ''; userOpts = { name, config, ... }: { From 751c2ed6e4af9e525fe57b7c0f0ee8a611eab9fa Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sun, 21 Jun 2020 17:01:34 +0200 Subject: [PATCH 3/5] nixos/users-groups: do not check validity of empty hashes --- nixos/modules/config/users-groups.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index c2b8b6b3163..e06514bd934 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -629,7 +629,8 @@ in { content = "${base64}${sep}${base64}"; mcf = "^${sep}${scheme}${sep}${content}$"; in - if (user.hashedPassword != null + if (user.hashedPassword != null # login disabled + && user.hashedPassword != "" # login without password && builtins.match mcf user.hashedPassword == null) then '' From 99899e2e464845da34638ab35125943e8445bce0 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Thu, 25 Jun 2020 02:00:56 +0200 Subject: [PATCH 4/5] nixos/users-groups: add assertion for ":" in hashes --- nixos/modules/config/users-groups.nix | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index e06514bd934..cca87d8b4a5 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -606,7 +606,17 @@ in { Neither the root account nor any wheel user has a password or SSH authorized key. You must set one to prevent being locked out of your system.''; } - ]; + ] ++ flip mapAttrsToList cfg.users (name: user: + { + assertion = (user.hashedPassword != null) + -> (builtins.match ".*:.*" user.hashedPassword == null); + message = '' + The password hash of user "${name}" contains a ":" character. + This is invalid and would break the login system because the fields + of /etc/shadow (file where hashes are stored) are colon-separated. + Please check the value of option `users.users."${name}".hashedPassword`.''; + } + ); warnings = builtins.filter (x: x != null) ( From c37347af7eaa0177e3a374dd94158ff546f20fdb Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Thu, 25 Jun 2020 02:02:29 +0200 Subject: [PATCH 5/5] nixos/users-groups: handle password hashes with special meaning --- nixos/modules/config/users-groups.nix | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index cca87d8b4a5..12d9be94663 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -6,6 +6,16 @@ let ids = config.ids; cfg = config.users; + # Check whether a password hash will allow login. + allowsLogin = hash: + hash == "" # login without password + || !(lib.elem hash + [ null # password login disabled + "!" # password login disabled + "!!" # a variant of "!" + "*" # password unset + ]); + passwordDescription = '' The options , and @@ -596,7 +606,7 @@ in { || cfg.group == "wheel" || elem "wheel" cfg.extraGroups) && - (cfg.hashedPassword != null + (allowsLogin cfg.hashedPassword || cfg.password != null || cfg.passwordFile != null || cfg.openssh.authorizedKeys.keys != [] @@ -639,15 +649,13 @@ in { content = "${base64}${sep}${base64}"; mcf = "^${sep}${scheme}${sep}${content}$"; in - if (user.hashedPassword != null # login disabled + if (allowsLogin user.hashedPassword && user.hashedPassword != "" # login without password && builtins.match mcf user.hashedPassword == null) - then - '' + then '' The password hash of user "${name}" may be invalid. You must set a valid hash or the user will be locked out of their account. Please - check the value of option `users.users."${name}".hashedPassword`. - '' + check the value of option `users.users."${name}".hashedPassword`.'' else null ));