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 @@
+
+
+
+
+