Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fprintd for openSUSE:Factory checked 
in at 2021-01-18 11:28:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fprintd (Old)
 and      /work/SRC/openSUSE:Factory/.fprintd.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fprintd"

Mon Jan 18 11:28:34 2021 rev:13 rq:863644 version:1.90.9

Changes:
--------
--- /work/SRC/openSUSE:Factory/fprintd/fprintd.changes  2020-12-21 
10:27:03.232227251 +0100
+++ /work/SRC/openSUSE:Factory/.fprintd.new.28504/fprintd.changes       
2021-01-18 11:32:24.888688164 +0100
@@ -1,0 +2,8 @@
+Fri Jan 15 19:42:37 UTC 2021 - Martin Hauke <[email protected]>
+
+- Update to version 1.90.9
+  * Fix multiple daemon lockup issues (#97)
+  * Fix print garbage collection to not delete used prints
+  * pam: Use the device with the most prints
+
+-------------------------------------------------------------------

Old:
----
  fprintd-1.90.8.tar.bz2

New:
----
  fprintd-1.90.9.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ fprintd.spec ++++++
--- /var/tmp/diff_new_pack.1xDsYM/_old  2021-01-18 11:32:25.480688748 +0100
+++ /var/tmp/diff_new_pack.1xDsYM/_new  2021-01-18 11:32:25.480688748 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package fprintd
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,10 +16,10 @@
 #
 
 
-%define gitlabhash 7d22a2b5b9d323638bb213aefb8627d897c8e482
+%define gitlabhash da60bddb3e5be024c6c1958437cb13e0ce0ffac8
 
 Name:           fprintd
-Version:        1.90.8
+Version:        1.90.9
 Release:        0
 Summary:        D-Bus service for Fingerprint reader access
 License:        GPL-2.0-or-later

++++++ fprintd-1.90.8.tar.bz2 -> fprintd-1.90.9.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/NEWS 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/NEWS
--- old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/NEWS   
2020-12-11 16:00:28.000000000 +0100
+++ new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/NEWS   
2021-01-13 13:23:24.000000000 +0100
@@ -1,6 +1,14 @@
 This file lists notable changes in each release. For the full history of all
 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:
 
 It seems that we are finally reaching the end of the tunnel with regard
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/meson.build 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/meson.build
--- old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/meson.build    
2020-12-11 16:00:28.000000000 +0100
+++ new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/meson.build    
2021-01-13 13:23:24.000000000 +0100
@@ -1,5 +1,5 @@
 project('fprintd', 'c',
-    version: '1.90.8',
+    version: '1.90.9',
     license: 'GPLv2+',
     default_options: [
         'buildtype=debugoptimized',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/pam/pam_fprintd.c 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/pam/pam_fprintd.c
--- 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/pam/pam_fprintd.c  
    2020-12-11 16:00:28.000000000 +0100
+++ 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/pam/pam_fprintd.c  
    2021-01-13 13:23:24.000000000 +0100
@@ -60,6 +60,11 @@
 #define USEC_PER_SEC ((uint64_t) 1000000ULL)
 #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
 now (void)
 {
@@ -112,11 +117,13 @@
 static char *
 open_device (pam_handle_t *pamh,
              sd_bus       *bus,
+             const char   *username,
              bool         *has_multiple_devices)
 {
   pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
   pf_autoptr (sd_bus_message) m = NULL;
   size_t num_devices;
+  size_t max_prints;
   const char *path = NULL;
   const char *s;
   int r;
@@ -143,12 +150,23 @@
       return NULL;
     }
 
-  if (sd_bus_message_read_basic (m, 'o', &path) < 0)
-    return NULL;
-
-  num_devices = 1;
+  num_devices = 0;
+  max_prints = 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);
   if (debug)
     pam_syslog (pamh, LOG_DEBUG, "Using device %s (out of %ld devices)", path, 
num_devices);
@@ -528,11 +546,11 @@
   return PAM_AUTH_ERR;
 }
 
-static bool
-user_has_prints (pam_handle_t *pamh,
-                 sd_bus       *bus,
-                 const char   *dev,
-                 const char   *username)
+static size_t
+user_enrolled_prints_num (pam_handle_t *pamh,
+                          sd_bus       *bus,
+                          const char   *dev,
+                          const char   *username)
 {
   pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
   pf_autoptr (sd_bus_message) m = NULL;
@@ -557,21 +575,21 @@
       if (debug)
         pam_syslog (pamh, LOG_DEBUG, "ListEnrolledFingers failed for %s: %s",
                     username, error.message);
-      return false;
+      return 0;
     }
 
   r = sd_bus_message_enter_container (m, 'a', "s");
   if (r < 0)
     {
       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)
     num_fingers++;
   sd_bus_message_exit_container (m);
 
-  return num_fingers > 0;
+  return num_fingers;
 }
 
 static void
@@ -651,8 +669,6 @@
 static int
 do_auth (pam_handle_t *pamh, const char *username)
 {
-  bool have_prints;
-
   pf_autoptr (verify_data) data = NULL;
   pf_autoptr (sd_bus) bus = NULL;
   pf_autoptr (sd_bus_slot) name_owner_changed_slot = NULL;
@@ -667,17 +683,10 @@
       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)
     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
    * we rely on the fact that we never see those signals.
    */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/device.c 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/device.c
--- old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/device.c   
2020-12-11 16:00:28.000000000 +0100
+++ new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/device.c   
2021-01-13 13:23:24.000000000 +0100
@@ -210,6 +210,16 @@
   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
 fprint_device_dispose (GObject *object)
 {
@@ -739,7 +749,7 @@
   if (!ret)
     {
       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);
       return NULL;
     }
@@ -784,15 +794,30 @@
   if (session != NULL &&
       g_strcmp0 (session->sender, name) == 0)
     {
-      while (priv->current_action != ACTION_NONE)
+      g_cancellable_cancel (priv->current_cancellable);
+
+      if (!priv->current_cancellable)
         {
-          /* OPEN/CLOSE are not cancellable, we just need to wait */
-          if (priv->current_cancellable)
-            g_cancellable_cancel (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;
 
-          g_main_context_iteration (NULL, TRUE);
+            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
        * was already closing. */
       g_clear_pointer (&session, session_data_unref);
@@ -838,11 +863,12 @@
 
   g_autoptr(SessionData) session = NULL;
   g_autoptr(GDBusMethodInvocation) invocation = NULL;
+  g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
 
+  action_unset = rdev;
   session = session_data_get (priv);
   invocation = g_steal_pointer (&session->invocation);
 
-  priv->current_action = ACTION_NONE;
   if (!fp_device_open_finish (dev, res, &error))
     {
       g_autoptr(GError) dbus_error = NULL;
@@ -939,12 +965,13 @@
 
   g_autoptr(SessionData) session = NULL;
   g_autoptr(GDBusMethodInvocation) invocation = NULL;
+  g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
 
   session = session_data_get (priv);
   session_data_set_new (priv, NULL, NULL);
   invocation = g_steal_pointer (&session->invocation);
+  action_unset = rdev;
 
-  priv->current_action = ACTION_NONE;
   if (!fp_device_close_finish (dev, res, &error))
     {
       g_autoptr(GError) dbus_error = NULL;
@@ -1052,7 +1079,7 @@
     case ACTION_VERIFY:
       g_set_error (error,
                    FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
-                   "Enrollment already in progress");
+                   "Verification already in progress");
       break;
 
     case ACTION_OPEN:
@@ -1084,6 +1111,47 @@
 }
 
 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
 match_cb (FpDevice *device,
           FpPrint  *match,
           FpPrint  *print,
@@ -1109,10 +1177,8 @@
 verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
 {
   g_autoptr(GError) error = NULL;
-  g_autoptr(SessionData) session = NULL;
   FprintDevice *rdev = user_data;
   FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
-  FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
   gboolean success;
   const char *name;
   gboolean match;
@@ -1121,8 +1187,6 @@
   g_assert (!!success == !error);
   name = verify_result_to_name (match, error);
 
-  session = session_data_get (priv);
-
   g_debug ("verify_cb: result %s", name);
 
   /* Automatically restart the operation for retry failures */
@@ -1148,21 +1212,7 @@
                        error->message);
         }
 
-      /* Return the cancellation or reset action right away if vanished. */
-      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);
+      stoppable_action_completed (rdev);
     }
 }
 
@@ -1173,7 +1223,6 @@
   g_autoptr(FpPrint) match = NULL;
   FprintDevice *rdev = user_data;
   FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
-  FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
   const char *name;
   gboolean success;
 
@@ -1206,22 +1255,7 @@
                        error->message);
         }
 
-      /* Return the cancellation or reset action right away if vanished. */
-      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);
+      stoppable_action_completed (rdev);
     }
 }
 
@@ -1444,7 +1478,7 @@
           guint index;
 
           store.print_data_load (priv->dev,
-                                 GPOINTER_TO_UINT (fingers->data),
+                                 GPOINTER_TO_UINT (finger->data),
                                  username,
                                  &print);
 
@@ -1518,7 +1552,6 @@
   g_autoptr(GError) error = NULL;
   FprintDevice *rdev = user_data;
   FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
-  FprintDBusDevice *dbus_dev = FPRINT_DBUS_DEVICE (rdev);
 
   g_autoptr(FpPrint) print = NULL;
   const char *name;
@@ -1566,18 +1599,7 @@
   if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     g_warning ("Device reported an error during enroll: %s", error->message);
 
-  /* Return the cancellation or reset action right away if vanished. */
-  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);
+  stoppable_action_completed (rdev);
 }
 
 
@@ -1822,6 +1844,7 @@
   FprintDevice *rdev = FPRINT_DEVICE (dbus_dev);
   FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
 
+  g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
   g_autoptr(GError) error = NULL;
   g_autofree char *user = NULL;
   const char *sender;
@@ -1839,6 +1862,7 @@
     }
 
   priv->current_action = ACTION_DELETE;
+  action_unset = rdev;
 
   if (!_fprint_device_check_claimed (rdev, invocation, &error))
     {
@@ -1872,8 +1896,6 @@
   if (!opened && fp_device_has_storage (priv->dev))
     fp_device_close_sync (priv->dev, NULL, NULL);
 
-  priv->current_action = ACTION_NONE;
-
   fprint_dbus_device_complete_delete_enrolled_fingers (dbus_dev,
                                                        invocation);
   return TRUE;
@@ -1888,6 +1910,7 @@
 
   g_autoptr(SessionData) session = NULL;
   g_autoptr(GError) error = NULL;
+  g_autoptr(FprintDeviceActionUnset) action_unset = NULL;
 
   if (!_fprint_device_check_claimed (rdev, invocation, &error))
     {
@@ -1902,13 +1925,12 @@
     }
 
   priv->current_action = ACTION_DELETE;
+  action_unset = rdev;
 
   session = session_data_get (priv);
 
   delete_enrolled_fingers (rdev, session->username);
 
-  priv->current_action = ACTION_NONE;
-
   fprint_dbus_device_complete_delete_enrolled_fingers2 (dbus_dev,
                                                         invocation);
   return TRUE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/file_storage.c 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/file_storage.c
--- 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/file_storage.c 
    2020-12-11 16:00:28.000000000 +0100
+++ 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/file_storage.c 
    2021-01-13 13:23:24.000000000 +0100
@@ -66,6 +66,10 @@
           elems = g_strsplit (path, ":", -1);
           storage_path = g_strdup (elems[0]);
         }
+      else if (*path)
+        {
+          storage_path = g_strdup (path);
+        }
     }
 
   if (storage_path == NULL)
@@ -151,7 +155,6 @@
       return r;
     }
 
-  //fp_dbg("saving to %s", path);
   g_file_set_contents (path, buf, len, &err);
   if (err)
     {
@@ -161,6 +164,8 @@
       return err->code;
     }
 
+  g_debug ("file_storage_print_data_save(): print saved to %s", path);
+
   return 0;
 }
 
@@ -172,7 +177,6 @@
   g_autofree char *contents = NULL;
   FpPrint *new;
 
-  //fp_dbg("from %s", path);
   g_file_get_contents (path, &contents, &length, &err);
   if (err)
     {
@@ -226,6 +230,7 @@
 int
 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 *path = NULL;
   int r;
@@ -234,12 +239,27 @@
 
   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);
   g_debug ("file_storage_print_data_delete(): unlink(\"%s\") %s",
            path, g_strerror (r));
 
-  /* FIXME: cleanup empty directory */
-  return g_unlink (path);
+  prints = file_storage_discover_prints (dev, username);
+  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 *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/fprintd.h 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/fprintd.h
--- old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/fprintd.h  
2020-12-11 16:00:28.000000000 +0100
+++ new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/fprintd.h  
2021-01-13 13:23:24.000000000 +0100
@@ -55,7 +55,7 @@
 
 /* Enum of possible permissions, orders and nick matter here:
    - 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.
  */
 typedef enum {
@@ -91,3 +91,18 @@
 guint32 _fprint_device_get_id (FprintDevice *rdev);
 /* Print */
 /* 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))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/manager.c 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/manager.c
--- old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/src/manager.c  
2020-12-11 16:00:28.000000000 +0100
+++ new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/src/manager.c  
2021-01-13 13:23:24.000000000 +0100
@@ -432,7 +432,7 @@
 GQuark
 fprint_error_quark (void)
 {
-  static volatile gsize quark = 0;
+  static gsize quark = 0;
 
   if (g_once_init_enter (&quark))
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/tests/fprintd.py 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/tests/fprintd.py
--- 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/tests/fprintd.py   
    2020-12-11 16:00:28.000000000 +0100
+++ 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/tests/fprintd.py   
    2021-01-13 13:23:24.000000000 +0100
@@ -296,24 +296,36 @@
             '.*net\.reactivated\.Fprint\.Error\.{}.*'.format(fprint_error))
 
     # From libfprint tests
-    def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT):
-        with Connection(self.sockaddr) as con:
+    def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT, con=None):
+        if con:
             con.sendall(struct.pack('ii', -1, retry_error))
+            return
 
-    # From libfprint tests
-    def send_error(self, error=FPrint.DeviceError.GENERAL):
         with Connection(self.sockaddr) as con:
-            con.sendall(struct.pack('ii', -2, error))
+            self.send_retry(retry_error, con)
 
     # From libfprint tests
-    def send_remove(self):
+    def send_error(self, error=FPrint.DeviceError.GENERAL, con=None):
+        if con:
+            con.sendall(struct.pack('ii', -2, error))
+            return
+
         with Connection(self.sockaddr) as con:
-            con.sendall(struct.pack('ii', -5, 0))
+            self.send_error(error, con)
 
     # From libfprint tests
-    def send_image(self, image):
-        img = self.prints[image]
+    def send_remove(self, con=None):
+        if con:
+            con.sendall(struct.pack('ii', -5, 0))
+            return
+
         with Connection(self.sockaddr) as con:
+            self.send_remove(con=con)
+
+    # From libfprint tests
+    def send_image(self, image, con=None):
+        if con:
+            img = self.prints[image]
             mem = img.get_data()
             mem = mem.tobytes()
             self.assertEqual(len(mem), img.get_width() * img.get_height())
@@ -322,6 +334,28 @@
             encoded_img += mem
 
             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):
         """ add cancellable... """
@@ -429,10 +463,12 @@
         if expected is not None:
             self.assertEqual(self._last_result, expected)
 
-    def enroll_image(self, img, finger='right-index-finger', 
expected_result='enroll-completed'):
-        self.device.EnrollStart('(s)', finger)
+    def enroll_image(self, img, device=None, finger='right-index-finger', 
expected_result='enroll-completed'):
+        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):
             self.send_image(img)
             if stage < stages - 1:
@@ -440,7 +476,7 @@
             else:
                 self.wait_for_result(expected_result)
 
-        self.device.EnrollStop()
+        device.EnrollStop()
         self.assertEqual(self._last_result, expected_result)
 
     def enroll_multiple_images(self, images_override={}, return_index=-1):
@@ -462,6 +498,29 @@
 
         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):
 
@@ -700,23 +759,7 @@
         self.device.Release()
 
     def test_claim_disconnect(self):
-        addr = os.environ['DBUS_SYSTEM_BUS_ADDRESS']
-
-        # 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)
+        bus, dev = self.get_secondary_bus_and_device()
 
         def call_done(obj, result, user_data):
             # Ignore the callback (should be an error)
@@ -726,8 +769,91 @@
         dev.Claim('(s)', 'testuser', result_handler=call_done)
 
         # Ensure the call is on the wire, then close immediately
-        dbus.flush_sync()
-        dbus.close_sync()
+        bus.flush_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)
 
@@ -843,9 +969,11 @@
         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')))
+        self.assertTrue(os.path.exists(self.state_dir))
 
     def test_enroll_invalid_storage_dir(self):
-        # Directory wil not exist yet
+        # Directory will not exist yet
         os.makedirs(self.state_dir, mode=0o500)
         self.addCleanup(os.chmod, self.state_dir, mode=0o700)
 
@@ -1214,6 +1342,12 @@
     def test_verify_retry_general(self):
         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):
         self.assertVerifyRetry(FPrint.DeviceRetry.TOO_SHORT, 
'verify-swipe-too-short')
 
@@ -1250,6 +1384,38 @@
     def test_verify_error_data_full(self):
         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):
         with self.assertFprintError('AlreadyInUse'):
             self.device.VerifyStart('(s)', self.verify_finger)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/tests/pam/test_pam_fprintd.py
 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/tests/pam/test_pam_fprintd.py
--- 
old/fprintd-v1.90.8-7d22a2b5b9d323638bb213aefb8627d897c8e482/tests/pam/test_pam_fprintd.py
  2020-12-11 16:00:28.000000000 +0100
+++ 
new/fprintd-v1.90.9-da60bddb3e5be024c6c1958437cb13e0ce0ffac8/tests/pam/test_pam_fprintd.py
  2021-01-13 13:23:24.000000000 +0100
@@ -154,6 +154,21 @@
         tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, 
expected_rv=PAM_AUTHINFO_UNAVAIL)
         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):
         self.setup_device()
         script = [
@@ -221,6 +236,31 @@
         self.assertRegex(res.info[0], r'Place your left middle finger on FDO 
Sandpaper Reader')
         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):
         self.setup_device()
         script = [

Reply via email to