We have a condition where a client vanishing instead of cleaning up the
operation using VerifyStop would cause fprintd to hang. This only
happens if the underlying enroll/verify/identify operation has already
finished when the client vanishes.
Fix this by correctly interpreting current_cancellable as a flag for
these operations.
Fixes: #97
This is useful in the functions where we have to unset the device's
current action but we may use early-return to handle multiple conditions
such as in open, close and delete functions.
The latest also currently is a bit buggy as it won't reset the state on
some failures.
In the usual test we cancel the operation immediately by calling
VerifyStop. This (often) tests the case where we don't end up restarting
the Verify operation internally.
We can easily force fprintd to have restarted already internally, so add
a test that does so by sleeping a bit. This should give us a slightly
higher branch coverage in the verify_cb/identify_cb tests.
It seems that GLib may process multiple DBus signals in one mainloop
iteration. This could cause messages to be re-ordered, which in turn
caused a race condition in the CI that could trigger random failures.
We must ignore NameOwnerChanged that happen due to automatic startup.
The easy way to do so is to just register it only when we get to the
point that a name owner change has security implications.
While add it, change it to always log at a warning level.
Fixes: #94
We already use FpFinger for storage operations and prints management,
but internally we keep still using the old finger number, that uses
different values for invalid data.
Let's be consistent, and always use FpFinger everywhere.
Implement simple auto-pointers for the types we use in pam_fprintd with
a basic implementation based on GLib one so that we can have the same
features without having neither an header-dependency on it.
If fprintd disappears or is replaced, then we might be getting signals
from another daemon/verifcation session.
As such we must give up at that point.
Related: #47
We had a race that was causing the events to be handled even if we were
not ready to accept them, causing a potential non-authentication.
So simulate this case, by sending a 'verify-match' event before we
started the verification and ensure that we ignore it.
In case fprintd is emitting a verify signal for another request that is
still going on while we're about to start a new verification, we'd just
accept such signal, so potentially allowing a log-in because another
concurrent request succeeded.
To avoid this, use async call to VerifyStart and open a verify window
(during which we accept the verification related signals) that is kept
open just once the VerifyStart call has been completed and before
stopping the verification again. As that's the only moment in which we
can be sure that we've control of the daemon events for such device.
Thanks to Benjamin to find out the race.
Fixes: #47
This is both in case in we start the authentication and in the absurd
but (hey, testing!) situation in which prints gets deleted in between
the device claiming and the verification start.
To handle this second scenario we need to instruct fprintd mock to raise
an error on some special command
This now allows:
* Sending signals before and after method return
* Exiting the daemon
* Emulating NoEnrolledPrints DBus method error
Co-authored-by: Benjamin Berg <bberg@redhat.com>
The verify script would start an async routine. However, this blocks the
dbus return, which really is needed.
Also, we should only return one item of the script for each VerifyStart
run. So, fix things by pop'ing the first item and putting it on the bus
from a GLib.add_timeout handler.
Signals like VerifyResult may be received from unrelated Verify
operations. To avoid races, we need to ignore any VerifyResult that
happenes before the DBus method returns.
The only way to do this race-free is to use the async version of the
VerifyStart method.
In order to be race free, clients need to ignore all signals until after
the DBus method to start verification has returned. So the signal must
be emitted later than it currently is.
If someone has started an operation, then we don't really need to
confirm they are permitted to stop it again. Not doing this has the
advantage that we cannot run into a second interactive authorization
step accidentally.
Delete needs to operate on the device, so no other actions are permitted
at the same time. And using the libfprint _sync methods does not
guard against reentrance.