Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/users-groups: do not check validity of special hashes #91238

Merged
merged 5 commits into from Jul 7, 2020

Conversation

rnhmjoj
Copy link
Contributor

@rnhmjoj rnhmjoj commented Jun 21, 2020

Motivation for this change

Fixup of PR #83171

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS)
  • Built manual
  • Tested via one or more NixOS test(s): `nixosTests.mutableUsers``
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

cc @tilpner @erictapen

[ "users" "users" "root" "initialHashedPassword" ]
(cfg: if cfg.security.initialHashedPassword == "!"
then null
else cfg.security.initialHashedPassword))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that the change is backwards-compatible with people setting security.initialRootPassword, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is. Also this option has been hidden since 2014, so the impact should be small.

@@ -588,7 +593,7 @@ in {
|| cfg.group == "wheel"
|| elem "wheel" cfg.extraGroups)
&&
((cfg.hashedPassword != null && cfg.hashedPassword != "!")
(cfg.hashedPassword != null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m super uncomfortable with this line, somebody else will have to confirm that it’s valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two possible cases I can think of:

  • using the deprecated security.initialRootPassword "!" will be turned into a null, so it's covered
  • using users.users.<name>.hashedPassword or similar, "!" will issue the warning about possibly being locked out.

But yes, it would be better is someone familiar with this module would comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks to me like @edolstra is the only one who touched this code in the past.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, user using users.users.<name>.hashedPassword that is not a hash will lock themselves out if they miss the warning so the assertion still makes sense. It is even too narrow here – I use * as a root’s hash and this would not save me. Not sure we can extend it much further without causing false positives, though.

Copy link
Contributor

@jtojnar jtojnar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We should definitely add an assertion that hashedPassword cannot contain : since that will definitely break the shadowfile as reported in Enforce no ":" in "hashedPassword" (perhaps a check) #12008
  2. There are other commonly used schemes for hashedPassword. Personally, I set it to * for root, since hash prefixed with ! means the account is locked according to shadow(5). Different systems might support special sequences with even wilder semantics like !! or *NS* https://unix.stackexchange.com/questions/252016/difference-between-vs-vs-in-etc-shadow

@@ -588,7 +593,7 @@ in {
|| cfg.group == "wheel"
|| elem "wheel" cfg.extraGroups)
&&
((cfg.hashedPassword != null && cfg.hashedPassword != "!")
(cfg.hashedPassword != null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, user using users.users.<name>.hashedPassword that is not a hash will lock themselves out if they miss the warning so the assertion still makes sense. It is even too narrow here – I use * as a root’s hash and this would not save me. Not sure we can extend it much further without causing false positives, though.

@rnhmjoj
Copy link
Contributor Author

rnhmjoj commented Jun 23, 2020

There are other commonly used schemes for hashedPassword. Personally, I set it to * for root, since hash prefixed with ! means the account is locked according to shadow(5). Different systems might support special sequences with even wilder semantics like !! or NS

What is the point of setting the hash to "!" when null is the default (and the update-users-groups.pl script locks users with "!" when the hash is null)? It's not a rhetoric question, I'm honestly asking.

If these special hashes are common I'll add exceptions, but to me it feel like an implementation detail that shouldn't leak to the NixOS configuration: the options users.users don't mention /etc/shadow anywhere.

@jtojnar
Copy link
Contributor

jtojnar commented Jun 23, 2020

What is the point of setting the hash to "!" when null is the default (and the update-users-groups.pl script locks users with "!" when the hash is null)? It's not a rhetoric question, I'm honestly asking.

I did not know that before reviewing the code. I would expect null to map to empty string (i.e. no password) so I set the hash to *. Also reading the shadow(5), using * makes more sense to me than !.

If these special hashes are common I'll add exceptions, but to me it feel like an implementation detail that shouldn't leak to the NixOS configuration: the options users.users don't mention /etc/shadow anywhere.

Yeah, this it a personal preference. Sometimes I like it when NixOS modules map directly to UNIX concepts and do not add much special logic. Especially, if I was familiar with the config before switching to NixOS.

@rnhmjoj
Copy link
Contributor Author

rnhmjoj commented Jun 25, 2020

I added a check for "!", "!!" and "*" in the assertion and the warning as you requested.
I also added another assertion for avoiding ":"s in the password hash, since these are guaranteed to break havoc.
The main concerns should be answered.

nixos/modules/config/users-groups.nix Outdated Show resolved Hide resolved
nixos/modules/config/users-groups.nix Outdated Show resolved Hide resolved
Copy link
Member

@Profpatsch Profpatsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can see, this is fine now

@DIzFer
Copy link
Contributor

DIzFer commented Jul 3, 2020

I seem to not understand what this PR is achieving on my system: I'm now getting the intended warning for a hashedPassword == "!"... which is exactly what I expect users.users.root.hashedPasswords to be. Am I expected (and doomed) to ignore a warning on every rebuild until the end of times?

@rnhmjoj
Copy link
Contributor Author

rnhmjoj commented Jul 3, 2020

No, you're not supposed to get that warning and this PR will fix it. The warning is intended to check valid hashes but in the original PR (#83171) I missed the edge cases of "!", "*" and others.

@nh2
Copy link
Contributor

nh2 commented Jul 3, 2020

Confirming that commit 470ce47 triggers a spurious warning, e.g. for users.extraUsers.root.password = ""; or users.extraUsers.root.password = "a"; (i came here via bisection of it).

@rnhmjoj
Copy link
Contributor Author

rnhmjoj commented Jul 4, 2020

@nh2 Note that It's not root.password, which is never checked, but root.initialHashedPassword set to "!".

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`.
This explanation was contained in the description of
security.initialRootPassword but got lost when it was deprecated
a long ago (f496c3c) and removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants