diff --git a/Makefile.am b/Makefile.am index 62e9de8b4018853bf2e1d308a00e2f10915b636e..095c8893aea232e3363a60d11c75cac584d64dd4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ AUTOMAKE_OPTIONS = dist-bzip2 SUBDIRS = src data tests po -EXTRA_DIST = TODO +EXTRA_DIST = TODO intltool-extract.in intltool-merge.in intltool-update.in diff --git a/autogen.sh b/autogen.sh index 096ac2016aea97294d0d8d282483c6128e61a2d8..16bc9ecfef6f7ec45983f3bad8c873b7e37b4d6e 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,6 +2,7 @@ aclocal || exit 1 autoheader || exit 1 glib-gettextize -f -c || exit 1 +intltoolize -c -f || exit 1 autoconf || exit 1 automake -a -c || exit 1 ./configure $* diff --git a/configure.ac b/configure.ac index 59d63944e217be92ce91c00a0cd714d735834956..2c2665c68e166742409d49c5471ac05fee70038b 100644 --- a/configure.ac +++ b/configure.ac @@ -11,6 +11,7 @@ GETTEXT_PACKAGE=fprintd AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, ["$GETTEXT_PACKAGE"], [Define to the Gettext package name]) AC_SUBST(GETTEXT_PACKAGE) AM_GLIB_GNU_GETTEXT +IT_PROG_INTLTOOL([0.35.0]) PKG_CHECK_MODULES(FPRINT, [libfprint > 0.1.0]) AC_SUBST(FPRINT_LIBS) @@ -24,10 +25,13 @@ PKG_CHECK_MODULES(DBUS_GLIB, "dbus-glib-1") AC_SUBST(DBUS_GLIB_LIBS) AC_SUBST(DBUS_GLIB_CFLAGS) -PKG_CHECK_MODULES(POLKIT, "polkit") +PKG_CHECK_MODULES(POLKIT, "polkit polkit-dbus") AC_SUBST(POLKIT_LIBS) AC_SUBST(POLKIT_CFLAGS) +AC_CHECK_PROG([POLKIT_POLICY_FILE_VALIDATE], + [polkit-policy-file-validate], [polkit-policy-file-validate]) + AS_AC_EXPAND(DATADIR, $datadir) DBUS_SERVICES_DIR="$DATADIR/dbus-1/services" diff --git a/data/Makefile.am b/data/Makefile.am index 0243423cf9559a47e449e9e266699e7b5d271ab3..98c9afab551ee8398b95b89656bf5f1c80942ffb 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,15 +1,21 @@ dbus_servicesdir = $(datadir)/dbus-1/system-services -dbus_confdir = $(sysconfdir)/dbus-1/system.d - dbus_services_in_files = net.reactivated.Fprint.service.in - dbus_services_DATA = $(dbus_services_in_files:.service.in=.service) $(dbus_services_DATA): $(dbus_services_in_files) sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@ +dbus_confdir = $(sysconfdir)/dbus-1/system.d dbus_conf_DATA = net.reactivated.Fprint.conf +polkitdir = $(datadir)/PolicyKit/policy +polkit_in_files = net.reactivated.fprint.device.policy.in + +@INTLTOOL_POLICY_RULE@ +polkit_DATA = $(polkit_in_files:.policy.in=.policy) + +check: + $(POLKIT_POLICY_FILE_VALIDATE) $(polkit_DATA) diff --git a/data/net.reactivated.fprint.device.policy.in b/data/net.reactivated.fprint.device.policy.in new file mode 100644 index 0000000000000000000000000000000000000000..af2eddb57dc42af4aacf33aec68153c4736845b5 --- /dev/null +++ b/data/net.reactivated.fprint.device.policy.in @@ -0,0 +1,42 @@ + + + + + + The FPrint Project + http://reactivated.net/fprint/ + fprint + + + <_description>Verify a fingerprint + <_message>Privileges are required to verify fingerprints. + + no + no + yes + + + + + <_description>Enroll new fingerprints + <_message>Privileges are required to enroll new fingerprints. + + no + no + yes + + + + + <_description>Select a user to enroll + <_message>Privileges are required to enroll new fingerprints for other users. + + no + no + auth_admin_keep_always + + + + diff --git a/src/device.c b/src/device.c index 391b4d3d211ba2c60568e22f725618585bd46831..26552a18a5b6bfb5dbb78b774f5c86726f1baaa0 100644 --- a/src/device.c +++ b/src/device.c @@ -34,6 +34,9 @@ extern DBusGConnection *fprintd_dbus_conn; +static void fprint_device_set_username(FprintDevice *rdev, + const char *username, + DBusGMethodInvocation *context); static void fprint_device_claim(FprintDevice *rdev, DBusGMethodInvocation *context); static void fprint_device_release(FprintDevice *rdev, @@ -89,9 +92,8 @@ struct FprintDevicePrivate { char *sender; /* Either the current user of the device, or if allowed, - * what was set using SetCurrentUid */ + * what was set using SetUsername */ char *username; - uid_t uid; /* type of storage */ int storage_type; @@ -257,18 +259,15 @@ _fprint_device_check_claimed (FprintDevice *rdev, } static gboolean -_check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, const char *action) +_fprint_device_check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, const char *action, GError **error) { FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); const char *sender; - GError *error; DBusError dbus_error; PolKitCaller *pk_caller; PolKitAction *pk_action; PolKitResult pk_result; - error = NULL; - /* Check that caller is privileged */ sender = dbus_g_method_get_sender (context); dbus_error_init (&dbus_error); @@ -277,38 +276,103 @@ _check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, co sender, &dbus_error); if (pk_caller == NULL) { - error = g_error_new (FPRINT_ERROR, - FPRINT_ERROR_INTERNAL, - "Error getting information about caller: %s: %s", - dbus_error.name, dbus_error.message); + g_set_error (error, FPRINT_ERROR, + FPRINT_ERROR_INTERNAL, + "Error getting information about caller: %s: %s", + dbus_error.name, dbus_error.message); dbus_error_free (&dbus_error); - dbus_g_method_return_error (context, error); - g_error_free (error); return FALSE; } pk_action = polkit_action_new (); polkit_action_set_action_id (pk_action, action); pk_result = polkit_context_is_caller_authorized (priv->pol_ctx, pk_action, pk_caller, - FALSE, NULL); + TRUE, NULL); polkit_caller_unref (pk_caller); polkit_action_unref (pk_action); if (pk_result != POLKIT_RESULT_YES) { - error = g_error_new (FPRINT_ERROR, - FPRINT_ERROR_INTERNAL, - "%s %s <-- (action, result)", - action, - polkit_result_to_string_representation (pk_result)); + g_set_error (error, FPRINT_ERROR, + FPRINT_ERROR_INTERNAL, + "%s %s <-- (action, result)", + action, + polkit_result_to_string_representation (pk_result)); dbus_error_free (&dbus_error); - dbus_g_method_return_error (context, error); - g_error_free (error); return FALSE; } return TRUE; } +static gboolean +_fprint_device_check_polkit_for_actions (FprintDevice *rdev, + DBusGMethodInvocation *context, + const char *action1, + const char *action2, + GError **error) +{ + if (_fprint_device_check_polkit_for_action (rdev, context, action1, error) != FALSE) + return TRUE; + + g_error_free (*error); + *error = NULL; + + return _fprint_device_check_polkit_for_action (rdev, context, action2, error); +} + +static void +fprint_device_set_username (FprintDevice *rdev, + const char *username, + DBusGMethodInvocation *context) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + GError *error = NULL; + struct session_data *session = priv->session; + GSList *elem = session->loaded_prints; + + if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.setusername", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + + if (username == NULL) { + dbus_g_method_return (context); + return; + } + + /* We already have a username, check if the one we're + * setting is the same */ + if (g_str_equal (username, priv->username) != FALSE) { + dbus_g_method_return (context); + return; + } + + g_free (priv->username); + priv->username = g_strdup (username); + + /* Any fingerprints to unload? */ + if (!elem) { + dbus_g_method_return (context); + return; + } + + /* Empty the fingerprints, as we have a different user */ + do { + struct loaded_print *print = elem->data; + + session->loaded_prints = g_slist_delete_link(session->loaded_prints, + elem); + g_slice_free(struct loaded_print, print); + } while ((elem = g_slist_next(elem)) != NULL); + + dbus_g_method_return (context); +} + static void dev_open_cb(struct fp_dev *dev, int status, void *user_data) { FprintDevice *rdev = user_data; @@ -353,6 +417,14 @@ static void fprint_device_claim(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_actions (rdev, context, + "net.reactivated.fprint.device.verify", + "net.reactivated.fprint.device.enroll", + &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + /* Get details about the current sender, and username/uid */ conn = dbus_g_connection_get_connection (fprintd_dbus_conn); sender = dbus_g_method_get_sender (context); @@ -430,6 +502,15 @@ static void fprint_device_release(FprintDevice *rdev, return; } + /* People that can claim can also release */ + if (_fprint_device_check_polkit_for_actions (rdev, context, + "net.reactivated.fprint.device.verify", + "net.reactivated.fprint.device.enroll", + &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + /* Unload any loaded prints */ if (elem) { do @@ -455,6 +536,11 @@ static void fprint_device_unload_print_data(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + g_message("unload print data %d for device %d", print_id, priv->id); if (!elem) { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, @@ -505,6 +591,11 @@ static void fprint_device_verify_start(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + g_message("start verification device %d print %d", priv->id, print_id); if (!elem) { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, @@ -557,6 +648,11 @@ static void fprint_device_verify_stop(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + r = fp_async_verify_stop(priv->dev, verify_stop_cb, context); if (r < 0) { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_STOP, @@ -598,6 +694,11 @@ static void fprint_device_enroll_start(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + g_message("start enrollment device %d finger %d", priv->id, finger_num); session->enroll_finger = finger_num; @@ -629,6 +730,11 @@ static void fprint_device_enroll_stop(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context); if (r < 0) { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_STOP, @@ -666,6 +772,11 @@ static void fprint_device_list_enrolled_fingers(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + prints = storages[priv->storage_type].discover_prints(priv->dev, priv->username); if (!prints) { g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS, @@ -700,6 +811,11 @@ static void fprint_device_load_print_data(FprintDevice *rdev, return; } + if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) { + dbus_g_method_return_error (context, error); + return; + } + r = storages[priv->storage_type].print_data_load(priv->dev, (enum fp_finger)finger_num, &data, priv->username); diff --git a/src/device.xml b/src/device.xml index 6ef580167df9ede84122b2ce275400f8843616d0..f7d16560e1e6fc7f96ba14445b5569c429b895e6 100644 --- a/src/device.xml +++ b/src/device.xml @@ -60,6 +60,11 @@ + + + + +