-
-
Notifications
You must be signed in to change notification settings - Fork 59
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
Add password hash authentication #573
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- what does libgcrypt offer over libcrypto?
- is there not a C++ library?
Hyprlock currently uses neither and I have just picked one of the two. Libgcrypt is much smaller and simpler than libcrypto as a whole. Although, mere one-off digest creation and checking looks quite similar in both. I knrew how to do it in libgcrypt. So I used it.
I don't know of any famous and battle-proven library. Do you? So I stayed on the safe side. As the task is a purely functional "take this data, compute the digest and compare it to this other digest", there is no inherent value in a library with an object model. There is no state-transfer into libgcrypt which could collide with the C++ object model. |
I just am not a fan of |
#define NEED_LIBGCRYPT_VERSION nullptr | ||
#include <gcrypt.h> | ||
|
||
using namespace std::chrono_literals; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ew
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I have no strong feelings about this, but what is to be had against readable literals? Is it just a too un-C++ thing to do? I will gladly change it back, if you want me to.
src/core/PwAuth.cpp
Outdated
using namespace std::chrono_literals; | ||
|
||
static auto hex2Bytes(const std::string& hex) -> std::unique_ptr<unsigned char[]> { | ||
auto bytes = std::make_unique<unsigned char[]>(hex.length() / 2u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what the actual fuck? std::vector??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry? I just need a unique_ptr to some fixed buffer, here (for automatic deletion after the hash generation). How would you recommend doing that with std::vector
(or, rather std::array
)?
src/core/PwAuth.hpp
Outdated
bool m_bBlockInput = true; | ||
bool m_bAuthenticated = false; | ||
bool m_bLibFailed = false; | ||
std::unique_ptr<unsigned char[]> m_sHash; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again wtf?
I think pam is fundamentally broken, so I am not entirely opposed to a custom Auth method. Two security relevant things.
|
} | ||
} else { | ||
Debug::log(CRIT, "libgcrypt could not be initialized"); | ||
m_bLibFailed = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just crash? Maybe with a RASSERT
or something. Without a crash you won't be able to log in, so I think that would make more sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This happens during initialisation. You want the locker to lock up your system, because of an error that is outside of the user's realm of influence? Was thinking that the locker should rather not lock the system if it knows beforehand that it cannot reliably unlock afterwards.
In the end this is your decision to make. I just wanted to bring this up as a counter argument, as I have thought about this as well and came to the opposite conclusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't crash we lock up the system, but silently.
If we crash we lock up the system in a more obvious way.
So the decision is to make it crash :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I programmed it now is to not lock up the system at all but immediately return. Hyprlock has not yet told the Compositor to lock the system.
EDIT: In line 161 in auth()
you can see that it immediately returns authenticated (and subsequently unlocks) if m_bLibFailed
is true.
I make it crash if you want, but your statement about the current silent lock is not correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the perspective of the application, every case of m_bLibFailed = true
looks identical. So, I would crash the application in all cases, then, not just when the library fails to initialise.
Is that not true for PAM as well? So, it should be some general artificial delay between login tries, not just for this method.
Well, I don't believe in security by obscurity. The strength of the hash is usually as good as any public key. If you entrust public keys to the public, you can as well with the hash. I know, though, that other people think different about this and leave this for you to decide. |
What I just wrote is, of course, not equally true, for hashes that are used without salt. |
All PAM login configurations i came across have such a delay.
No!! Password hashes need to be treated with care. Especially if the salt is also stored in the same file. You are right that having the password hash leaked to another user does not straight up mean they can login. But with enough time you might be able to find the password (for example, if the password is in rockyou.txt and you know the salt, it is game over). Finding a private key for a corresponding public key is MUCH harder than finding the plaintext for a certain hash. For that your security is only the plaintext length. |
963382e
to
2ee663b
Compare
Yeah, so I would just implement that near
You are right! So, it must be a read-restricted file. |
As an alternative to PAM authentication, password hash authentication only relies on the availability of libgcrypt (and some program like OpenSSL or sha256sum to create the hash). Supports salted hashes and all hash algorithms that are available in the actual libgcrypt installation.
As an alternative to PAM authentication, password hash authentication only relies on the availability of libgcrypt (and some program like OpenSSL or sha256sum to create the hash).
Supports salted hashes and all hash algorithms that are available in the actual libgcrypt installation.
This is practical in more restricted environments. As an example: I work on a Ubuntu machine w/o root privileges and use Hyprland via Nix Home Manager. Ubuntu uses a patched PAM library to support their own
@include
primitive which is incompatible with standard PAM. Additionallydlopen
across PAM library version does not work well from 1.6 to 1.5.I am aware that the documentation likely has to move from the README to the Wiki, but I put it there for easy initial review.