mirror of
https://gitlab.com/mishakmak/pam-fprint-grosshack.git
synced 2026-04-08 20:03:34 +02:00
device: Remove local storage prints if they've been removed from device
If a print we have stored locally is not available in device anymore, we need to cleanup the local database. We do not get a proper DATA_NOT_FOUND error for most devices (indeed, at this point no device does this properly). As such, do this when we see a DATA_NOT_FOUND error and the first time that we get a verify-no-match results on a device which is capable of listing all known prints. Co-Authored-by: Marco Trevisan (Treviño) <mail@3v1n0.net>
This commit is contained in:
93
src/device.c
93
src/device.c
@ -101,6 +101,8 @@ typedef struct
|
||||
FpDevice *dev;
|
||||
SessionData *_session;
|
||||
|
||||
gboolean local_storage_checked;
|
||||
|
||||
guint verify_stop_wait_timeout_id;
|
||||
|
||||
PolkitAuthority *auth;
|
||||
@ -1273,6 +1275,93 @@ report_verify_status (FprintDevice *rdev,
|
||||
session->verify_status_reported = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
check_local_storage (FprintDevice *rdev,
|
||||
gboolean found_match,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GError) err = NULL;
|
||||
g_autoptr(GPtrArray) device_prints = NULL;
|
||||
g_autoptr(GPtrArray) host_prints = NULL;
|
||||
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
||||
unsigned i;
|
||||
|
||||
g_return_if_fail (priv->current_action == ACTION_VERIFY ||
|
||||
priv->current_action == ACTION_IDENTIFY);
|
||||
|
||||
/* This only ever sense if the device can list prints. */
|
||||
if (!fp_device_has_feature (priv->dev, FP_DEVICE_FEATURE_STORAGE_LIST))
|
||||
return;
|
||||
|
||||
/* We do not have any proper driver that correctly reports DATA_NOT_FOUND
|
||||
* errors. Only synaptics, but there the feature is being disabled on the
|
||||
* firmware side.
|
||||
* As such, just always run a test the first time we get a match failure.
|
||||
*/
|
||||
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_NOT_FOUND))
|
||||
{
|
||||
if (priv->local_storage_checked)
|
||||
g_warning ("Device %s reported that a passed print did not exist during action %d, but we verified the local storage!",
|
||||
fp_device_get_name (priv->dev), priv->current_action);
|
||||
else
|
||||
g_debug ("Device %s reported that a passed print did not exist during action %d",
|
||||
fp_device_get_name (priv->dev), priv->current_action);
|
||||
}
|
||||
else if (error || priv->local_storage_checked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (!found_match)
|
||||
{
|
||||
g_debug ("Device %s failed to match during action %d, verifying local storage",
|
||||
fp_device_get_name (priv->dev), priv->current_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
priv->local_storage_checked = TRUE;
|
||||
|
||||
device_prints = fp_device_list_prints_sync (priv->dev, NULL, &err);
|
||||
if (!device_prints)
|
||||
{
|
||||
g_warning ("Failed to query prints: %s", err->message);
|
||||
return;
|
||||
}
|
||||
|
||||
host_prints = load_all_prints (rdev);
|
||||
|
||||
for (i = 0; i < host_prints->len; i++)
|
||||
{
|
||||
FpPrint *print = g_ptr_array_index (host_prints, i);
|
||||
int r;
|
||||
|
||||
if (g_ptr_array_find_with_equal_func (device_prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
NULL))
|
||||
continue;
|
||||
|
||||
/* Print not known by device, remove locally */
|
||||
if ((r = store.print_data_delete (priv->dev,
|
||||
fp_print_get_finger (print),
|
||||
fp_print_get_username (print))) == 0)
|
||||
{
|
||||
g_message ("Deleted stored finger %d for user %s as it is unknown to device.",
|
||||
fp_print_get_finger (print),
|
||||
fp_print_get_username (print));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Error deleting finger %d for user %s that is unknown to device: %d!",
|
||||
fp_print_get_finger (print),
|
||||
fp_print_get_username (print),
|
||||
r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
can_start_action (FprintDevice *rdev, GError **error)
|
||||
{
|
||||
@ -1489,6 +1578,8 @@ verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
error->message);
|
||||
}
|
||||
|
||||
check_local_storage (rdev, match, error);
|
||||
|
||||
stoppable_action_completed (rdev);
|
||||
}
|
||||
}
|
||||
@ -1532,6 +1623,8 @@ identify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
error->message);
|
||||
}
|
||||
|
||||
check_local_storage (rdev, match != NULL, error);
|
||||
|
||||
stoppable_action_completed (rdev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1086,6 +1086,51 @@ class FPrintdVirtualStorageDeviceTests(FPrintdVirtualStorageDeviceBaseTest):
|
||||
prints = self.get_stored_prints()
|
||||
self.assertEqual(set(prints), set(garbage_prints))
|
||||
|
||||
def test_local_storage_cleanup_data_error(self):
|
||||
# Enroll a print and delete it
|
||||
self.enroll_print('deleted-print', finger='left-thumb')
|
||||
self.send_command('REMOVE', 'deleted-print')
|
||||
|
||||
# Note: would be thrown anyway by the storage device if we scan something
|
||||
self.send_error(FPrint.DeviceError.DATA_NOT_FOUND)
|
||||
self.device.VerifyStart('(s)', 'any')
|
||||
|
||||
self.wait_for_result('verify-no-match')
|
||||
self.device.VerifyStop()
|
||||
|
||||
# At this point, there is no print left
|
||||
with self.assertFprintError('NoEnrolledPrints'):
|
||||
self.device.ListEnrolledFingers('(s)', 'testuser')
|
||||
|
||||
def test_local_storage_cleanup_no_match(self):
|
||||
# Enroll a print and delete it
|
||||
self.enroll_print('existing-print', finger='right-index-finger')
|
||||
self.enroll_print('deleted-print', finger='left-thumb')
|
||||
self.send_command('REMOVE', 'deleted-print')
|
||||
|
||||
# We need to send a print that is known to the device
|
||||
self.send_image('other-print')
|
||||
self.device.VerifyStart('(s)', 'right-index-finger')
|
||||
|
||||
self.wait_for_result('verify-no-match')
|
||||
self.device.VerifyStop()
|
||||
|
||||
# At this point, the deleted print has disappeared
|
||||
self.assertEqual(set(self.device.ListEnrolledFingers('(s)', 'testuser')), {'right-index-finger'})
|
||||
|
||||
# Now, do the same thing, and the print will not be deleted
|
||||
self.enroll_print('deleted-print', finger='left-thumb')
|
||||
self.send_command('REMOVE', 'deleted-print')
|
||||
|
||||
self.send_image('other-print')
|
||||
self.device.VerifyStart('(s)', 'right-index-finger')
|
||||
|
||||
self.wait_for_result('verify-no-match')
|
||||
self.device.VerifyStop()
|
||||
|
||||
# At this point, the deleted print is still there
|
||||
self.assertEqual(set(self.device.ListEnrolledFingers('(s)', 'testuser')), {'right-index-finger', 'left-thumb'})
|
||||
|
||||
def test_enroll_with_one_stage_only(self):
|
||||
self._maybe_reduce_enroll_stages(stages=1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user