Merge pull request #91238 from rnhmjoj/users

nixos/users-groups: do not check validity of special hashes
This commit is contained in:
Michele Guerini Rocco 2020-07-07 10:57:51 +02:00 committed by GitHub
commit 01c4a388ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -6,6 +6,16 @@ let
ids = config.ids; ids = config.ids;
cfg = config.users; 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 = '' passwordDescription = ''
The options <option>hashedPassword</option>, The options <option>hashedPassword</option>,
<option>password</option> and <option>passwordFile</option> <option>password</option> and <option>passwordFile</option>
@ -25,17 +35,19 @@ let
''; '';
hashedPasswordDescription = '' hashedPasswordDescription = ''
To generate hashed password install <literal>mkpasswd</literal> To generate a hashed password install the <literal>mkpasswd</literal>
package and run <literal>mkpasswd -m sha-512</literal>. package and run <literal>mkpasswd -m sha-512</literal>.
For password-less logins without password prompt, use If set to an empty string (<literal>""</literal>), this user will
the empty string <literal>""</literal>. be able to log in without being asked for a password (but not via remote
services such as SSH, or indirectly via <command>su</command> or
<command>sudo</command>). 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 <option>users.users.&lt;name?&gt;.password</option>.
For logins with a fixed password (including the empty-string password with If set to <literal>null</literal> (default) this user will not
prompt), use one of the un-hashed password options instead, such as be able to log in using a password (i.e. via <command>login</command>
<option>users.users.&lt;name?&gt;.password</option>. command).
Such unprotected logins should only be used for e.g. bootable live systems.
''; '';
userOpts = { name, config, ... }: { userOpts = { name, config, ... }: {
@ -415,6 +427,12 @@ in {
imports = [ imports = [
(mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ]) (mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ])
(mkAliasOptionModule [ "users" "extraGroups" ] [ "users" "groups" ]) (mkAliasOptionModule [ "users" "extraGroups" ] [ "users" "groups" ])
(mkChangedOptionModule
[ "security" "initialRootPassword" ]
[ "users" "users" "root" "initialHashedPassword" ]
(cfg: if cfg.security.initialHashedPassword == "!"
then null
else cfg.security.initialHashedPassword))
]; ];
###### interface ###### interface
@ -486,14 +504,6 @@ in {
''; '';
}; };
# FIXME: obsolete - will remove.
security.initialRootPassword = mkOption {
type = types.str;
default = "!";
example = "";
visible = false;
};
}; };
@ -508,7 +518,6 @@ in {
home = "/root"; home = "/root";
shell = mkDefault cfg.defaultUserShell; shell = mkDefault cfg.defaultUserShell;
group = "root"; group = "root";
initialHashedPassword = mkDefault config.security.initialRootPassword;
}; };
nobody = { nobody = {
uid = ids.uids.nobody; uid = ids.uids.nobody;
@ -597,7 +606,7 @@ in {
|| cfg.group == "wheel" || cfg.group == "wheel"
|| elem "wheel" cfg.extraGroups) || elem "wheel" cfg.extraGroups)
&& &&
((cfg.hashedPassword != null && cfg.hashedPassword != "!") (allowsLogin cfg.hashedPassword
|| cfg.password != null || cfg.password != null
|| cfg.passwordFile != null || cfg.passwordFile != null
|| cfg.openssh.authorizedKeys.keys != [] || cfg.openssh.authorizedKeys.keys != []
@ -607,7 +616,17 @@ in {
Neither the root account nor any wheel user has a password or SSH authorized key. 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.''; 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 = warnings =
builtins.filter (x: x != null) ( builtins.filter (x: x != null) (
@ -630,14 +649,13 @@ in {
content = "${base64}${sep}${base64}"; content = "${base64}${sep}${base64}";
mcf = "^${sep}${scheme}${sep}${content}$"; mcf = "^${sep}${scheme}${sep}${content}$";
in in
if (user.hashedPassword != null if (allowsLogin user.hashedPassword
&& user.hashedPassword != "" # login without password
&& builtins.match mcf user.hashedPassword == null) && builtins.match mcf user.hashedPassword == null)
then then ''
''
The password hash of user "${name}" may be invalid. You must set a 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 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 else null
)); ));