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;
|
FpDevice *dev;
|
||||||
SessionData *_session;
|
SessionData *_session;
|
||||||
|
|
||||||
|
gboolean local_storage_checked;
|
||||||
|
|
||||||
guint verify_stop_wait_timeout_id;
|
guint verify_stop_wait_timeout_id;
|
||||||
|
|
||||||
PolkitAuthority *auth;
|
PolkitAuthority *auth;
|
||||||
@ -1273,6 +1275,93 @@ report_verify_status (FprintDevice *rdev,
|
|||||||
session->verify_status_reported = TRUE;
|
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
|
static gboolean
|
||||||
can_start_action (FprintDevice *rdev, GError **error)
|
can_start_action (FprintDevice *rdev, GError **error)
|
||||||
{
|
{
|
||||||
@ -1489,6 +1578,8 @@ verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
error->message);
|
error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_local_storage (rdev, match, error);
|
||||||
|
|
||||||
stoppable_action_completed (rdev);
|
stoppable_action_completed (rdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1532,6 +1623,8 @@ identify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
error->message);
|
error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_local_storage (rdev, match != NULL, error);
|
||||||
|
|
||||||
stoppable_action_completed (rdev);
|
stoppable_action_completed (rdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1086,6 +1086,51 @@ class FPrintdVirtualStorageDeviceTests(FPrintdVirtualStorageDeviceBaseTest):
|
|||||||
prints = self.get_stored_prints()
|
prints = self.get_stored_prints()
|
||||||
self.assertEqual(set(prints), set(garbage_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):
|
def test_enroll_with_one_stage_only(self):
|
||||||
self._maybe_reduce_enroll_stages(stages=1)
|
self._maybe_reduce_enroll_stages(stages=1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user