mirror of
https://gitlab.com/mishakmak/pam-fprint-grosshack.git
synced 2026-04-09 12:23:34 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da60bddb3e | |||
| 506d99e90c | |||
| e7f47e28d7 | |||
| 938c1aac5a | |||
| fd02922608 | |||
| 195f7eaf5f | |||
| 48ea3b89c9 | |||
| 4cfa6b5b37 | |||
| c685f0d34c | |||
| eece834231 | |||
| 3faaa81257 | |||
| b9cdb58a1a | |||
| ab8dcfaa61 | |||
| 25a97c8276 | |||
| 8057e49d31 | |||
| f75e800d5c | |||
| 6ae4f5e939 | |||
| 7c9a04c2ae | |||
| 7b7aa6e99d | |||
| b624f8c8c7 | |||
| 3e81179eca | |||
| c6647ba875 | |||
| 988ee01f66 | |||
| 32ee94c8a0 |
8
NEWS
8
NEWS
@ -1,6 +1,14 @@
|
|||||||
This file lists notable changes in each release. For the full history of all
|
This file lists notable changes in each release. For the full history of all
|
||||||
changes, see ChangeLog.
|
changes, see ChangeLog.
|
||||||
|
|
||||||
|
Version 1.90.9:
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
- Fix multiple daemon lockup issues (#97)
|
||||||
|
- Fix print garbage collection to not delete used prints
|
||||||
|
- pam: Use the device with the most prints
|
||||||
|
|
||||||
|
|
||||||
Version 1.90.8:
|
Version 1.90.8:
|
||||||
|
|
||||||
It seems that we are finally reaching the end of the tunnel with regard
|
It seems that we are finally reaching the end of the tunnel with regard
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
project('fprintd', 'c',
|
project('fprintd', 'c',
|
||||||
version: '1.90.8',
|
version: '1.90.9',
|
||||||
license: 'GPLv2+',
|
license: 'GPLv2+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
|
|||||||
@ -60,6 +60,11 @@ static unsigned timeout = DEFAULT_TIMEOUT;
|
|||||||
#define USEC_PER_SEC ((uint64_t) 1000000ULL)
|
#define USEC_PER_SEC ((uint64_t) 1000000ULL)
|
||||||
#define NSEC_PER_USEC ((uint64_t) 1000ULL)
|
#define NSEC_PER_USEC ((uint64_t) 1000ULL)
|
||||||
|
|
||||||
|
static size_t user_enrolled_prints_num (pam_handle_t *pamh,
|
||||||
|
sd_bus *bus,
|
||||||
|
const char *dev,
|
||||||
|
const char *username);
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
now (void)
|
now (void)
|
||||||
{
|
{
|
||||||
@ -112,11 +117,13 @@ send_err_msg (pam_handle_t *pamh, const char *msg)
|
|||||||
static char *
|
static char *
|
||||||
open_device (pam_handle_t *pamh,
|
open_device (pam_handle_t *pamh,
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
|
const char *username,
|
||||||
bool *has_multiple_devices)
|
bool *has_multiple_devices)
|
||||||
{
|
{
|
||||||
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
||||||
pf_autoptr (sd_bus_message) m = NULL;
|
pf_autoptr (sd_bus_message) m = NULL;
|
||||||
size_t num_devices;
|
size_t num_devices;
|
||||||
|
size_t max_prints;
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
const char *s;
|
const char *s;
|
||||||
int r;
|
int r;
|
||||||
@ -143,12 +150,23 @@ open_device (pam_handle_t *pamh,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd_bus_message_read_basic (m, 'o', &path) < 0)
|
num_devices = 0;
|
||||||
return NULL;
|
max_prints = 0;
|
||||||
|
|
||||||
num_devices = 1;
|
|
||||||
while ((r = sd_bus_message_read_basic (m, 'o', &s)) > 0)
|
while ((r = sd_bus_message_read_basic (m, 'o', &s)) > 0)
|
||||||
num_devices++;
|
{
|
||||||
|
size_t enrolled_prints = user_enrolled_prints_num (pamh, bus, s, username);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
pam_syslog (pamh, LOG_DEBUG, "%s prints registered: %" PRIu64, s, enrolled_prints);
|
||||||
|
|
||||||
|
if (enrolled_prints > max_prints)
|
||||||
|
{
|
||||||
|
max_prints = enrolled_prints;
|
||||||
|
path = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_devices++;
|
||||||
|
}
|
||||||
*has_multiple_devices = (num_devices > 1);
|
*has_multiple_devices = (num_devices > 1);
|
||||||
if (debug)
|
if (debug)
|
||||||
pam_syslog (pamh, LOG_DEBUG, "Using device %s (out of %ld devices)", path, num_devices);
|
pam_syslog (pamh, LOG_DEBUG, "Using device %s (out of %ld devices)", path, num_devices);
|
||||||
@ -528,11 +546,11 @@ do_verify (sd_bus *bus,
|
|||||||
return PAM_AUTH_ERR;
|
return PAM_AUTH_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static size_t
|
||||||
user_has_prints (pam_handle_t *pamh,
|
user_enrolled_prints_num (pam_handle_t *pamh,
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
const char *dev,
|
const char *dev,
|
||||||
const char *username)
|
const char *username)
|
||||||
{
|
{
|
||||||
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
||||||
pf_autoptr (sd_bus_message) m = NULL;
|
pf_autoptr (sd_bus_message) m = NULL;
|
||||||
@ -557,21 +575,21 @@ user_has_prints (pam_handle_t *pamh,
|
|||||||
if (debug)
|
if (debug)
|
||||||
pam_syslog (pamh, LOG_DEBUG, "ListEnrolledFingers failed for %s: %s",
|
pam_syslog (pamh, LOG_DEBUG, "ListEnrolledFingers failed for %s: %s",
|
||||||
username, error.message);
|
username, error.message);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_message_enter_container (m, 'a', "s");
|
r = sd_bus_message_enter_container (m, 'a', "s");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
pam_syslog (pamh, LOG_ERR, "Failed to parse answer from ListEnrolledFingers(): %d", r);
|
pam_syslog (pamh, LOG_ERR, "Failed to parse answer from ListEnrolledFingers(): %d", r);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((r = sd_bus_message_read_basic (m, 's', &s)) > 0)
|
while ((r = sd_bus_message_read_basic (m, 's', &s)) > 0)
|
||||||
num_fingers++;
|
num_fingers++;
|
||||||
sd_bus_message_exit_container (m);
|
sd_bus_message_exit_container (m);
|
||||||
|
|
||||||
return num_fingers > 0;
|
return num_fingers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -651,8 +669,6 @@ name_owner_changed (sd_bus_message *m,
|
|||||||
static int
|
static int
|
||||||
do_auth (pam_handle_t *pamh, const char *username)
|
do_auth (pam_handle_t *pamh, const char *username)
|
||||||
{
|
{
|
||||||
bool have_prints;
|
|
||||||
|
|
||||||
pf_autoptr (verify_data) data = NULL;
|
pf_autoptr (verify_data) data = NULL;
|
||||||
pf_autoptr (sd_bus) bus = NULL;
|
pf_autoptr (sd_bus) bus = NULL;
|
||||||
pf_autoptr (sd_bus_slot) name_owner_changed_slot = NULL;
|
pf_autoptr (sd_bus_slot) name_owner_changed_slot = NULL;
|
||||||
@ -667,17 +683,10 @@ do_auth (pam_handle_t *pamh, const char *username)
|
|||||||
return PAM_AUTHINFO_UNAVAIL;
|
return PAM_AUTHINFO_UNAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->dev = open_device (pamh, bus, &data->has_multiple_devices);
|
data->dev = open_device (pamh, bus, username, &data->has_multiple_devices);
|
||||||
if (data->dev == NULL)
|
if (data->dev == NULL)
|
||||||
return PAM_AUTHINFO_UNAVAIL;
|
return PAM_AUTHINFO_UNAVAIL;
|
||||||
|
|
||||||
have_prints = user_has_prints (pamh, bus, data->dev, username);
|
|
||||||
if (debug)
|
|
||||||
pam_syslog (pamh, LOG_DEBUG, "prints registered: %s\n", have_prints ? "yes" : "no");
|
|
||||||
|
|
||||||
if (!have_prints)
|
|
||||||
return PAM_AUTHINFO_UNAVAIL;
|
|
||||||
|
|
||||||
/* Only connect to NameOwnerChanged when needed. In case of automatic startup
|
/* Only connect to NameOwnerChanged when needed. In case of automatic startup
|
||||||
* we rely on the fact that we never see those signals.
|
* we rely on the fact that we never see those signals.
|
||||||
*/
|
*/
|
||||||
|
|||||||
150
src/device.c
150
src/device.c
@ -210,6 +210,16 @@ session_data_set_new (FprintDevicePrivate *priv, gchar *sender, gchar *username)
|
|||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef FprintDevice FprintDeviceActionUnset;
|
||||||
|
static void
|
||||||
|
auto_device_action_unset (FprintDeviceActionUnset *self)
|
||||||
|
{
|
||||||
|
FprintDevicePrivate *priv = fprint_device_get_instance_private (self);
|
||||||
|
|
||||||
|
priv->current_action = ACTION_NONE;
|
||||||
|
}
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FprintDeviceActionUnset, auto_device_action_unset);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fprint_device_dispose (GObject *object)
|
fprint_device_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@ -739,7 +749,7 @@ _fprint_device_check_for_username (FprintDevice *rdev,
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL,
|
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL,
|
||||||
"Could not get conection unix user ID: %s",
|
"Could not get connection unix user ID: %s",
|
||||||
local_error->message);
|
local_error->message);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -784,15 +794,30 @@ _fprint_device_client_vanished (GDBusConnection *connection,
|
|||||||
if (session != NULL &&
|
if (session != NULL &&
|
||||||
g_strcmp0 (session->sender, name) == 0)
|
g_strcmp0 (session->sender, name) == 0)
|
||||||
{
|
{
|
||||||
while (priv->current_action != ACTION_NONE)
|
g_cancellable_cancel (priv->current_cancellable);
|
||||||
{
|
|
||||||
/* OPEN/CLOSE are not cancellable, we just need to wait */
|
|
||||||
if (priv->current_cancellable)
|
|
||||||
g_cancellable_cancel (priv->current_cancellable);
|
|
||||||
|
|
||||||
g_main_context_iteration (NULL, TRUE);
|
if (!priv->current_cancellable)
|
||||||
|
{
|
||||||
|
/* This isn't optimal, but for verify/identify/enroll we expect the stop
|
||||||
|
* command. And we use current_cancellable as a flag to know that the
|
||||||
|
* underlying operation has finished already.
|
||||||
|
* If it has finished, unset the current_action. */
|
||||||
|
switch (priv->current_action)
|
||||||
|
{
|
||||||
|
case ACTION_VERIFY:
|
||||||
|
case ACTION_IDENTIFY:
|
||||||
|
case ACTION_ENROLL:
|
||||||
|
priv->current_action = ACTION_NONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (priv->current_action != ACTION_NONE)
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
|
||||||
/* The session may have disappeared at this point if the device
|
/* The session may have disappeared at this point if the device
|
||||||
* was already closing. */
|
* was already closing. */
|
||||||
g_clear_pointer (&session, session_data_unref);
|
g_clear_pointer (&session, session_data_unref);
|
||||||
@ -838,11 +863,12 @@ dev_open_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
|
|
||||||
g_autoptr(SessionData) session = NULL;
|
g_autoptr(SessionData) session = NULL;
|
||||||
g_autoptr(GDBusMethodInvocation) invocation = NULL;
|
g_autoptr(GDBusMethodInvocation) invocation = NULL;
|
||||||
|
g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
|
||||||
|
|
||||||
|
action_unset = rdev;
|
||||||
session = session_data_get (priv);
|
session = session_data_get (priv);
|
||||||
invocation = g_steal_pointer (&session->invocation);
|
invocation = g_steal_pointer (&session->invocation);
|
||||||
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
if (!fp_device_open_finish (dev, res, &error))
|
if (!fp_device_open_finish (dev, res, &error))
|
||||||
{
|
{
|
||||||
g_autoptr(GError) dbus_error = NULL;
|
g_autoptr(GError) dbus_error = NULL;
|
||||||
@ -939,12 +965,13 @@ dev_close_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
|
|
||||||
g_autoptr(SessionData) session = NULL;
|
g_autoptr(SessionData) session = NULL;
|
||||||
g_autoptr(GDBusMethodInvocation) invocation = NULL;
|
g_autoptr(GDBusMethodInvocation) invocation = NULL;
|
||||||
|
g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
|
||||||
|
|
||||||
session = session_data_get (priv);
|
session = session_data_get (priv);
|
||||||
session_data_set_new (priv, NULL, NULL);
|
session_data_set_new (priv, NULL, NULL);
|
||||||
invocation = g_steal_pointer (&session->invocation);
|
invocation = g_steal_pointer (&session->invocation);
|
||||||
|
action_unset = rdev;
|
||||||
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
if (!fp_device_close_finish (dev, res, &error))
|
if (!fp_device_close_finish (dev, res, &error))
|
||||||
{
|
{
|
||||||
g_autoptr(GError) dbus_error = NULL;
|
g_autoptr(GError) dbus_error = NULL;
|
||||||
@ -1052,7 +1079,7 @@ can_start_action (FprintDevice *rdev, GError **error)
|
|||||||
case ACTION_VERIFY:
|
case ACTION_VERIFY:
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
|
FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
|
||||||
"Enrollment already in progress");
|
"Verification already in progress");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_OPEN:
|
case ACTION_OPEN:
|
||||||
@ -1083,6 +1110,47 @@ can_start_action (FprintDevice *rdev, GError **error)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stoppable_action_completed (FprintDevice *rdev)
|
||||||
|
{
|
||||||
|
g_autoptr(SessionData) session = NULL;
|
||||||
|
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
||||||
|
FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
|
||||||
|
|
||||||
|
session = session_data_get (priv);
|
||||||
|
|
||||||
|
/* Return the cancellation or reset action right away if vanished. */
|
||||||
|
if (priv->current_cancel_invocation)
|
||||||
|
{
|
||||||
|
switch (priv->current_action)
|
||||||
|
{
|
||||||
|
case ACTION_VERIFY:
|
||||||
|
case ACTION_IDENTIFY:
|
||||||
|
fprint_dbus_device_complete_verify_stop (dbus_dev,
|
||||||
|
g_steal_pointer (&priv->current_cancel_invocation));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION_ENROLL:
|
||||||
|
fprint_dbus_device_complete_enroll_stop (dbus_dev,
|
||||||
|
g_steal_pointer (&priv->current_cancel_invocation));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->current_action = ACTION_NONE;
|
||||||
|
session->verify_status_reported = FALSE;
|
||||||
|
}
|
||||||
|
else if (g_cancellable_is_cancelled (priv->current_cancellable))
|
||||||
|
{
|
||||||
|
priv->current_action = ACTION_NONE;
|
||||||
|
session->verify_status_reported = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&priv->current_cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
match_cb (FpDevice *device,
|
match_cb (FpDevice *device,
|
||||||
FpPrint *match,
|
FpPrint *match,
|
||||||
@ -1109,10 +1177,8 @@ static void
|
|||||||
verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autoptr(SessionData) session = NULL;
|
|
||||||
FprintDevice *rdev = user_data;
|
FprintDevice *rdev = user_data;
|
||||||
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
||||||
FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
|
|
||||||
gboolean success;
|
gboolean success;
|
||||||
const char *name;
|
const char *name;
|
||||||
gboolean match;
|
gboolean match;
|
||||||
@ -1121,8 +1187,6 @@ verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
g_assert (!!success == !error);
|
g_assert (!!success == !error);
|
||||||
name = verify_result_to_name (match, error);
|
name = verify_result_to_name (match, error);
|
||||||
|
|
||||||
session = session_data_get (priv);
|
|
||||||
|
|
||||||
g_debug ("verify_cb: result %s", name);
|
g_debug ("verify_cb: result %s", name);
|
||||||
|
|
||||||
/* Automatically restart the operation for retry failures */
|
/* Automatically restart the operation for retry failures */
|
||||||
@ -1148,21 +1212,7 @@ verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
error->message);
|
error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the cancellation or reset action right away if vanished. */
|
stoppable_action_completed (rdev);
|
||||||
if (priv->current_cancel_invocation)
|
|
||||||
{
|
|
||||||
fprint_dbus_device_complete_verify_stop (dbus_dev,
|
|
||||||
g_steal_pointer (&priv->current_cancel_invocation));
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
session->verify_status_reported = FALSE;
|
|
||||||
}
|
|
||||||
else if (g_cancellable_is_cancelled (priv->current_cancellable))
|
|
||||||
{
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
session->verify_status_reported = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_object (&priv->current_cancellable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1173,7 +1223,6 @@ identify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
g_autoptr(FpPrint) match = NULL;
|
g_autoptr(FpPrint) match = NULL;
|
||||||
FprintDevice *rdev = user_data;
|
FprintDevice *rdev = user_data;
|
||||||
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
||||||
FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
|
|
||||||
const char *name;
|
const char *name;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
@ -1206,22 +1255,7 @@ identify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
error->message);
|
error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the cancellation or reset action right away if vanished. */
|
stoppable_action_completed (rdev);
|
||||||
if (priv->current_cancel_invocation)
|
|
||||||
{
|
|
||||||
fprint_dbus_device_complete_verify_stop (dbus_dev,
|
|
||||||
g_steal_pointer (&priv->current_cancel_invocation));
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
}
|
|
||||||
else if (g_cancellable_is_cancelled (priv->current_cancellable))
|
|
||||||
{
|
|
||||||
g_autoptr(SessionData) session = NULL;
|
|
||||||
session = session_data_get (priv);
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
session->verify_status_reported = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_object (&priv->current_cancellable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1444,7 +1478,7 @@ try_delete_print (FprintDevice *rdev)
|
|||||||
guint index;
|
guint index;
|
||||||
|
|
||||||
store.print_data_load (priv->dev,
|
store.print_data_load (priv->dev,
|
||||||
GPOINTER_TO_UINT (fingers->data),
|
GPOINTER_TO_UINT (finger->data),
|
||||||
username,
|
username,
|
||||||
&print);
|
&print);
|
||||||
|
|
||||||
@ -1518,7 +1552,6 @@ enroll_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FprintDevice *rdev = user_data;
|
FprintDevice *rdev = user_data;
|
||||||
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
||||||
FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
|
|
||||||
|
|
||||||
g_autoptr(FpPrint) print = NULL;
|
g_autoptr(FpPrint) print = NULL;
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -1566,18 +1599,7 @@ enroll_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
g_warning ("Device reported an error during enroll: %s", error->message);
|
g_warning ("Device reported an error during enroll: %s", error->message);
|
||||||
|
|
||||||
/* Return the cancellation or reset action right away if vanished. */
|
stoppable_action_completed (rdev);
|
||||||
if (priv->current_cancel_invocation)
|
|
||||||
{
|
|
||||||
fprint_dbus_device_complete_enroll_stop (dbus_dev,
|
|
||||||
g_steal_pointer (&priv->current_cancel_invocation));
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
}
|
|
||||||
else if (g_cancellable_is_cancelled (priv->current_cancellable))
|
|
||||||
{
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
}
|
|
||||||
g_clear_object (&priv->current_cancellable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1822,6 +1844,7 @@ fprint_device_delete_enrolled_fingers (FprintDBusDevice *dbus_dev,
|
|||||||
FprintDevice *rdev = FPRINT_DEVICE (dbus_dev);
|
FprintDevice *rdev = FPRINT_DEVICE (dbus_dev);
|
||||||
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
|
||||||
|
|
||||||
|
g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autofree char *user = NULL;
|
g_autofree char *user = NULL;
|
||||||
const char *sender;
|
const char *sender;
|
||||||
@ -1839,6 +1862,7 @@ fprint_device_delete_enrolled_fingers (FprintDBusDevice *dbus_dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->current_action = ACTION_DELETE;
|
priv->current_action = ACTION_DELETE;
|
||||||
|
action_unset = rdev;
|
||||||
|
|
||||||
if (!_fprint_device_check_claimed (rdev, invocation, &error))
|
if (!_fprint_device_check_claimed (rdev, invocation, &error))
|
||||||
{
|
{
|
||||||
@ -1872,8 +1896,6 @@ fprint_device_delete_enrolled_fingers (FprintDBusDevice *dbus_dev,
|
|||||||
if (!opened && fp_device_has_storage (priv->dev))
|
if (!opened && fp_device_has_storage (priv->dev))
|
||||||
fp_device_close_sync (priv->dev, NULL, NULL);
|
fp_device_close_sync (priv->dev, NULL, NULL);
|
||||||
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
|
|
||||||
fprint_dbus_device_complete_delete_enrolled_fingers (dbus_dev,
|
fprint_dbus_device_complete_delete_enrolled_fingers (dbus_dev,
|
||||||
invocation);
|
invocation);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1888,6 +1910,7 @@ fprint_device_delete_enrolled_fingers2 (FprintDBusDevice *dbus_dev,
|
|||||||
|
|
||||||
g_autoptr(SessionData) session = NULL;
|
g_autoptr(SessionData) session = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
|
||||||
|
|
||||||
if (!_fprint_device_check_claimed (rdev, invocation, &error))
|
if (!_fprint_device_check_claimed (rdev, invocation, &error))
|
||||||
{
|
{
|
||||||
@ -1902,13 +1925,12 @@ fprint_device_delete_enrolled_fingers2 (FprintDBusDevice *dbus_dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->current_action = ACTION_DELETE;
|
priv->current_action = ACTION_DELETE;
|
||||||
|
action_unset = rdev;
|
||||||
|
|
||||||
session = session_data_get (priv);
|
session = session_data_get (priv);
|
||||||
|
|
||||||
delete_enrolled_fingers (rdev, session->username);
|
delete_enrolled_fingers (rdev, session->username);
|
||||||
|
|
||||||
priv->current_action = ACTION_NONE;
|
|
||||||
|
|
||||||
fprint_dbus_device_complete_delete_enrolled_fingers2 (dbus_dev,
|
fprint_dbus_device_complete_delete_enrolled_fingers2 (dbus_dev,
|
||||||
invocation);
|
invocation);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|||||||
@ -66,6 +66,10 @@ get_storage_path (void)
|
|||||||
elems = g_strsplit (path, ":", -1);
|
elems = g_strsplit (path, ":", -1);
|
||||||
storage_path = g_strdup (elems[0]);
|
storage_path = g_strdup (elems[0]);
|
||||||
}
|
}
|
||||||
|
else if (*path)
|
||||||
|
{
|
||||||
|
storage_path = g_strdup (path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storage_path == NULL)
|
if (storage_path == NULL)
|
||||||
@ -151,7 +155,6 @@ file_storage_print_data_save (FpPrint *print)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//fp_dbg("saving to %s", path);
|
|
||||||
g_file_set_contents (path, buf, len, &err);
|
g_file_set_contents (path, buf, len, &err);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -161,6 +164,8 @@ file_storage_print_data_save (FpPrint *print)
|
|||||||
return err->code;
|
return err->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_debug ("file_storage_print_data_save(): print saved to %s", path);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +177,6 @@ load_from_file (char *path, FpPrint **print)
|
|||||||
g_autofree char *contents = NULL;
|
g_autofree char *contents = NULL;
|
||||||
FpPrint *new;
|
FpPrint *new;
|
||||||
|
|
||||||
//fp_dbg("from %s", path);
|
|
||||||
g_file_get_contents (path, &contents, &length, &err);
|
g_file_get_contents (path, &contents, &length, &err);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -226,6 +230,7 @@ file_storage_print_data_load (FpDevice *dev,
|
|||||||
int
|
int
|
||||||
file_storage_print_data_delete (FpDevice *dev, FpFinger finger, const char *username)
|
file_storage_print_data_delete (FpDevice *dev, FpFinger finger, const char *username)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GSList) prints = NULL;
|
||||||
g_autofree gchar *base_store = NULL;
|
g_autofree gchar *base_store = NULL;
|
||||||
g_autofree gchar *path = NULL;
|
g_autofree gchar *path = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -234,12 +239,27 @@ file_storage_print_data_delete (FpDevice *dev, FpFinger finger, const char *user
|
|||||||
|
|
||||||
path = get_path_to_print_dscv (dev, finger, base_store);
|
path = get_path_to_print_dscv (dev, finger, base_store);
|
||||||
|
|
||||||
|
if (!g_file_test (path, G_FILE_TEST_EXISTS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
r = g_unlink (path);
|
r = g_unlink (path);
|
||||||
g_debug ("file_storage_print_data_delete(): unlink(\"%s\") %s",
|
g_debug ("file_storage_print_data_delete(): unlink(\"%s\") %s",
|
||||||
path, g_strerror (r));
|
path, g_strerror (r));
|
||||||
|
|
||||||
/* FIXME: cleanup empty directory */
|
prints = file_storage_discover_prints (dev, username);
|
||||||
return g_unlink (path);
|
if (!prints)
|
||||||
|
{
|
||||||
|
g_autofree char *dir = g_steal_pointer (&path);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
g_autofree char *tmp = g_steal_pointer (&dir);
|
||||||
|
dir = g_path_get_dirname (tmp);
|
||||||
|
}
|
||||||
|
while (g_str_has_prefix (dir, base_store) && g_rmdir (dir) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList *
|
static GSList *
|
||||||
|
|||||||
@ -55,7 +55,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* Enum of possible permissions, orders and nick matter here:
|
/* Enum of possible permissions, orders and nick matter here:
|
||||||
- The order controls the priority of a required permission when various are
|
- The order controls the priority of a required permission when various are
|
||||||
accepted: the lowest the value, the more priorty it has.
|
accepted: the lowest the value, the more priority it has.
|
||||||
- Nick must match the relative polkit rule.
|
- Nick must match the relative polkit rule.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -91,3 +91,18 @@ FprintDevice *fprint_device_new (FpDevice *dev);
|
|||||||
guint32 _fprint_device_get_id (FprintDevice *rdev);
|
guint32 _fprint_device_get_id (FprintDevice *rdev);
|
||||||
/* Print */
|
/* Print */
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
|
||||||
|
|
||||||
|
/* Some compatibility definitions for older GLib. Copied from from libfprint. */
|
||||||
|
#if !GLIB_CHECK_VERSION (2, 57, 0)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GTypeClass, g_type_class_unref);
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GParamSpec, g_param_spec_unref);
|
||||||
|
#else
|
||||||
|
/* Re-define G_SOURCE_FUNC as we are technically not allowed to use it with
|
||||||
|
* the version we depend on currently. */
|
||||||
|
#undef G_SOURCE_FUNC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void))(f))
|
||||||
|
|||||||
@ -432,7 +432,7 @@ fprint_manager_get_default_device (FprintManager *manager,
|
|||||||
GQuark
|
GQuark
|
||||||
fprint_error_quark (void)
|
fprint_error_quark (void)
|
||||||
{
|
{
|
||||||
static volatile gsize quark = 0;
|
static gsize quark = 0;
|
||||||
|
|
||||||
if (g_once_init_enter (&quark))
|
if (g_once_init_enter (&quark))
|
||||||
{
|
{
|
||||||
|
|||||||
232
tests/fprintd.py
232
tests/fprintd.py
@ -296,24 +296,36 @@ class FPrintdTest(dbusmock.DBusTestCase):
|
|||||||
'.*net\.reactivated\.Fprint\.Error\.{}.*'.format(fprint_error))
|
'.*net\.reactivated\.Fprint\.Error\.{}.*'.format(fprint_error))
|
||||||
|
|
||||||
# From libfprint tests
|
# From libfprint tests
|
||||||
def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT):
|
def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT, con=None):
|
||||||
with Connection(self.sockaddr) as con:
|
if con:
|
||||||
con.sendall(struct.pack('ii', -1, retry_error))
|
con.sendall(struct.pack('ii', -1, retry_error))
|
||||||
|
return
|
||||||
|
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_retry(retry_error, con)
|
||||||
|
|
||||||
# From libfprint tests
|
# From libfprint tests
|
||||||
def send_error(self, error=FPrint.DeviceError.GENERAL):
|
def send_error(self, error=FPrint.DeviceError.GENERAL, con=None):
|
||||||
with Connection(self.sockaddr) as con:
|
if con:
|
||||||
con.sendall(struct.pack('ii', -2, error))
|
con.sendall(struct.pack('ii', -2, error))
|
||||||
|
return
|
||||||
|
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_error(error, con)
|
||||||
|
|
||||||
# From libfprint tests
|
# From libfprint tests
|
||||||
def send_remove(self):
|
def send_remove(self, con=None):
|
||||||
with Connection(self.sockaddr) as con:
|
if con:
|
||||||
con.sendall(struct.pack('ii', -5, 0))
|
con.sendall(struct.pack('ii', -5, 0))
|
||||||
|
return
|
||||||
|
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_remove(con=con)
|
||||||
|
|
||||||
# From libfprint tests
|
# From libfprint tests
|
||||||
def send_image(self, image):
|
def send_image(self, image, con=None):
|
||||||
img = self.prints[image]
|
if con:
|
||||||
with Connection(self.sockaddr) as con:
|
img = self.prints[image]
|
||||||
mem = img.get_data()
|
mem = img.get_data()
|
||||||
mem = mem.tobytes()
|
mem = mem.tobytes()
|
||||||
self.assertEqual(len(mem), img.get_width() * img.get_height())
|
self.assertEqual(len(mem), img.get_width() * img.get_height())
|
||||||
@ -322,6 +334,28 @@ class FPrintdTest(dbusmock.DBusTestCase):
|
|||||||
encoded_img += mem
|
encoded_img += mem
|
||||||
|
|
||||||
con.sendall(encoded_img)
|
con.sendall(encoded_img)
|
||||||
|
return
|
||||||
|
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_image(image, con)
|
||||||
|
|
||||||
|
def send_finger_automatic(self, automatic, con=None):
|
||||||
|
# Set whether finger on/off is reported around images
|
||||||
|
if con:
|
||||||
|
con.sendall(struct.pack('ii', -3, 1 if automatic else 0))
|
||||||
|
return
|
||||||
|
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_finger_automatic(automatic, con=con)
|
||||||
|
|
||||||
|
def send_finger_report(self, has_finger, con=None):
|
||||||
|
# Send finger on/off
|
||||||
|
if con:
|
||||||
|
con.sendall(struct.pack('ii', -4, 1 if has_finger else 0))
|
||||||
|
return
|
||||||
|
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_finger_report(has_finger, con=con)
|
||||||
|
|
||||||
def call_device_method_async(self, method, *args):
|
def call_device_method_async(self, method, *args):
|
||||||
""" add cancellable... """
|
""" add cancellable... """
|
||||||
@ -429,10 +463,12 @@ class FPrintdVirtualDeviceBaseTest(FPrintdTest):
|
|||||||
if expected is not None:
|
if expected is not None:
|
||||||
self.assertEqual(self._last_result, expected)
|
self.assertEqual(self._last_result, expected)
|
||||||
|
|
||||||
def enroll_image(self, img, finger='right-index-finger', expected_result='enroll-completed'):
|
def enroll_image(self, img, device=None, finger='right-index-finger', expected_result='enroll-completed'):
|
||||||
self.device.EnrollStart('(s)', finger)
|
if device is None:
|
||||||
|
device = self.device
|
||||||
|
device.EnrollStart('(s)', finger)
|
||||||
|
|
||||||
stages = self.device.get_cached_property('num-enroll-stages').unpack()
|
stages = device.get_cached_property('num-enroll-stages').unpack()
|
||||||
for stage in range(stages):
|
for stage in range(stages):
|
||||||
self.send_image(img)
|
self.send_image(img)
|
||||||
if stage < stages - 1:
|
if stage < stages - 1:
|
||||||
@ -440,7 +476,7 @@ class FPrintdVirtualDeviceBaseTest(FPrintdTest):
|
|||||||
else:
|
else:
|
||||||
self.wait_for_result(expected_result)
|
self.wait_for_result(expected_result)
|
||||||
|
|
||||||
self.device.EnrollStop()
|
device.EnrollStop()
|
||||||
self.assertEqual(self._last_result, expected_result)
|
self.assertEqual(self._last_result, expected_result)
|
||||||
|
|
||||||
def enroll_multiple_images(self, images_override={}, return_index=-1):
|
def enroll_multiple_images(self, images_override={}, return_index=-1):
|
||||||
@ -462,6 +498,29 @@ class FPrintdVirtualDeviceBaseTest(FPrintdTest):
|
|||||||
|
|
||||||
return (enrolled, enroll_map)
|
return (enrolled, enroll_map)
|
||||||
|
|
||||||
|
def get_secondary_bus_and_device(self, claim=None):
|
||||||
|
addr = os.environ['DBUS_SYSTEM_BUS_ADDRESS']
|
||||||
|
|
||||||
|
# Get a separate bus connection
|
||||||
|
bus = Gio.DBusConnection.new_for_address_sync(addr,
|
||||||
|
Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION |
|
||||||
|
Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT, None, None)
|
||||||
|
assert bus.is_closed() == False
|
||||||
|
|
||||||
|
dev_path = self.device.get_object_path()
|
||||||
|
dev = Gio.DBusProxy.new_sync(bus,
|
||||||
|
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
||||||
|
None,
|
||||||
|
'net.reactivated.Fprint',
|
||||||
|
dev_path,
|
||||||
|
'net.reactivated.Fprint.Device',
|
||||||
|
None)
|
||||||
|
|
||||||
|
if claim is not None:
|
||||||
|
dev.Claim('(s)', claim)
|
||||||
|
|
||||||
|
return bus, dev
|
||||||
|
|
||||||
|
|
||||||
class FPrintdManagerTests(FPrintdVirtualDeviceBaseTest):
|
class FPrintdManagerTests(FPrintdVirtualDeviceBaseTest):
|
||||||
|
|
||||||
@ -700,23 +759,7 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
self.device.Release()
|
self.device.Release()
|
||||||
|
|
||||||
def test_claim_disconnect(self):
|
def test_claim_disconnect(self):
|
||||||
addr = os.environ['DBUS_SYSTEM_BUS_ADDRESS']
|
bus, dev = self.get_secondary_bus_and_device()
|
||||||
|
|
||||||
# Get a separat bus connection
|
|
||||||
dbus = Gio.DBusConnection.new_for_address_sync(addr,
|
|
||||||
Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION |
|
|
||||||
Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT, None, None)
|
|
||||||
assert dbus.is_closed() == False
|
|
||||||
|
|
||||||
|
|
||||||
dev_path = self.device.get_object_path()
|
|
||||||
dev = Gio.DBusProxy.new_sync(dbus,
|
|
||||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
|
||||||
None,
|
|
||||||
'net.reactivated.Fprint',
|
|
||||||
dev_path,
|
|
||||||
'net.reactivated.Fprint.Device',
|
|
||||||
None)
|
|
||||||
|
|
||||||
def call_done(obj, result, user_data):
|
def call_done(obj, result, user_data):
|
||||||
# Ignore the callback (should be an error)
|
# Ignore the callback (should be an error)
|
||||||
@ -726,8 +769,91 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
dev.Claim('(s)', 'testuser', result_handler=call_done)
|
dev.Claim('(s)', 'testuser', result_handler=call_done)
|
||||||
|
|
||||||
# Ensure the call is on the wire, then close immediately
|
# Ensure the call is on the wire, then close immediately
|
||||||
dbus.flush_sync()
|
bus.flush_sync()
|
||||||
dbus.close_sync()
|
bus.close_sync()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_enroll_running_disconnect(self):
|
||||||
|
bus, dev = self.get_secondary_bus_and_device(claim='testuser')
|
||||||
|
|
||||||
|
# Start an enroll and disconnect, without finishing/cancelling
|
||||||
|
dev.EnrollStart('(s)', 'left-index-finger')
|
||||||
|
|
||||||
|
# Ensure the call is on the wire, then close immediately
|
||||||
|
bus.flush_sync()
|
||||||
|
bus.close_sync()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_enroll_done_disconnect(self):
|
||||||
|
bus, dev = self.get_secondary_bus_and_device(claim='testuser')
|
||||||
|
|
||||||
|
# Start an enroll and disconnect, without finishing/cancelling
|
||||||
|
dev.EnrollStart('(s)', 'left-index-finger')
|
||||||
|
|
||||||
|
# This works because we also receive the signals on the main connection
|
||||||
|
stages = dev.get_cached_property('num-enroll-stages').unpack()
|
||||||
|
for stage in range(stages):
|
||||||
|
self.send_image('whorl')
|
||||||
|
if stage < stages - 1:
|
||||||
|
self.wait_for_result('enroll-stage-passed')
|
||||||
|
else:
|
||||||
|
self.wait_for_result('enroll-completed')
|
||||||
|
|
||||||
|
bus.close_sync()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_verify_running_disconnect(self):
|
||||||
|
bus, dev = self.get_secondary_bus_and_device(claim='testuser')
|
||||||
|
self.enroll_image('whorl', device=dev)
|
||||||
|
|
||||||
|
# Start an enroll and disconnect, without finishing/cancelling
|
||||||
|
dev.VerifyStart('(s)', 'right-index-finger')
|
||||||
|
|
||||||
|
bus.close_sync()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_verify_done_disconnect(self):
|
||||||
|
bus, dev = self.get_secondary_bus_and_device(claim='testuser')
|
||||||
|
self.enroll_image('whorl', device=dev)
|
||||||
|
|
||||||
|
# Start an enroll and disconnect, without finishing/cancelling
|
||||||
|
dev.VerifyStart('(s)', 'right-index-finger')
|
||||||
|
self.send_image('whorl')
|
||||||
|
# Wait for match and sleep a bit to give fprintd time to wrap up
|
||||||
|
self.wait_for_result('verify-match')
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
bus.close_sync()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_identify_running_disconnect(self):
|
||||||
|
bus, dev = self.get_secondary_bus_and_device(claim='testuser')
|
||||||
|
self.enroll_image('whorl', device=dev)
|
||||||
|
|
||||||
|
# Start an enroll and disconnect, without finishing/cancelling
|
||||||
|
dev.VerifyStart('(s)', 'any')
|
||||||
|
|
||||||
|
bus.close_sync()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_identify_done_disconnect(self):
|
||||||
|
bus, dev = self.get_secondary_bus_and_device(claim='testuser')
|
||||||
|
self.enroll_image('whorl', device=dev)
|
||||||
|
|
||||||
|
# Start an enroll and disconnect, without finishing/cancelling
|
||||||
|
dev.VerifyStart('(s)', 'any')
|
||||||
|
self.send_image('whorl')
|
||||||
|
# Wait for match and sleep a bit to give fprintd time to wrap up
|
||||||
|
self.wait_for_result('verify-match')
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
bus.close_sync()
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
@ -843,9 +969,11 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
self.device.DeleteEnrolledFingers2()
|
self.device.DeleteEnrolledFingers2()
|
||||||
|
|
||||||
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
||||||
|
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser')))
|
||||||
|
self.assertTrue(os.path.exists(self.state_dir))
|
||||||
|
|
||||||
def test_enroll_invalid_storage_dir(self):
|
def test_enroll_invalid_storage_dir(self):
|
||||||
# Directory wil not exist yet
|
# Directory will not exist yet
|
||||||
os.makedirs(self.state_dir, mode=0o500)
|
os.makedirs(self.state_dir, mode=0o500)
|
||||||
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
||||||
|
|
||||||
@ -1214,6 +1342,12 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest):
|
|||||||
def test_verify_retry_general(self):
|
def test_verify_retry_general(self):
|
||||||
self.assertVerifyRetry(FPrint.DeviceRetry.GENERAL, 'verify-retry-scan')
|
self.assertVerifyRetry(FPrint.DeviceRetry.GENERAL, 'verify-retry-scan')
|
||||||
|
|
||||||
|
def test_verify_retry_general_restarted(self):
|
||||||
|
self.assertVerifyRetry(FPrint.DeviceRetry.GENERAL, 'verify-retry-scan')
|
||||||
|
# Give fprintd time to re-start the request. We can't force the other
|
||||||
|
# case (cancellation before restart happened), but we can force this one.
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
def test_verify_retry_too_short(self):
|
def test_verify_retry_too_short(self):
|
||||||
self.assertVerifyRetry(FPrint.DeviceRetry.TOO_SHORT, 'verify-swipe-too-short')
|
self.assertVerifyRetry(FPrint.DeviceRetry.TOO_SHORT, 'verify-swipe-too-short')
|
||||||
|
|
||||||
@ -1250,6 +1384,38 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest):
|
|||||||
def test_verify_error_data_full(self):
|
def test_verify_error_data_full(self):
|
||||||
self.assertVerifyError(FPrint.DeviceError.DATA_FULL, 'verify-unknown-error')
|
self.assertVerifyError(FPrint.DeviceError.DATA_FULL, 'verify-unknown-error')
|
||||||
|
|
||||||
|
def test_multiple_verify(self):
|
||||||
|
self.send_image('tented_arch')
|
||||||
|
self.wait_for_result()
|
||||||
|
self.assertTrue(self._verify_stopped)
|
||||||
|
self.assertEqual(self._last_result, 'verify-no-match')
|
||||||
|
self.device.VerifyStop()
|
||||||
|
|
||||||
|
self.device.VerifyStart('(s)', self.verify_finger)
|
||||||
|
self.send_image('whorl')
|
||||||
|
self.wait_for_result()
|
||||||
|
self.assertTrue(self._verify_stopped)
|
||||||
|
self.assertEqual(self._last_result, 'verify-match')
|
||||||
|
|
||||||
|
def test_multiple_verify_cancelled(self):
|
||||||
|
with Connection(self.sockaddr) as con:
|
||||||
|
self.send_finger_automatic(False, con=con)
|
||||||
|
self.send_finger_report(True, con=con)
|
||||||
|
self.send_image('tented_arch', con=con)
|
||||||
|
self.wait_for_result()
|
||||||
|
self.assertTrue(self._verify_stopped)
|
||||||
|
self.assertEqual(self._last_result, 'verify-no-match')
|
||||||
|
self.device.VerifyStop()
|
||||||
|
|
||||||
|
# We'll be cancelled at this point, so con is invalid
|
||||||
|
|
||||||
|
self.device.VerifyStart('(s)', self.verify_finger)
|
||||||
|
self.send_finger_report(False)
|
||||||
|
self.send_image('whorl')
|
||||||
|
self.wait_for_result()
|
||||||
|
self.assertTrue(self._verify_stopped)
|
||||||
|
self.assertEqual(self._last_result, 'verify-match')
|
||||||
|
|
||||||
def test_verify_start_during_verify(self):
|
def test_verify_start_during_verify(self):
|
||||||
with self.assertFprintError('AlreadyInUse'):
|
with self.assertFprintError('AlreadyInUse'):
|
||||||
self.device.VerifyStart('(s)', self.verify_finger)
|
self.device.VerifyStart('(s)', self.verify_finger)
|
||||||
|
|||||||
40
tests/pam/test_pam_fprintd.py
Executable file → Normal file
40
tests/pam/test_pam_fprintd.py
Executable file → Normal file
@ -154,6 +154,21 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTHINFO_UNAVAIL)
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTHINFO_UNAVAIL)
|
||||||
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
|
|
||||||
|
def test_pam_fprintd_retry(self):
|
||||||
|
self.setup_device()
|
||||||
|
script = [
|
||||||
|
( 'verify-swipe-too-short', False, 1 ),
|
||||||
|
( 'verify-finger-not-centered', False, 1 ),
|
||||||
|
( 'verify-match', True, 1 )
|
||||||
|
]
|
||||||
|
self.device_mock.SetVerifyScript(script)
|
||||||
|
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_SUCCESS)
|
||||||
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
|
self.assertRegex(res.info[0], r'Swipe your left little finger across the fingerprint reader')
|
||||||
|
self.assertRegex(res.errors[0], r'Swipe was too short, try again')
|
||||||
|
self.assertRegex(res.errors[1], r'Your finger was not centered, try swiping your finger again')
|
||||||
|
|
||||||
def test_pam_fprintd_no_fingers_while_verifying(self):
|
def test_pam_fprintd_no_fingers_while_verifying(self):
|
||||||
self.setup_device()
|
self.setup_device()
|
||||||
script = [
|
script = [
|
||||||
@ -221,6 +236,31 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
self.assertRegex(res.info[0], r'Place your left middle finger on FDO Sandpaper Reader')
|
self.assertRegex(res.info[0], r'Place your left middle finger on FDO Sandpaper Reader')
|
||||||
self.assertEqual(len(res.errors), 0)
|
self.assertEqual(len(res.errors), 0)
|
||||||
|
|
||||||
|
def test_pam_fprintd_multi_reader_not_all_enrolled(self):
|
||||||
|
# Add a 1st device with actual enrolled prints
|
||||||
|
device_path = self.obj_fprintd_mock.AddDevice('FDO Empty reader', 3, 'press')
|
||||||
|
empty_reader = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
||||||
|
empty_reader.SetEnrolledFingers('toto', dbus.Array(set([]), signature='s'))
|
||||||
|
|
||||||
|
# Add a 2nd device with actual enrolled prints
|
||||||
|
device_path = self.obj_fprintd_mock.AddDevice('FDO Most Used Reader', 3, 'press')
|
||||||
|
sandpaper_device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
||||||
|
sandpaper_device_mock.SetEnrolledFingers('toto', ['left-middle-finger', 'right-middle-finger'])
|
||||||
|
script = [
|
||||||
|
( 'verify-match', True, 2 )
|
||||||
|
]
|
||||||
|
sandpaper_device_mock.SetVerifyScript(script)
|
||||||
|
|
||||||
|
# Add a 3rd device, with only one enrolled finger
|
||||||
|
self.setup_device()
|
||||||
|
self.device_mock.SetEnrolledFingers('toto', ['left-middle-finger'])
|
||||||
|
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_SUCCESS)
|
||||||
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
|
|
||||||
|
self.assertRegex(res.info[0], r'Place your left middle finger on FDO Most Used Reader')
|
||||||
|
self.assertEqual(len(res.errors), 0)
|
||||||
|
|
||||||
def test_pam_fprintd_last_try_auth(self):
|
def test_pam_fprintd_last_try_auth(self):
|
||||||
self.setup_device()
|
self.setup_device()
|
||||||
script = [
|
script = [
|
||||||
|
|||||||
Reference in New Issue
Block a user