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

Parallel or "any" PAM modules #301

Open
X-Ryl669 opened this issue Nov 21, 2020 · 19 comments
Open

Parallel or "any" PAM modules #301

X-Ryl669 opened this issue Nov 21, 2020 · 19 comments

Comments

@X-Ryl669
Copy link

There are more and more module now that "add" confidence to authentication or can even shortcut other methods. I'm talking about fingerprint (with libfprint) or face recognition (with Howdy).
In that use case, one might want to use more than a module to authenticate (and this is currently supported), or use any method to authenticate.
This case is not supported, or badly.
Currently, one has to fail one method to trigger another method.
Would it be possible to run multiple module in parallel and have "any" method succeed ?
For example, either the fingerprint is detected or a password is entered or face recognition succeeded (all at the same time).

@t8m
Copy link
Member

t8m commented Nov 23, 2020

Unfortunately this would require multithreading support. GDM handles this by running multiple pam authentications in parallel with different PAM stack configurations. I am afraid that supporting this properly in libpam would require complete redesign of the stack configuration format.

@X-Ryl669
Copy link
Author

What about a "pam_any" module that would take as parameters, the other module to run in parallel, something like this:
auth sufficient pam_any.so child0=pam_fprint.so child0_arg="whatever fprint needs" child1=pam_howdy.so child1_arg="whatever howdy needs" child2=pam_unix.so child2_arg="nullok_secure"
From the library point of view, it's a single module that either succeed or fails like the other, but inside this parallel module it starts 2 or more thread to run the individual module on their own and join them on first success, or all failure?

@X-Ryl669
Copy link
Author

This triggers a question: is there an official way to stop a PAM item gracefully while it's not finished ?

@boltgolt
Copy link

I've been looking into this issue for years for Howdy and (in my very biased opinion) i think it's a pretty large missing feature. I think the need for for this feature extends to any authentication method that tries to proof user identity with something else than a passcode or pincode. For example, using a YubiKey USB device or voice recognition. Anything that does not use a keyboard for authentication could benefit from allowing a password to be entered at the same time.

Unrelated to the issue, but i also want to thank all of you that maintain PAM. My project would never have been possible if there was no flexible authentication system like PAM

@X-Ryl669
Copy link
Author

X-Ryl669 commented Dec 27, 2020

If using threads is not possible, it could fork and run x processes. In that case, we completely don't care about stopping gracefully in the children. This would be POSIX only.

@musikid
Copy link

musikid commented Jan 18, 2021

Thanks to the experiments of @ccat3z, it seems possible to cancel getting the password (pam_get_authtok()) from another thread. I'm not sure however of the safety of this operation, because I don't find any reference that pam_conv->conv() function is a cancellation point and therefore if the resources are freed correctly.

@JamieKidman
Copy link

JamieKidman commented Oct 2, 2022

RFC86.0 has: Required, Sufficient, and Optional which do not allow for this behaviour.

My use case is M of N so say have 4 auth methods but I only want to have to use 2 and don't care which two.
I have built a solution using optional but according to RFC 2119 Optional means truly optional however RFC86.0 predates that RFC.

You can use the ability to have fail skip, and success run another pam module to store data in either:
Env variable with pam_[put|get}env()
Memory structure with pam
[get|set]_data()
Callback with application (pam_conv(), but I don't think that is write here)
You can also write and read to a file (it is c after all, but probably not great)

auth [success=0 error=1] pam_password.so
auth required pam_set_shared_value.so 1
auth [success=0 error=1] pam_fingerprint.so
auth required pam_set_shared_value.so 1
auth [success=0 error=1] pam_face.so
auth required pam_set_shared_value.so 1
auth required pam_evaluate_shared.so 2

If the final evaluation returns success then the user will be authed.

I think this is not great an would like a key word to allow for failure to not impact auth

@JamieKidman
Copy link

JamieKidman commented Oct 2, 2022

Just a slight correction, the definition in RFC86.0 for optional makes using it in this manner acceptable.

(b) `optional': With this flag, the PAM framework ignores the

@JamieKidman
Copy link

@X-Ryl669 I think that would address your needs still not great but it isnt horrendous?

@gzqx
Copy link

gzqx commented Nov 8, 2022

@X-Ryl669 I think that would address your needs still not great but it isnt horrendous?

I am a bit confused about the description (since it talks nothing about success). I tried this method with howdy (a facial recognition ) and password. It still needs to do howdy first, but yes after it fails it directly goes to password and when using sufficient it tries 3 time as configured in howdy.

I guess it can be taken as a workaround, but it is not different from setting howdy to only try once. I am a bit confused about the point of the option flag.

@X-Ryl669
Copy link
Author

X-Ryl669 commented Nov 8, 2022

Sorry, I gave up using PAM for my needs. Howdy works, but I was more concerned about fprint issues and because of the sequential authentication scheme, it's not usable for me.

I don't know about optional but I'm pretty sure we don't speak about the same thing. I'm not speaking about the requirement of an authentication scheme (where "optional" would be useful), but on the temporal sequence of authentication that, currently, can't happen at the same time.

In practice, even if you have a "optional" fingerprint authentication feature, PAM will execute it and wait for its process to return "true" or "false", before trying the next module. Since each module takes time and you can't start typing your password until the fingerprint has finished, this makes the whole experience miserable and awful. Changing to optional wouldn't change anything here, PAM is basically monothreaded and sequential.

Howdy worked around it by including the password handling in howdy itself, IIUC. But that's a hack IMHO, if each module were to do the same, we wouldn't need PAM at all. This should be a standard PAM feature.

@gzqx
Copy link

gzqx commented Nov 8, 2022

you can't start typing your password until the fingerprint has finished

YMMV, but I kind of foreseen when the fingerprint will not work (e.g. when my finger is wet). In this case, if you set the option flag, you can directly type in password, enter, and then put finger to the module, either it succeeds or not it will directly unlock the computer.

@X-Ryl669
Copy link
Author

X-Ryl669 commented Nov 8, 2022

The simple fact that you have to run the other module is a defect, IMHO.

In a good user experience, you could type your password, press enter and be done. Or you could put your finger on the sensor and be done.

But having to do both actions for every single time you run sudo or login, it's just a PITA. I've disabled it and now I enter my password. The fingerprint sensor is gathering dust and it's a shame since it's not a HW issue, it's just the software stack that's broken.

@JamieKidman
Copy link

@X-Ryl669 I think that would address your needs still not great but it isnt horrendous?

I am a bit confused about the description (since it talks nothing about success). I tried this method with howdy (a facial recognition ) and password. It still needs to do howdy first, but yes after it fails it directly goes to password and when using sufficient it tries 3 time as configured in howdy.

I guess it can be taken as a workaround, but it is not different from setting howdy to only try once. I am a bit confused about the point of the option flag.

@gzqx on success it behaves as other modules, i think the power of that comes from taking advantage of skipping steps
auth [success=0 error=1] pam_password.so
auth required pam_set_shared_value.so 1
auth [success=0 error=1] pam_fingerprint.so
auth required pam_set_shared_value.so 1
auth [success=0 error=1] pam_face.so
auth required pam_set_shared_value.so 1
auth required pam_evaluate_shared.so 2

the success=n and error=n refers to how many stages to skip.

@X-Ryl669
Copy link
Author

X-Ryl669 commented Nov 9, 2022

You could also make a whole custom module that allows for async inside it for face and password etc.

That's what Howdy is doing, IIUC. And it's bad because they only care about password and face login, so their module does this.
They another one might want fingerprint and face, or fingerprint and face and password, or TOTP + password or Yubikey + fingerprint and so on. You see, it's an exponential curve of combination modules to implement. Multiply the number of bugs per the number of combination and you have a security nightmare system.

Why ? because PAM doesn't support running simultaneous module at the same time (I guess it was designed when multitasking was expensive). I agree it wouldn't work if two module needs to access terminal input (like a TOTP and a password at the same time and in that case, some locking should be required to serialize the access), but for the other cases, I don't understand why it would fail.

@ChocolateLoverRaj
Copy link

Has anyone made the pam_any module as described in #301 (comment)?

@ChocolateLoverRaj
Copy link

Btw I created a PAM any module - https://github.com/ChocolateLoverRaj/pam-any. It doesn't do all the PAM stuff but for authenticating it should be able to accept typing a password, howdy, and fingerprint when running sudo.

@Abdillah
Copy link

That's awesome @ChocolateLoverRaj. I don't have the capacity to build one, but thinking that a Rust PAM any module would be cool.

@Alexandero89
Copy link

Btw I created a PAM any module - https://github.com/ChocolateLoverRaj/pam-any. It doesn't do all the PAM stuff but for authenticating it should be able to accept typing a password, howdy, and fingerprint when running sudo.

I was just thinking about writing a Rust PAM module but was not sure if its even possible.
Thanks for your code! Now i know its possible and can have a look how it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants