diff --git a/pam/pam_fprintd.c b/pam/pam_fprintd.c index 9847f4a..5e8757c 100644 --- a/pam/pam_fprintd.c +++ b/pam/pam_fprintd.c @@ -154,7 +154,7 @@ static DBusGProxy *create_manager (pam_handle_t *pamh, DBusGConnection **ret_con return manager; } -static close_and_unref (DBusGConnection *connection) +static void close_and_unref (DBusGConnection *connection) { DBusConnection *conn; @@ -335,7 +335,11 @@ static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev) ret = PAM_SUCCESS; else if (g_str_equal (data->result, "verify-unknown-error")) ret = PAM_AUTHINFO_UNAVAIL; - else { + else if (g_str_equal (data->result, "verify-disconnected")) { + ret = PAM_AUTHINFO_UNAVAIL; + g_free (data->result); + break; + } else { send_info_msg (data->pamh, "An unknown error occured"); ret = PAM_AUTH_ERR; g_free (data->result); diff --git a/src/device.c b/src/device.c index 68a0b52..e1127da 100644 --- a/src/device.c +++ b/src/device.c @@ -28,6 +28,7 @@ #include #include +#include #include "fprintd-marshal.h" #include "fprintd.h" @@ -119,6 +120,8 @@ struct FprintDevicePrivate { FprintDeviceAction current_action; /* Whether we should ignore new signals on the device */ gboolean action_done; + /* Whether the device was disconnected */ + gboolean disconnected; }; typedef struct FprintDevicePrivate FprintDevicePrivate; @@ -368,6 +371,8 @@ verify_result_to_name (int result) return "verify-finger-not-centered"; case FP_VERIFY_RETRY_REMOVE_FINGER: return "verify-remove-and-retry"; + case -EPROTO: + return "verify-disconnected"; default: return "verify-unknown-error"; } @@ -391,11 +396,21 @@ enroll_result_to_name (int result) return "enroll-finger-not-centered"; case FP_ENROLL_RETRY_REMOVE_FINGER: return "enroll-remove-and-retry"; + case -EPROTO: + return "enroll-disconnected"; default: return "enroll-unknown-error"; } } +static void +set_disconnected (FprintDevicePrivate *priv, const char *res) +{ + if (g_str_equal (res, "enroll-disconnected") || + g_str_equal (res, "verify-disconnected")) + priv->disconnected = TRUE; +} + static gboolean _fprint_device_check_claimed (FprintDevice *rdev, DBusGMethodInvocation *context, @@ -790,6 +805,7 @@ static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img, if (r == FP_VERIFY_NO_MATCH || r == FP_VERIFY_MATCH || r < 0) priv->action_done = TRUE; + set_disconnected (priv, name); g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, priv->action_done); fp_img_free(img); @@ -813,6 +829,7 @@ static void identify_cb(struct fp_dev *dev, int r, if (r == FP_VERIFY_NO_MATCH || r == FP_VERIFY_MATCH || r < 0) priv->action_done = TRUE; + set_disconnected (priv, name); g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, priv->action_done); fp_img_free(img); @@ -986,7 +1003,10 @@ static void fprint_device_verify_stop(FprintDevice *rdev, fp_print_data_free (priv->verify_data); priv->verify_data = NULL; } - r = fp_async_verify_stop(priv->dev, verify_stop_cb, context); + if (!priv->disconnected) + r = fp_async_verify_stop(priv->dev, verify_stop_cb, context); + else + r = 0; } else if (priv->current_action == ACTION_IDENTIFY) { if (priv->identify_data != NULL) { guint i; @@ -995,7 +1015,10 @@ static void fprint_device_verify_stop(FprintDevice *rdev, g_free (priv->identify_data); priv->identify_data = NULL; } - r = fp_async_identify_stop(priv->dev, identify_stop_cb, context); + if (!priv->disconnected) + r = fp_async_identify_stop(priv->dev, identify_stop_cb, context); + else + r = 0; } else { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_ACTION_IN_PROGRESS, "No verification in progress"); @@ -1010,6 +1033,8 @@ static void fprint_device_verify_stop(FprintDevice *rdev, dbus_g_method_return_error(context, error); g_error_free (error); } + if (priv->disconnected) + dbus_g_method_return(context); priv->current_action = ACTION_NONE; } @@ -1020,6 +1045,7 @@ static void enroll_stage_cb(struct fp_dev *dev, int result, struct FprintDevice *rdev = user_data; FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); struct session_data *session = priv->session; + const char *name = enroll_result_to_name (result); int r; /* We're done, ignore new events for the action */ @@ -1035,8 +1061,9 @@ static void enroll_stage_cb(struct fp_dev *dev, int result, if (result == FP_ENROLL_COMPLETE || result == FP_ENROLL_FAIL || result < 0) priv->action_done = TRUE; + set_disconnected (priv, name); - g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, enroll_result_to_name (result), priv->action_done); + g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, name, priv->action_done); fp_img_free(img); fp_print_data_free(print); @@ -1129,13 +1156,18 @@ static void fprint_device_enroll_stop(FprintDevice *rdev, return; } - r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context); + if (!priv->disconnected) + r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context); + else + r = 0; if (r < 0) { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL, "Enroll stop failed with error %d", r); dbus_g_method_return_error(context, error); g_error_free (error); } + if (priv->disconnected) + dbus_g_method_return(context); priv->current_action = ACTION_NONE; } diff --git a/src/device.xml b/src/device.xml index 402c44b..99912ad 100644 --- a/src/device.xml +++ b/src/device.xml @@ -182,6 +182,12 @@ The user should remove their finger from the reader and retry scanning their finger, the verification is still ongoing. + + verify-disconnected + + The device was disconnected during the verification, no other actions should be taken, and you shouldn't use the device any more. + + verify-unknown-error @@ -239,6 +245,13 @@ The user should remove their finger from the reader and retry scanning their finger, the enrollment is still ongoing. + + enroll-disconnected + + The device was disconnected during the enrollment, no other actions should be taken, and you shouldn't use the device any more. + + + enroll-unknown-error diff --git a/tests/verify.c b/tests/verify.c index 999c402..eb739cb 100644 --- a/tests/verify.c +++ b/tests/verify.c @@ -100,7 +100,7 @@ static void find_finger(DBusGProxy *dev, const char *username) static void verify_result(GObject *object, const char *result, gboolean done, void *user_data) { gboolean *verify_completed = user_data; - g_print("Verify result: %s\n", result); + g_print("Verify result: %s (%s)\n", result, done ? "done" : "not done"); if (done != FALSE) *verify_completed = TRUE; }