mirror of
https://gitlab.com/mishakmak/pam-fprint-grosshack.git
synced 2026-04-11 13:23:33 +02:00
Compare commits
175 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 267b322f6d | |||
| 3b83240e57 | |||
| 897cbd341e | |||
| 9d0305ea05 | |||
| 3dbfdabe01 | |||
| 45cf63d589 | |||
| 29ed88a50a | |||
| e301779c20 | |||
| be5d283a3e | |||
| ebfcbdd13e | |||
| ec7376d7e6 | |||
| df568e1ce1 | |||
| 7ee61393ec | |||
| 57ca0dc95e | |||
| 85ba309e9d | |||
| 3f2174676e | |||
| 5e18d46971 | |||
| a8bd2bc25e | |||
| 88a627f187 | |||
| a8818f9bfb | |||
| c5a3089f89 | |||
| 5de1261df6 | |||
| e5c82d7b96 | |||
| 9c842e2c2f | |||
| ec5cce083c | |||
| ab8118bde2 | |||
| 08fb209aed | |||
| 6eb9f263fd | |||
| 74d05e7996 | |||
| 83cd09ba2f | |||
| 8ed77829a7 | |||
| b63c76319f | |||
| fd9a86eca4 | |||
| 38ba7199b7 | |||
| 827baff301 | |||
| 6a5d46c8b0 | |||
| 1ae0f4926d | |||
| e1c2698807 | |||
| b14bfd8226 | |||
| 1e2f360ade | |||
| 778a8540aa | |||
| 4e707f0d31 | |||
| 4c78012103 | |||
| e59f3cbc4f | |||
| 1a860aa882 | |||
| a183b779ec | |||
| 9d6c7eb1a9 | |||
| 110c0018a2 | |||
| 5611317c72 | |||
| 0904c8a527 | |||
| a681996d1d | |||
| 4e7cf47a3d | |||
| 9d3f3fcaca | |||
| 30474a6546 | |||
| 93bad82540 | |||
| e224913b80 | |||
| b2cae5cccf | |||
| 3419901f65 | |||
| c85ca09e35 | |||
| ecc02cb588 | |||
| 091f373109 | |||
| f6eb3b3ea5 | |||
| d7ca9e6095 | |||
| 6797928884 | |||
| d6c70be822 | |||
| d33a7c7e9d | |||
| 94d3a18dcd | |||
| 5635383c96 | |||
| ac98b881be | |||
| 629f7fcc11 | |||
| 5a703baa20 | |||
| 6641cb6da8 | |||
| 870b48637a | |||
| 4b0cde81fd | |||
| 59b3d2af8d | |||
| 93bcac946e | |||
| a5063dc0e4 | |||
| 5fbc38c938 | |||
| c42e627ddd | |||
| 2fd86624e5 | |||
| 6dc699ae6f | |||
| e075d37590 | |||
| 18d6a86e9d | |||
| 14051cac76 | |||
| 4e47222962 | |||
| c07a63da99 | |||
| 812a3552a6 | |||
| ff06a301f0 | |||
| 19353c971c | |||
| 290e56023f | |||
| efe92a7c33 | |||
| a7cf0ae3b2 | |||
| ba60533f71 | |||
| fcd2d65490 | |||
| 6dd010f05c | |||
| 714f499ab6 | |||
| d72c802415 | |||
| 184e1bd4d0 | |||
| f401f399a8 | |||
| 3dd0018f23 | |||
| 90298134a2 | |||
| 8ff4360750 | |||
| fd733e55be | |||
| 6a1fffae82 | |||
| 47bd3f7fbb | |||
| 4f3589c0dc | |||
| eccd790df7 | |||
| bc29114a2c | |||
| cf95187268 | |||
| 23c37cd9b5 | |||
| 967e4f24ed | |||
| d7fec03f24 | |||
| 4a3ae5ccaf | |||
| e828ea3b2d | |||
| d27872ff86 | |||
| cfbded36e1 | |||
| 072fbc2b46 | |||
| 7846359b65 | |||
| 08339a0648 | |||
| 3dd10b4b37 | |||
| bee2e154b1 | |||
| 27f0b64d03 | |||
| f4ee2f86a3 | |||
| 04829ed39f | |||
| 756a80a63e | |||
| b861500a9f | |||
| 154d0c0373 | |||
| b2cdc1ed1e | |||
| ab47e03f05 | |||
| f92801a15c | |||
| 086ceb98ab | |||
| 8bdbc7e2b0 | |||
| 1f8bb1abd4 | |||
| 47d55a97c4 | |||
| 657b90a066 | |||
| 3821b96ca5 | |||
| 22ad9b5ae8 | |||
| 2ddc8a86a2 | |||
| 930cae4647 | |||
| 5e9624bef5 | |||
| efac52d94f | |||
| af18aa35e5 | |||
| 0d7a703200 | |||
| ad19c49e2e | |||
| a8de1003a4 | |||
| cefe939141 | |||
| 24cd986476 | |||
| 06480c7994 | |||
| b2ad590891 | |||
| 85aad7bb01 | |||
| 0fb4f3b021 | |||
| 21564885ea | |||
| 6064e30200 | |||
| fd8297306c | |||
| e7f804e9fc | |||
| 0e993d92e2 | |||
| b312a5e540 | |||
| c12778ec5b | |||
| dbabd4d7d3 | |||
| db1865eb3e | |||
| 10a3e75937 | |||
| 01ea517a97 | |||
| 3a98ef646b | |||
| 750a815fdf | |||
| 53fcf52989 | |||
| 52e12459df | |||
| 554df2a8d9 | |||
| 681bd1ed2a | |||
| 8890732194 | |||
| 7dac81dcad | |||
| 1ecae1d014 | |||
| ba7a45d3f8 | |||
| 49dced5566 | |||
| e25544a8f0 | |||
| ee8589ec9d |
@ -8,9 +8,9 @@ include:
|
||||
|
||||
variables:
|
||||
extends: .libfprint_common_variables
|
||||
FEDORA_TAG: rawhide
|
||||
FEDORA_VERSION: rawhide
|
||||
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FEDORA_VERSION:$FEDORA_TAG"
|
||||
FDO_DISTRIBUTION_TAG: latest
|
||||
FDO_DISTRIBUTION_VERSION: rawhide
|
||||
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||
DEPENDENCIES: dbus-glib-devel
|
||||
gcc
|
||||
gcovr
|
||||
@ -18,6 +18,7 @@ variables:
|
||||
git
|
||||
glibc-devel
|
||||
gtk-doc
|
||||
libasan
|
||||
libfprint-devel
|
||||
meson
|
||||
pam-devel
|
||||
@ -28,7 +29,12 @@ variables:
|
||||
|
||||
image: "$FEDORA_IMAGE"
|
||||
|
||||
.install_libfprint_dev: &install_libfprint_dev
|
||||
.fprintd_build_preconditions:
|
||||
except:
|
||||
variables:
|
||||
- $FPRINT_CRON_TASK == "BUILD_CI_IMAGES"
|
||||
|
||||
.install_libfprint_dev:
|
||||
before_script:
|
||||
# Make sure we don't build or link against the system libfprint
|
||||
- dnf remove -y libfprint-devel
|
||||
@ -42,21 +48,16 @@ image: "$FEDORA_IMAGE"
|
||||
- echo "libfprint/demo/gtk-libfprint-test.ui" >> po/POTFILES.skip
|
||||
|
||||
build_stable:
|
||||
except:
|
||||
variables:
|
||||
- $FPRINT_CRON_TASK == "BUILD_CI_IMAGES"
|
||||
# FIXME: Stable builds will fail until libfprintv 2 reaches rawhide
|
||||
allow_failure: true
|
||||
extends: .fprintd_build_preconditions
|
||||
script:
|
||||
- meson _build
|
||||
- ninja -C _build -v
|
||||
- ninja -C _build -v install
|
||||
|
||||
build_dev:
|
||||
except:
|
||||
variables:
|
||||
- $FPRINT_CRON_TASK == "BUILD_CI_IMAGES"
|
||||
<<: *install_libfprint_dev
|
||||
extends:
|
||||
- .fprintd_build_preconditions
|
||||
- .install_libfprint_dev
|
||||
script:
|
||||
- meson _build --werror -Dgtk_doc=true
|
||||
- ninja -C _build -v
|
||||
@ -68,11 +69,10 @@ build_dev:
|
||||
- _build/meson-logs/*.txt
|
||||
|
||||
test_dev:
|
||||
except:
|
||||
variables:
|
||||
- $FPRINT_CRON_TASK == "BUILD_CI_IMAGES"
|
||||
extends:
|
||||
- .fprintd_build_preconditions
|
||||
- .install_libfprint_dev
|
||||
stage: test
|
||||
<<: *install_libfprint_dev
|
||||
script:
|
||||
- meson _build -Db_coverage=true
|
||||
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
|
||||
@ -84,15 +84,29 @@ test_dev:
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
|
||||
test_dev_with_sanitizer:
|
||||
extends:
|
||||
- .fprintd_build_preconditions
|
||||
- .install_libfprint_dev
|
||||
stage: test
|
||||
script:
|
||||
- meson _build -Db_sanitize=address
|
||||
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 5
|
||||
artifacts:
|
||||
name: meson-logs
|
||||
when: on_failure
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
|
||||
# CONTAINERS creation stage
|
||||
container_fedora_build:
|
||||
extends: .fedora@container-build
|
||||
extends: .fdo.container-build@fedora
|
||||
only:
|
||||
variables:
|
||||
- $FPRINT_CRON_TASK == "BUILD_CI_IMAGES"
|
||||
variables:
|
||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||
# a list of packages to install
|
||||
FEDORA_RPMS:
|
||||
FDO_DISTRIBUTION_PACKAGES:
|
||||
$DEPENDENCIES
|
||||
$LIBFPRINT_DEPENDENCIES
|
||||
|
||||
23
NEWS
23
NEWS
@ -1,6 +1,29 @@
|
||||
This file lists notable changes in each release. For the full history of all
|
||||
changes, see ChangeLog.
|
||||
|
||||
Version 1.90.5:
|
||||
|
||||
The 1.90.4 release contained some bad errors, this release addresses those.
|
||||
|
||||
Highlights:
|
||||
- Permit building with polkit older than 0.114
|
||||
- Fix possible issues with PAM test
|
||||
- Fix incorrect DBus policy
|
||||
- Fix build so that CFLAGS enviroment is correctly used
|
||||
- Skip hotplug test with older libfprint (which times out otherwise)
|
||||
|
||||
Version 1.90.4:
|
||||
|
||||
This fprintd release contains major core reworkings and improved testing.
|
||||
As such, only the most important changes are listed here, focusing on
|
||||
changes relevant to distributors.
|
||||
|
||||
Highlights:
|
||||
- Authentication is now required to enroll a new print (#5)
|
||||
- Add support for the libfprint early reporting mechanism
|
||||
- Proper hotplug support together with libfprint 1.90.4
|
||||
- Handle STATE_DIRECTORY containing multiple paths
|
||||
|
||||
version 1.90.1:
|
||||
- Add support for prints saved on the fingerprint device itself
|
||||
- Add integration tests using the virtual image driver, and further
|
||||
|
||||
@ -9,3 +9,6 @@
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#mesondefine VERSION
|
||||
|
||||
/* Whether current polkit version supports autopointers */
|
||||
#mesondefine POLKIT_HAS_AUTOPOINTERS
|
||||
|
||||
@ -12,8 +12,16 @@
|
||||
|
||||
<!-- Anyone can talk to the service -->
|
||||
<policy context="default">
|
||||
<allow send_destination="net.reactivated.Fprint"/>
|
||||
<allow send_interface="net.reactivated.Fprint"/>
|
||||
<allow send_destination="net.reactivated.Fprint"
|
||||
send_interface="net.reactivated.Fprint"/>
|
||||
|
||||
<!-- Basic D-Bus API stuff -->
|
||||
<allow send_destination="net.reactivated.Fprint"
|
||||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||
<allow send_destination="net.reactivated.Fprint"
|
||||
send_interface="org.freedesktop.DBus.Properties"/>
|
||||
<allow send_destination="net.reactivated.Fprint"
|
||||
send_interface="org.freedesktop.DBus.ObjectManager"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<defaults>
|
||||
<allow_any>no</allow_any>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
<allow_active>auth_self_keep</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ docbook_xml_header = custom_target('docbook_xml_header',
|
||||
output: 'docbook-xml-header.xml',
|
||||
command: [
|
||||
'echo', '-n',
|
||||
'<?xml version="1.0"?>',
|
||||
'<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">',
|
||||
'<?xml version="1.0"?>\n',
|
||||
'<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n',
|
||||
],
|
||||
capture: true,
|
||||
)
|
||||
|
||||
48
meson.build
48
meson.build
@ -1,9 +1,9 @@
|
||||
project('fprintd', 'c',
|
||||
version: '1.90.1',
|
||||
version: '1.90.5',
|
||||
license: 'GPLv2+',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
'warning_level=1',
|
||||
'warning_level=3',
|
||||
'c_std=gnu99',
|
||||
],
|
||||
meson_version: '>= 0.50.0')
|
||||
@ -12,23 +12,8 @@ gnome = import('gnome')
|
||||
i18n = import('i18n')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
host_system = host_machine.system()
|
||||
glib_min_version = '2.56'
|
||||
libfprint_min_version = '1.90.0'
|
||||
|
||||
fprintd_installdir = get_option('prefix') / get_option('libexecdir')
|
||||
fprintd_plugindir = get_option('prefix') / get_option('libdir') / meson.project_name() / 'modules'
|
||||
storage_path = get_option('prefix') / get_option('localstatedir') / 'lib/fprint'
|
||||
localedir = get_option('prefix') / get_option('localedir')
|
||||
datadir = get_option('prefix') / get_option('datadir')
|
||||
sysconfdir = get_option('sysconfdir')
|
||||
if get_option('prefix') != '/usr'
|
||||
sysconfdir = get_option('prefix') / sysconfdir
|
||||
endif
|
||||
|
||||
common_cflags = cc.get_supported_arguments([
|
||||
'-fno-strict-aliasing',
|
||||
'-Wall',
|
||||
'-Wcast-align',
|
||||
'-Werror=address',
|
||||
'-Werror=array-bounds',
|
||||
@ -67,14 +52,37 @@ common_cflags = cc.get_supported_arguments([
|
||||
])
|
||||
add_project_arguments(common_cflags, language: 'c')
|
||||
|
||||
common_cflags = cc.get_supported_arguments([
|
||||
# The stub passes a lot of params that we do not use, maybe a good idea to
|
||||
# mark it appropriately, but this works well for now.
|
||||
'-Wno-unused-parameter',
|
||||
# We use g_signal_handlers_disconnect_* which is not compatible with -Wpedantic
|
||||
'-Wno-pedantic',
|
||||
])
|
||||
add_project_arguments(common_cflags, language: 'c')
|
||||
|
||||
host_system = host_machine.system()
|
||||
glib_min_version = '2.56'
|
||||
libfprint_min_version = '1.90.1'
|
||||
|
||||
fprintd_installdir = get_option('prefix') / get_option('libexecdir')
|
||||
fprintd_plugindir = get_option('prefix') / get_option('libdir') / meson.project_name() / 'modules'
|
||||
storage_path = get_option('prefix') / get_option('localstatedir') / 'lib/fprint'
|
||||
localedir = get_option('prefix') / get_option('localedir')
|
||||
datadir = get_option('prefix') / get_option('datadir')
|
||||
sysconfdir = get_option('sysconfdir')
|
||||
if get_option('prefix') != '/usr'
|
||||
sysconfdir = get_option('prefix') / sysconfdir
|
||||
endif
|
||||
|
||||
# Dependencies
|
||||
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
|
||||
gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version)
|
||||
gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
|
||||
gmodule_dep = dependency('gmodule-2.0', version: '>=' + glib_min_version)
|
||||
libfprint_dep = dependency('libfprint-2', version: '>=' + libfprint_min_version)
|
||||
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.91')
|
||||
dbus_dep = dependency('dbus-1', required: false)
|
||||
dbus_glib_dep = dependency('dbus-glib-1')
|
||||
libsystemd_dep = dependency('libsystemd', required: get_option('pam'))
|
||||
pam_dep = cc.find_library('pam',
|
||||
required: get_option('pam'),
|
||||
@ -125,6 +133,7 @@ python3_test_modules = {
|
||||
'dbus': true,
|
||||
'dbusmock': true,
|
||||
'gi': true,
|
||||
'gi.repository.FPrint': true,
|
||||
'pypamtest': get_option('pam'),
|
||||
}
|
||||
python3_available_modules = []
|
||||
@ -140,6 +149,7 @@ cdata.set_quoted('GETTEXT_PACKAGE', meson.project_name())
|
||||
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
cdata.set_quoted('VERSION', meson.project_version())
|
||||
cdata.set_quoted('SYSCONFDIR', sysconfdir)
|
||||
cdata.set('POLKIT_HAS_AUTOPOINTERS', polkit_gobject_dep.version().version_compare('>= 0.114'))
|
||||
|
||||
config_h = configure_file(
|
||||
input: 'config.h.in',
|
||||
@ -178,5 +188,7 @@ output += ' PAM module: ' + pam_dep.found().to_string()
|
||||
output += ' Manuals: ' + get_option('man').to_string()
|
||||
output += ' GTK Doc: ' + get_option('gtk_doc').to_string()
|
||||
output += ' XML Linter ' + xmllint.found().to_string()
|
||||
output += '\nTest setup:\n'
|
||||
output += ' With address sanitizer: ' + address_sanitizer.to_string()
|
||||
|
||||
message('\n'+'\n'.join(output)+'\n')
|
||||
|
||||
@ -153,16 +153,16 @@ GNUC_UNUSED static const char *verify_result_str_to_msg(const char *result, bool
|
||||
|
||||
if (strcmp (result, "verify-retry-scan") == 0) {
|
||||
if (is_swipe == false)
|
||||
return N_("Place your finger on the reader again");
|
||||
return TR (N_("Place your finger on the reader again"));
|
||||
else
|
||||
return N_("Swipe your finger again");
|
||||
return TR (N_("Swipe your finger again"));
|
||||
}
|
||||
if (strcmp (result, "verify-swipe-too-short") == 0)
|
||||
return N_("Swipe was too short, try again");
|
||||
return TR (N_("Swipe was too short, try again"));
|
||||
if (strcmp (result, "verify-finger-not-centered") == 0)
|
||||
return N_("Your finger was not centered, try swiping your finger again");
|
||||
return TR (N_("Your finger was not centered, try swiping your finger again"));
|
||||
if (strcmp (result, "verify-remove-and-retry") == 0)
|
||||
return N_("Remove your finger, and try swiping your finger again");
|
||||
return TR (N_("Remove your finger, and try swiping your finger again"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -179,16 +179,16 @@ GNUC_UNUSED static const char *enroll_result_str_to_msg(const char *result, bool
|
||||
|
||||
if (strcmp (result, "enroll-retry-scan") == 0 || strcmp (result, "enroll-stage-passed") == 0) {
|
||||
if (is_swipe == false)
|
||||
return N_("Place your finger on the reader again");
|
||||
return TR (N_("Place your finger on the reader again"));
|
||||
else
|
||||
return N_("Swipe your finger again");
|
||||
return TR (N_("Swipe your finger again"));
|
||||
}
|
||||
if (strcmp (result, "enroll-swipe-too-short") == 0)
|
||||
return N_("Swipe was too short, try again");
|
||||
return TR (N_("Swipe was too short, try again"));
|
||||
if (strcmp (result, "enroll-finger-not-centered") == 0)
|
||||
return N_("Your finger was not centered, try swiping your finger again");
|
||||
return TR (N_("Your finger was not centered, try swiping your finger again"));
|
||||
if (strcmp (result, "enroll-remove-and-retry") == 0)
|
||||
return N_("Remove your finger, and try swiping your finger again");
|
||||
return TR (N_("Remove your finger, and try swiping your finger again"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ verify_result (sd_bus_message *m,
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg = _(verify_result_str_to_msg (result, data->is_swipe));
|
||||
msg = verify_result_str_to_msg (result, data->is_swipe);
|
||||
send_err_msg (data->pamh, msg);
|
||||
|
||||
return 0;
|
||||
@ -217,7 +217,7 @@ verify_finger_selected (sd_bus_message *m,
|
||||
char *msg;
|
||||
|
||||
if (sd_bus_message_read_basic (m, 's', &finger_name) < 0) {
|
||||
pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyFingerSelected signal: %m");
|
||||
pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyFingerSelected signal: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -423,12 +423,10 @@ do_verify (pam_handle_t *pamh,
|
||||
ret = PAM_AUTHINFO_UNAVAIL;
|
||||
} else if (str_equal (data->result, "verify-disconnected")) {
|
||||
ret = PAM_AUTHINFO_UNAVAIL;
|
||||
free (data->result);
|
||||
break;
|
||||
} else {
|
||||
send_info_msg (data->pamh, _("An unknown error occurred"));
|
||||
send_err_msg (data->pamh, _("An unknown error occurred"));
|
||||
ret = PAM_AUTH_ERR;
|
||||
free (data->result);
|
||||
break;
|
||||
}
|
||||
free (data->result);
|
||||
@ -560,7 +558,7 @@ static int do_auth(pam_handle_t *pamh, const char *username)
|
||||
sd_bus *bus = NULL;
|
||||
|
||||
if (sd_bus_open_system (&bus) < 0) {
|
||||
pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %m");
|
||||
pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %d", errno);
|
||||
return PAM_AUTHINFO_UNAVAIL;
|
||||
}
|
||||
|
||||
@ -615,7 +613,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
|
||||
const char **argv)
|
||||
{
|
||||
const char *username;
|
||||
unsigned i;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
|
||||
1169
src/device.c
1169
src/device.c
File diff suppressed because it is too large
Load Diff
@ -12,9 +12,6 @@
|
||||
|
||||
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
|
||||
<interface name="net.reactivated.Fprint.Device">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol"
|
||||
value="fprint_device" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:title id="polkit-integration">
|
||||
PolicyKit integration
|
||||
@ -282,8 +279,6 @@
|
||||
<arg type="as" name="enrolled_fingers" direction="out">
|
||||
<doc:doc><doc:summary>An array of strings representing the enrolled fingerprints. See <doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.</doc:summary></doc:doc>
|
||||
</arg>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -304,8 +299,6 @@
|
||||
<arg type="s" name="username" direction="in">
|
||||
<doc:doc><doc:summary>The username for whom to delete the enrolled fingerprints. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
|
||||
</arg>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -327,8 +320,6 @@
|
||||
<!-- ************************************************************ -->
|
||||
|
||||
<method name="DeleteEnrolledFingers2">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -348,8 +339,6 @@
|
||||
<arg type="s" name="username" direction="in">
|
||||
<doc:doc><doc:summary>The username for whom to claim the device. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
|
||||
</arg>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -368,8 +357,6 @@
|
||||
<!-- ************************************************************ -->
|
||||
|
||||
<method name="Release">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -390,8 +377,6 @@
|
||||
<arg type="s" name="finger_name" direction="in">
|
||||
<doc:doc><doc:summary>A string representing the finger to verify. See <doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.</doc:summary></doc:doc>
|
||||
</arg>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -415,8 +400,6 @@
|
||||
<!-- ************************************************************ -->
|
||||
|
||||
<method name="VerifyStop">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -486,8 +469,6 @@
|
||||
<doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.
|
||||
Note that "any" is not a valid finger name for this method.</doc:summary></doc:doc>
|
||||
</arg>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
@ -511,8 +492,6 @@
|
||||
<!-- ************************************************************ -->
|
||||
|
||||
<method name="EnrollStop">
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value="" />
|
||||
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
|
||||
@ -42,18 +42,33 @@
|
||||
#define FILE_STORAGE_PATH "/var/lib/fprint"
|
||||
#define DIR_PERMS 0700
|
||||
|
||||
static char *storage_path = NULL;
|
||||
|
||||
static const char *get_storage_path(void)
|
||||
{
|
||||
const char *path;
|
||||
const char *path = NULL;
|
||||
|
||||
if (storage_path != NULL)
|
||||
return storage_path;
|
||||
|
||||
/* set by systemd >= 240 to an absolute path
|
||||
* taking into account the StateDirectory
|
||||
* unit file setting */
|
||||
path = g_getenv ("STATE_DIRECTORY");
|
||||
if (path != NULL)
|
||||
return path;
|
||||
if (path != NULL) {
|
||||
/* If multiple directories are set, then in the environment variable
|
||||
* the paths are concatenated with colon (":"). */
|
||||
if (strchr (path, ':')) {
|
||||
g_auto(GStrv) elems = NULL;
|
||||
elems = g_strsplit (path, ":", -1);
|
||||
storage_path = g_strdup (elems[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return FILE_STORAGE_PATH;
|
||||
if (storage_path == NULL)
|
||||
storage_path = g_strdup (FILE_STORAGE_PATH);
|
||||
|
||||
return storage_path;
|
||||
}
|
||||
|
||||
static char *get_path_to_storedir(const char *driver, const char * device_id, char *base_store)
|
||||
@ -64,7 +79,7 @@ static char *get_path_to_storedir(const char *driver, const char * device_id, ch
|
||||
static char *__get_path_to_print(const char *driver, const char * device_id,
|
||||
FpFinger finger, char *base_store)
|
||||
{
|
||||
char *dirpath;
|
||||
g_autofree char *dirpath = NULL;
|
||||
char *path;
|
||||
char fingername[2];
|
||||
|
||||
@ -72,7 +87,6 @@ static char *__get_path_to_print(const char *driver, const char * device_id,
|
||||
|
||||
dirpath = get_path_to_storedir(driver, device_id, base_store);
|
||||
path = g_build_filename(dirpath, fingername, NULL);
|
||||
g_free(dirpath);
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -173,7 +187,7 @@ int file_storage_print_data_load(FpDevice *dev,
|
||||
{
|
||||
g_autofree gchar *path = NULL;
|
||||
g_autofree gchar *base_store = NULL;
|
||||
FpPrint *new = NULL;
|
||||
g_autoptr(FpPrint) new = NULL;
|
||||
int r;
|
||||
|
||||
base_store = file_storage_get_basestore_for_username(username);
|
||||
@ -186,11 +200,10 @@ int file_storage_print_data_load(FpDevice *dev,
|
||||
return r;
|
||||
|
||||
if (!fp_print_compatible (new, dev)) {
|
||||
g_object_unref (new);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*print = new;
|
||||
*print = g_steal_pointer (&new);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -296,6 +309,6 @@ int file_storage_init(void)
|
||||
|
||||
int file_storage_deinit(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
g_clear_pointer (&storage_path, g_free);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
VOID:STRING,BOOLEAN
|
||||
@ -20,31 +20,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <fprint.h>
|
||||
#include "fprintd-enums.h"
|
||||
#include "fprintd-dbus.h"
|
||||
|
||||
/* General */
|
||||
#define TIMEOUT 30
|
||||
#define FPRINT_SERVICE_NAME "net.reactivated.Fprint"
|
||||
#define FPRINT_SERVICE_PATH "/net/reactivated/Fprint"
|
||||
|
||||
/* Errors */
|
||||
GQuark fprint_error_quark(void);
|
||||
GType fprint_error_get_type(void);
|
||||
|
||||
#define FPRINT_ERROR fprint_error_quark()
|
||||
#define FPRINT_TYPE_ERROR fprint_error_get_type()
|
||||
#define FPRINT_ERROR_DBUS_INTERFACE "net.reactivated.Fprint.Error"
|
||||
typedef enum {
|
||||
FPRINT_ERROR_CLAIM_DEVICE, /* developer didn't claim the device */
|
||||
FPRINT_ERROR_ALREADY_IN_USE, /* device is already claimed by somebody else */
|
||||
FPRINT_ERROR_INTERNAL, /* internal error occurred */
|
||||
FPRINT_ERROR_PERMISSION_DENIED, /* PolicyKit refused the action */
|
||||
FPRINT_ERROR_NO_ENROLLED_PRINTS, /* No prints are enrolled */
|
||||
FPRINT_ERROR_NO_ACTION_IN_PROGRESS, /* No actions currently in progress */
|
||||
FPRINT_ERROR_INVALID_FINGERNAME, /* the finger name passed was invalid */
|
||||
FPRINT_ERROR_NO_SUCH_DEVICE, /* device does not exist */
|
||||
/* developer didn't claim the device */
|
||||
FPRINT_ERROR_CLAIM_DEVICE, /*< nick=net.reactivated.Fprint.Error.ClaimDevice >*/
|
||||
/* device is already claimed by somebody else */
|
||||
FPRINT_ERROR_ALREADY_IN_USE, /*< nick=net.reactivated.Fprint.Error.AlreadyInUse >*/
|
||||
/* internal error occurred */
|
||||
FPRINT_ERROR_INTERNAL, /*< nick=net.reactivated.Fprint.Error.Internal >*/
|
||||
/* PolicyKit refused the action */
|
||||
FPRINT_ERROR_PERMISSION_DENIED, /*< nick=net.reactivated.Fprint.Error.PermissionDenied >*/
|
||||
/* No prints are enrolled */
|
||||
FPRINT_ERROR_NO_ENROLLED_PRINTS, /*< nick=net.reactivated.Fprint.Error.NoEnrolledPrints >*/
|
||||
/* No actions currently in progress */
|
||||
FPRINT_ERROR_NO_ACTION_IN_PROGRESS, /*< nick=net.reactivated.Fprint.Error.NoActionInProgress >*/
|
||||
/* the finger name passed was invalid */
|
||||
FPRINT_ERROR_INVALID_FINGERNAME, /*< nick=net.reactivated.Fprint.Error.InvalidFingername >*/
|
||||
/* device does not exist */
|
||||
FPRINT_ERROR_NO_SUCH_DEVICE, /*< nick=net.reactivated.Fprint.Error.NoSuchDevice >*/
|
||||
} FprintError;
|
||||
|
||||
typedef enum {
|
||||
FPRINT_DEVICE_PERMISSION_NONE = 0,
|
||||
FPRINT_DEVICE_PERMISSION_ENROLL = (1 << 0), /*< nick=net.reactivated.fprint.device.enroll >*/
|
||||
FPRINT_DEVICE_PERMISSION_SETUSERNAME = (1 << 1), /*< nick=net.reactivated.fprint.device.setusername >*/
|
||||
FPRINT_DEVICE_PERMISSION_VERIFY = (1 << 2), /*< nick=net.reactivated.fprint.device.verify >*/
|
||||
} FprintDevicePermission;
|
||||
|
||||
/* Manager */
|
||||
#define FPRINT_TYPE_MANAGER (fprint_manager_get_type())
|
||||
G_DECLARE_FINAL_TYPE (FprintManager, fprint_manager, FPRINT, MANAGER, GObject)
|
||||
@ -53,23 +68,18 @@ struct _FprintManager {
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
FprintManager *fprint_manager_new(gboolean no_timeout);
|
||||
FprintManager *fprint_manager_new (GDBusConnection *connection, gboolean no_timeout);
|
||||
|
||||
/* Device */
|
||||
#define FPRINT_TYPE_DEVICE (fprint_device_get_type())
|
||||
G_DECLARE_FINAL_TYPE (FprintDevice, fprint_device, FPRINT, DEVICE, GObject)
|
||||
G_DECLARE_FINAL_TYPE (FprintDevice, fprint_device, FPRINT, DEVICE,
|
||||
FprintDBusDeviceSkeleton)
|
||||
|
||||
struct _FprintDevice {
|
||||
GObject parent;
|
||||
FprintDBusDeviceSkeleton parent;
|
||||
};
|
||||
|
||||
FprintDevice *fprint_device_new(FpDevice *dev);
|
||||
guint32 _fprint_device_get_id(FprintDevice *rdev);
|
||||
/* Print */
|
||||
/* TODO */
|
||||
|
||||
/* Binding data included in main.c through server-bindings.h which individual
|
||||
* class implementations need to access.
|
||||
*/
|
||||
extern const DBusGObjectInfo dbus_glib_fprint_manager_object_info;
|
||||
extern const DBusGObjectInfo dbus_glib_fprint_device_object_info;
|
||||
|
||||
106
src/main.c
106
src/main.c
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* fprint D-Bus daemon
|
||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -19,10 +20,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <dbus/dbus-glib-bindings.h>
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <fprint.h>
|
||||
@ -36,7 +38,6 @@
|
||||
|
||||
fp_storage store;
|
||||
|
||||
DBusGConnection *fprintd_dbus_conn = NULL;
|
||||
static gboolean no_timeout = FALSE;
|
||||
static gboolean g_fatal_warnings = FALSE;
|
||||
|
||||
@ -56,11 +57,10 @@ static gboolean
|
||||
load_storage_module (const char *module_name)
|
||||
{
|
||||
GModule *module;
|
||||
char *filename;
|
||||
g_autofree char *filename = NULL;
|
||||
|
||||
filename = g_module_build_path (PLUGINDIR, module_name);
|
||||
module = g_module_open (filename, 0);
|
||||
g_free (filename);
|
||||
if (module == NULL)
|
||||
return FALSE;
|
||||
|
||||
@ -82,46 +82,29 @@ load_storage_module (const char *module_name)
|
||||
static gboolean
|
||||
load_conf (void)
|
||||
{
|
||||
GKeyFile *file;
|
||||
char *filename;
|
||||
char *module_name;
|
||||
GError *error = NULL;
|
||||
gboolean ret;
|
||||
g_autofree char *filename = NULL;
|
||||
g_autofree char *module_name = NULL;
|
||||
g_autoptr(GKeyFile) file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
filename = g_build_filename (SYSCONFDIR, "fprintd.conf", NULL);
|
||||
file = g_key_file_new ();
|
||||
g_debug("About to load configuration file '%s'", filename);
|
||||
if (!g_key_file_load_from_file (file, filename, G_KEY_FILE_NONE, &error)) {
|
||||
g_warning ("Could not open \"%s\": %s\n", filename, error->message);
|
||||
goto bail;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
filename = NULL;
|
||||
|
||||
module_name = g_key_file_get_string (file, "storage", "type", &error);
|
||||
if (module_name == NULL)
|
||||
goto bail;
|
||||
|
||||
g_key_file_free (file);
|
||||
return FALSE;
|
||||
|
||||
if (g_str_equal (module_name, "file")) {
|
||||
g_free (module_name);
|
||||
set_storage_file ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ret = load_storage_module (module_name);
|
||||
g_free (module_name);
|
||||
|
||||
return ret;
|
||||
|
||||
bail:
|
||||
g_key_file_free (file);
|
||||
g_free (filename);
|
||||
g_error_free (error);
|
||||
|
||||
return FALSE;
|
||||
return load_storage_module (module_name);
|
||||
}
|
||||
|
||||
static const GOptionEntry entries[] = {
|
||||
@ -138,13 +121,33 @@ static gboolean sigterm_callback(gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_acquired (GDBusConnection *connection,
|
||||
const char *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_debug ("D-Bus service launched with name: %s", name);
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_lost (GDBusConnection *connection,
|
||||
const char *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_warning ("Failed to get name: %s", name);
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GOptionContext *context;
|
||||
GMainLoop *loop;
|
||||
GError *error = NULL;
|
||||
FprintManager *manager;
|
||||
DBusGProxy *driver_proxy;
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(GMainLoop) loop = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FprintManager) manager = NULL;
|
||||
g_autoptr(GDBusConnection) connection = NULL;
|
||||
guint32 request_name_ret;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
@ -158,7 +161,6 @@ int main(int argc, char **argv)
|
||||
|
||||
if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
|
||||
g_warning ("couldn't parse command-line options: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -170,16 +172,13 @@ int main(int argc, char **argv)
|
||||
g_log_set_always_fatal (fatal_mask);
|
||||
}
|
||||
|
||||
/* Obtain a connection to the session bus */
|
||||
fprintd_dbus_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (fprintd_dbus_conn == NULL) {
|
||||
/* Obtain a connection to the system bus */
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
if (!G_IS_DBUS_CONNECTION (connection)) {
|
||||
g_warning("Failed to open connection to bus: %s", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
driver_proxy = dbus_g_proxy_new_for_name(fprintd_dbus_conn,
|
||||
DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
|
||||
|
||||
/* Load the configuration file,
|
||||
* and the default storage plugin */
|
||||
if (!load_conf())
|
||||
@ -192,33 +191,24 @@ int main(int argc, char **argv)
|
||||
g_debug("Launching FprintObject");
|
||||
|
||||
/* create the one instance of the Manager object to be shared between
|
||||
* all fprintd users */
|
||||
manager = fprint_manager_new(no_timeout);
|
||||
* all fprintd users. This blocks until all the devices are enumerated */
|
||||
manager = fprint_manager_new (connection, no_timeout);
|
||||
|
||||
/* Obtain the well-known name after the manager has been initialized.
|
||||
* Otherwise a client immediately enumerating the devices will not see
|
||||
* any. */
|
||||
if (!org_freedesktop_DBus_request_name(driver_proxy, FPRINT_SERVICE_NAME,
|
||||
0, &request_name_ret, &error)) {
|
||||
g_warning("Failed to get name: %s", error->message);
|
||||
g_object_unref (manager);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
g_warning ("Got result code %u from requesting name", request_name_ret);
|
||||
g_object_unref (manager);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_debug("D-Bus service launched with name: %s", FPRINT_SERVICE_NAME);
|
||||
request_name_ret = g_bus_own_name_on_connection (connection,
|
||||
FPRINT_SERVICE_NAME,
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
on_name_acquired,
|
||||
on_name_lost,
|
||||
loop, NULL);
|
||||
|
||||
g_debug("entering main loop");
|
||||
g_main_loop_run(loop);
|
||||
g_bus_unown_name (request_name_ret);
|
||||
g_debug("main loop completed");
|
||||
|
||||
g_object_unref (manager);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
294
src/manager.c
294
src/manager.c
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* /net/reactivated/Fprint/Manager object implementation
|
||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -19,7 +20,6 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <dbus/dbus-glib-bindings.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <fprint.h>
|
||||
@ -27,47 +27,107 @@
|
||||
|
||||
#include "fprintd.h"
|
||||
|
||||
extern DBusGConnection *fprintd_dbus_conn;
|
||||
|
||||
static void fprint_manager_constructed (GObject *object);
|
||||
static gboolean fprint_manager_get_devices(FprintManager *manager,
|
||||
GPtrArray **devices, GError **error);
|
||||
static gboolean fprint_manager_get_default_device(FprintManager *manager,
|
||||
const char **device, GError **error);
|
||||
#include "manager-dbus-glue.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GDBusConnection *connection;
|
||||
GDBusObjectManager *object_manager;
|
||||
FprintDBusManager *dbus_manager;
|
||||
FpContext *context;
|
||||
GSList *dev_registry;
|
||||
gboolean no_timeout;
|
||||
guint timeout_id;
|
||||
} FprintManagerPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE(FprintManager, fprint_manager, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintManager))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
FPRINT_MANAGER_CONNECTION,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS];
|
||||
|
||||
static void fprint_manager_finalize(GObject *object)
|
||||
{
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
|
||||
|
||||
g_clear_object (&priv->object_manager);
|
||||
g_clear_object (&priv->dbus_manager);
|
||||
g_clear_object (&priv->connection);
|
||||
g_clear_object (&priv->context);
|
||||
g_slist_free(priv->dev_registry);
|
||||
|
||||
G_OBJECT_CLASS(fprint_manager_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static FprintDevice *
|
||||
fprint_dbus_object_skeleton_get_device (FprintDBusObjectSkeleton *object) {
|
||||
FprintDevice *rdev;
|
||||
|
||||
g_object_get (object, "device", &rdev, NULL);
|
||||
return rdev;
|
||||
}
|
||||
|
||||
static void fprint_manager_set_property (GObject *object, guint property_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
FprintManager *self = FPRINT_MANAGER (object);
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
|
||||
|
||||
switch (property_id) {
|
||||
case FPRINT_MANAGER_CONNECTION:
|
||||
priv->connection = g_value_dup_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fprint_manager_get_property (GObject *object, guint property_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
FprintManager *self = FPRINT_MANAGER (object);
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
|
||||
|
||||
switch (property_id) {
|
||||
case FPRINT_MANAGER_CONNECTION:
|
||||
g_value_set_object (value, priv->connection);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fprint_manager_class_init(FprintManagerClass *klass)
|
||||
{
|
||||
dbus_g_object_type_install_info(FPRINT_TYPE_MANAGER,
|
||||
&dbus_glib_fprint_manager_object_info);
|
||||
dbus_g_error_domain_register (FPRINT_ERROR, FPRINT_ERROR_DBUS_INTERFACE, FPRINT_TYPE_ERROR);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
G_OBJECT_CLASS(klass)->finalize = fprint_manager_finalize;
|
||||
object_class->constructed = fprint_manager_constructed;
|
||||
object_class->set_property = fprint_manager_set_property;
|
||||
object_class->get_property = fprint_manager_get_property;
|
||||
object_class->finalize = fprint_manager_finalize;
|
||||
|
||||
properties[FPRINT_MANAGER_CONNECTION] =
|
||||
g_param_spec_object ("connection",
|
||||
"Connection",
|
||||
"Set GDBus connection property",
|
||||
G_TYPE_DBUS_CONNECTION,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static gchar *get_device_path(FprintDevice *rdev)
|
||||
{
|
||||
return g_strdup_printf("/net/reactivated/Fprint/Device/%d",
|
||||
return g_strdup_printf (FPRINT_SERVICE_PATH "/Device/%d",
|
||||
_fprint_device_get_id(rdev));
|
||||
}
|
||||
|
||||
@ -84,7 +144,8 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
|
||||
{
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||
guint num_devices_used = 0;
|
||||
GSList *l;
|
||||
g_autolist(GDBusObject) devices = NULL;
|
||||
GList *l;
|
||||
gboolean in_use;
|
||||
|
||||
if (priv->timeout_id > 0) {
|
||||
@ -94,9 +155,13 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
|
||||
if (priv->no_timeout)
|
||||
return;
|
||||
|
||||
for (l = priv->dev_registry; l != NULL; l = l->next) {
|
||||
FprintDevice *dev = l->data;
|
||||
devices = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||
|
||||
for (l = devices; l != NULL; l = l->next) {
|
||||
g_autoptr(FprintDevice) dev = NULL;
|
||||
FprintDBusObjectSkeleton *object = l->data;
|
||||
|
||||
dev = fprint_dbus_object_skeleton_get_device (object);
|
||||
g_object_get (G_OBJECT(dev), "in-use", &in_use, NULL);
|
||||
if (in_use != FALSE)
|
||||
num_devices_used++;
|
||||
@ -106,45 +171,91 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
|
||||
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_get_devices (FprintManager *manager, GDBusMethodInvocation *invocation,
|
||||
FprintDBusManager *skeleton)
|
||||
{
|
||||
g_autoptr(GPtrArray) devices = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
if (!fprint_manager_get_devices (manager, &devices, &error)) {
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
fprint_dbus_manager_complete_get_devices (skeleton, invocation,
|
||||
(const gchar *const *)
|
||||
devices->pdata);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_get_default_device (FprintManager *manager,
|
||||
GDBusMethodInvocation *invocation,
|
||||
FprintDBusManager *skeleton)
|
||||
{
|
||||
const gchar *device;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
if (!fprint_manager_get_default_device (manager, &device, &error)) {
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
fprint_dbus_manager_complete_get_default_device (skeleton, invocation,
|
||||
device);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
||||
{
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||
FprintDevice *rdev = fprint_device_new(device);
|
||||
g_autoptr(FprintDBusObjectSkeleton) object = NULL;
|
||||
g_autoptr(FprintDevice) rdev = NULL;
|
||||
g_autofree gchar *path = NULL;
|
||||
|
||||
rdev = fprint_device_new(device);
|
||||
|
||||
g_signal_connect (G_OBJECT(rdev), "notify::in-use",
|
||||
G_CALLBACK (fprint_manager_in_use_notified), manager);
|
||||
|
||||
priv->dev_registry = g_slist_prepend (priv->dev_registry, rdev);
|
||||
path = get_device_path (rdev);
|
||||
dbus_g_connection_register_g_object(fprintd_dbus_conn, path,
|
||||
G_OBJECT(rdev));
|
||||
|
||||
object = fprint_dbus_object_skeleton_new (path);
|
||||
fprint_dbus_object_skeleton_set_device (object,
|
||||
FPRINT_DBUS_DEVICE (rdev));
|
||||
g_dbus_object_manager_server_export (
|
||||
G_DBUS_OBJECT_MANAGER_SERVER (priv->object_manager),
|
||||
G_DBUS_OBJECT_SKELETON (object));
|
||||
}
|
||||
|
||||
static void
|
||||
device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
||||
{
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||
GSList *item;
|
||||
g_autofree gchar *path = NULL;
|
||||
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
||||
GList *item;
|
||||
|
||||
for (item = priv->dev_registry; item; item = item->next) {
|
||||
FprintDevice *rdev;
|
||||
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||
|
||||
for (item = objects; item; item = item->next) {
|
||||
g_autoptr(FprintDevice) rdev = NULL;
|
||||
g_autoptr(FpDevice) dev = NULL;
|
||||
FprintDBusObjectSkeleton *object = item->data;
|
||||
|
||||
rdev = item->data;
|
||||
|
||||
rdev = fprint_dbus_object_skeleton_get_device (object);
|
||||
g_object_get (rdev, "dev", &dev, NULL);
|
||||
if (dev != device)
|
||||
continue;
|
||||
|
||||
priv->dev_registry = g_slist_delete_link (priv->dev_registry, item);
|
||||
|
||||
dbus_g_connection_unregister_g_object(fprintd_dbus_conn, G_OBJECT(rdev));
|
||||
g_dbus_object_manager_server_unexport (
|
||||
G_DBUS_OBJECT_MANAGER_SERVER (priv->object_manager),
|
||||
g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (rdev)));
|
||||
|
||||
g_signal_handlers_disconnect_by_data (rdev, manager);
|
||||
g_object_unref (rdev);
|
||||
|
||||
/* We cannot continue to iterate at this point, but we don't need to either */
|
||||
break;
|
||||
@ -155,13 +266,37 @@ device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
||||
fprint_manager_in_use_notified (NULL, NULL, manager);
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_manager_init (FprintManager *manager)
|
||||
static void fprint_manager_constructed (GObject *object)
|
||||
{
|
||||
FprintManager *manager = FPRINT_MANAGER (object);
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||
GDBusObjectManagerServer *object_manager_server;
|
||||
|
||||
object_manager_server =
|
||||
g_dbus_object_manager_server_new (FPRINT_SERVICE_PATH "/Device");
|
||||
|
||||
priv->object_manager = G_DBUS_OBJECT_MANAGER (object_manager_server);
|
||||
priv->dbus_manager = fprint_dbus_manager_skeleton_new ();
|
||||
priv->context = fp_context_new ();
|
||||
|
||||
g_signal_connect_object (priv->dbus_manager,
|
||||
"handle-get-devices",
|
||||
G_CALLBACK (handle_get_devices),
|
||||
manager,
|
||||
G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (priv->dbus_manager,
|
||||
"handle-get-default-device",
|
||||
G_CALLBACK (handle_get_default_device),
|
||||
manager,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_manager),
|
||||
priv->connection,
|
||||
FPRINT_SERVICE_PATH "/Manager", NULL);
|
||||
|
||||
g_dbus_object_manager_server_set_connection (object_manager_server,
|
||||
priv->connection);
|
||||
|
||||
/* And register the signals for initial enumeration and hotplug. */
|
||||
g_signal_connect_object (priv->context,
|
||||
"device-added",
|
||||
@ -175,19 +310,25 @@ fprint_manager_init (FprintManager *manager)
|
||||
manager,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
/* Prepare everything by enumerating all devices. */
|
||||
/* Prepare everything by enumerating all devices.
|
||||
* This blocks the main loop until the existing devices are enumerated
|
||||
*/
|
||||
fp_context_enumerate (priv->context);
|
||||
|
||||
dbus_g_connection_register_g_object(fprintd_dbus_conn,
|
||||
"/net/reactivated/Fprint/Manager", G_OBJECT(manager));
|
||||
G_OBJECT_CLASS (fprint_manager_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
FprintManager *fprint_manager_new(gboolean no_timeout)
|
||||
static void
|
||||
fprint_manager_init (FprintManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
FprintManager *fprint_manager_new (GDBusConnection *connection, gboolean no_timeout)
|
||||
{
|
||||
FprintManagerPrivate *priv;
|
||||
GObject *object;
|
||||
|
||||
object = g_object_new(FPRINT_TYPE_MANAGER, NULL);
|
||||
object = g_object_new (FPRINT_TYPE_MANAGER, "connection", connection, NULL);
|
||||
priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
|
||||
priv->no_timeout = no_timeout;
|
||||
|
||||
@ -201,23 +342,30 @@ static gboolean fprint_manager_get_devices(FprintManager *manager,
|
||||
GPtrArray **devices, GError **error)
|
||||
{
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||
GSList *elem;
|
||||
GSList *l;
|
||||
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
||||
GList *l;
|
||||
int num_open;
|
||||
GPtrArray *devs;
|
||||
|
||||
elem = g_slist_reverse(g_slist_copy(priv->dev_registry));
|
||||
num_open = g_slist_length(elem);
|
||||
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||
objects = g_list_reverse (objects);
|
||||
|
||||
num_open = g_list_length (objects);
|
||||
devs = g_ptr_array_sized_new(num_open);
|
||||
|
||||
if (num_open > 0) {
|
||||
for (l = elem; l != NULL; l = l->next) {
|
||||
FprintDevice *rdev = l->data;
|
||||
g_ptr_array_add(devs, get_device_path(rdev));
|
||||
}
|
||||
}
|
||||
for (l = objects; l != NULL; l = l->next) {
|
||||
g_autoptr(FprintDevice) rdev = NULL;
|
||||
FprintDBusObjectSkeleton *object = l->data;
|
||||
const char *path;
|
||||
|
||||
g_slist_free(elem);
|
||||
rdev = fprint_dbus_object_skeleton_get_device (object);
|
||||
path = g_dbus_interface_skeleton_get_object_path (
|
||||
G_DBUS_INTERFACE_SKELETON (rdev));
|
||||
g_ptr_array_add (devs, (char *) path);
|
||||
}
|
||||
}
|
||||
g_ptr_array_add (devs, NULL);
|
||||
|
||||
*devices = devs;
|
||||
return TRUE;
|
||||
@ -227,14 +375,19 @@ static gboolean fprint_manager_get_default_device(FprintManager *manager,
|
||||
const char **device, GError **error)
|
||||
{
|
||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||
GSList *elem;;
|
||||
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
||||
int num_open;
|
||||
|
||||
elem = priv->dev_registry;
|
||||
num_open = g_slist_length(elem);
|
||||
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||
num_open = g_list_length (objects);
|
||||
|
||||
if (num_open > 0) {
|
||||
*device = get_device_path (g_slist_last (elem)->data);
|
||||
g_autoptr(FprintDevice) rdev = NULL;
|
||||
FprintDBusObjectSkeleton *object = g_list_last (objects)->data;
|
||||
|
||||
rdev = fprint_dbus_object_skeleton_get_device (object);
|
||||
*device = g_dbus_interface_skeleton_get_object_path (
|
||||
G_DBUS_INTERFACE_SKELETON (rdev));
|
||||
return TRUE;
|
||||
} else {
|
||||
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE,
|
||||
@ -246,32 +399,23 @@ static gboolean fprint_manager_get_default_device(FprintManager *manager,
|
||||
|
||||
GQuark fprint_error_quark (void)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string("fprintd-error-quark");
|
||||
return quark;
|
||||
static volatile gsize quark = 0;
|
||||
if (g_once_init_enter (&quark)) {
|
||||
g_autoptr(GEnumClass) errors_enum = NULL;
|
||||
GQuark domain;
|
||||
unsigned i;
|
||||
|
||||
domain = g_quark_from_static_string ("fprintd-error-quark");
|
||||
errors_enum = g_type_class_ref (FPRINT_TYPE_ERROR);
|
||||
|
||||
for (i = 0; i < errors_enum->n_values; ++i) {
|
||||
GEnumValue *value = &errors_enum->values[i];
|
||||
|
||||
g_dbus_error_register_error (domain, value->value,
|
||||
value->value_nick);
|
||||
}
|
||||
|
||||
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
|
||||
GType
|
||||
fprint_error_get_type (void)
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if (etype == 0) {
|
||||
static const GEnumValue values[] =
|
||||
{
|
||||
ENUM_ENTRY (FPRINT_ERROR_CLAIM_DEVICE, "ClaimDevice"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_ALREADY_IN_USE, "AlreadyInUse"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_INTERNAL, "Internal"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_PERMISSION_DENIED, "PermissionDenied"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_NO_ENROLLED_PRINTS, "NoEnrolledPrints"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_NO_ACTION_IN_PROGRESS, "NoActionInProgress"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_INVALID_FINGERNAME, "InvalidFingername"),
|
||||
ENUM_ENTRY (FPRINT_ERROR_NO_SUCH_DEVICE, "NoSuchDevice"),
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
etype = g_enum_register_static ("FprintError", values);
|
||||
g_once_init_leave (&quark, domain);
|
||||
}
|
||||
return etype;
|
||||
return (GQuark) quark;
|
||||
}
|
||||
|
||||
@ -5,8 +5,6 @@
|
||||
]>
|
||||
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
|
||||
<interface name="net.reactivated.Fprint.Manager">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol"
|
||||
value="fprint_manager" />
|
||||
|
||||
<!-- ************************************************************ -->
|
||||
|
||||
|
||||
@ -1,30 +1,10 @@
|
||||
fprintd_marshal = gnome.genmarshal('fprintd-marshal',
|
||||
prefix: 'fprintd_marshal',
|
||||
sources: 'fprintd-marshal.list',
|
||||
valist_marshallers: true,
|
||||
)
|
||||
|
||||
bash = find_program('bash')
|
||||
dbus_binding_tool = find_program('dbus-binding-tool')
|
||||
dbus_interfaces = ['Manager', 'Device']
|
||||
dbus_interfaces_files = []
|
||||
dbus_server_glue_sources = []
|
||||
|
||||
foreach interface_name: dbus_interfaces
|
||||
interface = interface_name.to_lower()
|
||||
interface_file = interface + '.xml'
|
||||
glue_name = interface + '-dbus-glue.h'
|
||||
dbus_server_glue_sources += custom_target(glue_name,
|
||||
input: interface_file,
|
||||
output: glue_name,
|
||||
command: [
|
||||
dbus_binding_tool,
|
||||
'--prefix=fprint_' + interface,
|
||||
'--mode=glib-server',
|
||||
'--output=@OUTPUT@',
|
||||
'@INPUT@',
|
||||
])
|
||||
|
||||
dbus_interfaces_files += custom_target('dbus_interface_' + interface,
|
||||
input: interface_file,
|
||||
output: 'net.reactivated.Fprint.@0@.xml'.format(interface_name),
|
||||
@ -34,14 +14,30 @@ foreach interface_name: dbus_interfaces
|
||||
)
|
||||
endforeach
|
||||
|
||||
fprintd_dbus_sources = gnome.gdbus_codegen('fprintd-dbus',
|
||||
sources: dbus_interfaces_files,
|
||||
autocleanup: 'all',
|
||||
interface_prefix: 'net.reactivated.Fprint.',
|
||||
namespace: 'FprintDBus',
|
||||
object_manager: true,
|
||||
)
|
||||
|
||||
fprintd_enum_files = gnome.mkenums_simple('fprintd-enums',
|
||||
sources: 'fprintd.h',
|
||||
)
|
||||
|
||||
fprintd_deps = declare_dependency(
|
||||
include_directories: [
|
||||
include_directories('..'),
|
||||
],
|
||||
sources: [
|
||||
fprintd_enum_files,
|
||||
fprintd_dbus_sources,
|
||||
],
|
||||
dependencies: [
|
||||
dbus_glib_dep,
|
||||
glib_dep,
|
||||
gio_dep,
|
||||
gio_unix_dep,
|
||||
gmodule_dep,
|
||||
libfprint_dep,
|
||||
polkit_gobject_dep,
|
||||
@ -58,8 +54,6 @@ libfprintd_private = static_library('fprintd-private',
|
||||
'device.c',
|
||||
'fprintd.h',
|
||||
'manager.c',
|
||||
dbus_server_glue_sources,
|
||||
fprintd_marshal,
|
||||
],
|
||||
dependencies: fprintd_deps,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
|
||||
4
tests/LSAN-leaks-suppress.txt
Normal file
4
tests/LSAN-leaks-suppress.txt
Normal file
@ -0,0 +1,4 @@
|
||||
leak:initialize_device
|
||||
leak:usbi_alloc_device
|
||||
leak:libusb-1.0.so.*
|
||||
leak:PyMem_RawMalloc
|
||||
@ -93,8 +93,9 @@ def GetDefaultDevice(self):
|
||||
return devices[0]
|
||||
|
||||
@dbus.service.method(MANAGER_MOCK_IFACE,
|
||||
in_signature='sis', out_signature='s')
|
||||
def AddDevice(self, device_name, num_enroll_stages, scan_type):
|
||||
in_signature='sisb', out_signature='s')
|
||||
def AddDevice(self, device_name, num_enroll_stages, scan_type,
|
||||
has_identification=False):
|
||||
'''Convenience method to add a fingerprint reader device
|
||||
|
||||
You have to specify a device name, the number of enrollment
|
||||
@ -139,12 +140,27 @@ def AddDevice(self, device_name, num_enroll_stages, scan_type):
|
||||
|
||||
device = mockobject.objects[path]
|
||||
device.fingers = {}
|
||||
device.has_identification = has_identification
|
||||
device.claimed_user = None
|
||||
device.action = None
|
||||
device.selected_finger = None
|
||||
device.verify_script = []
|
||||
|
||||
return path
|
||||
|
||||
@dbus.service.method(MANAGER_MOCK_IFACE,
|
||||
in_signature='o')
|
||||
def RemoveDevice(self, path):
|
||||
# This isn't compatible with hotplugging devices, which fprintd doesn't
|
||||
# support yet, but it's meant to remove devices added to the mock for
|
||||
# testing purposes.
|
||||
if not path:
|
||||
raise dbus.exceptions.DBusException(
|
||||
'Invalid empty path.',
|
||||
name='org.freedesktop.DBus.Error.InvalidArgs')
|
||||
|
||||
self.RemoveObject(path)
|
||||
|
||||
@dbus.service.method(DEVICE_IFACE,
|
||||
in_signature='s', out_signature='as')
|
||||
def ListEnrolledFingers(device, user):
|
||||
@ -186,6 +202,8 @@ def Release(device):
|
||||
'Device was not claimed before use',
|
||||
name='net.reactivated.Fprint.Error.ClaimDevice')
|
||||
device.claimed_user = None
|
||||
device.action = None
|
||||
device.selected_finger = None
|
||||
|
||||
def can_verify_finger(device, finger_name):
|
||||
# We should already have checked that there are enrolled fingers
|
||||
@ -228,8 +246,9 @@ def VerifyStart(device, finger_name):
|
||||
name='net.reactivated.Fprint.Error.AlreadyInUse')
|
||||
device.action = 'verify'
|
||||
|
||||
if finger_name == 'any':
|
||||
if finger_name == 'any' and not device.has_identification:
|
||||
finger_name = device.fingers[device.claimed_user][0]
|
||||
device.selected_finger = finger_name
|
||||
device.EmitSignal(DEVICE_IFACE, 'VerifyFingerSelected', 's', [
|
||||
finger_name
|
||||
])
|
||||
@ -262,6 +281,7 @@ def VerifyStop(device):
|
||||
'No verification to stop',
|
||||
name='net.reactivated.Fprint.Error.NoActionInProgress')
|
||||
device.action = None
|
||||
device.selected_finger = None
|
||||
|
||||
@dbus.service.method(DEVICE_IFACE,
|
||||
in_signature='s', out_signature='')
|
||||
@ -317,11 +337,6 @@ def SetEnrolledFingers(device, user, fingers):
|
||||
Returns nothing.
|
||||
'''
|
||||
|
||||
if len(fingers) < 1:
|
||||
raise dbus.exceptions.DBusException(
|
||||
'Fingers array must not be empty',
|
||||
name='org.freedesktop.DBus.Error.InvalidArgs')
|
||||
|
||||
for k in fingers:
|
||||
if k not in VALID_FINGER_NAMES:
|
||||
raise dbus.exceptions.DBusException(
|
||||
@ -330,6 +345,30 @@ def SetEnrolledFingers(device, user, fingers):
|
||||
|
||||
device.fingers[user] = fingers
|
||||
|
||||
@dbus.service.method(DEVICE_MOCK_IFACE,
|
||||
in_signature='', out_signature='s')
|
||||
def GetSelectedFinger(device):
|
||||
'''Convenience method to get the finger under verification
|
||||
|
||||
Returns the finger name that the user has selected for verifying
|
||||
'''
|
||||
if not device.selected_finger:
|
||||
raise dbus.exceptions.DBusException(
|
||||
'Device is not verifying',
|
||||
name='net.reactivated.Fprint.Error.NoActionInProgress')
|
||||
|
||||
return device.selected_finger
|
||||
|
||||
@dbus.service.method(DEVICE_MOCK_IFACE,
|
||||
in_signature='', out_signature='b')
|
||||
def HasIdentification(device):
|
||||
'''Convenience method to get if a device supports identification
|
||||
|
||||
Returns whether identification is supported.
|
||||
'''
|
||||
|
||||
return device.has_identification
|
||||
|
||||
@dbus.service.method(DEVICE_MOCK_IFACE,
|
||||
in_signature='a(sbi)', out_signature='')
|
||||
def SetVerifyScript(device, script):
|
||||
|
||||
113
tests/dbusmock/polkitd.py
Normal file
113
tests/dbusmock/polkitd.py
Normal file
@ -0,0 +1,113 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''polkit mock template
|
||||
|
||||
This creates the basic methods and properties of the
|
||||
org.freedesktop.PolicyKit1.Authority object, so that we can use it async
|
||||
'''
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Lesser General Public License as published by the Free
|
||||
# Software Foundation; either version 3 of the License, or (at your option) any
|
||||
# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text
|
||||
# of the license.
|
||||
|
||||
__author__ = 'Marco Trevisan'
|
||||
__email__ = 'marco.trevisan@canonical.com'
|
||||
__copyright__ = '(c) 2020 Canonical Ltd.'
|
||||
__license__ = 'LGPL 3+'
|
||||
|
||||
import dbus
|
||||
import time
|
||||
|
||||
from dbusmock import MOCK_IFACE, mockobject
|
||||
|
||||
BUS_NAME = 'org.freedesktop.PolicyKit1'
|
||||
MAIN_OBJ = '/org/freedesktop/PolicyKit1/Authority'
|
||||
MAIN_IFACE = 'org.freedesktop.PolicyKit1.Authority'
|
||||
SYSTEM_BUS = True
|
||||
IS_OBJECT_MANAGER = False
|
||||
|
||||
def load(mock, parameters):
|
||||
polkitd = mockobject.objects[MAIN_OBJ]
|
||||
# default state
|
||||
polkitd.allow_unknown = False
|
||||
polkitd.allowed = []
|
||||
polkitd.delay = 0
|
||||
polkitd.simulate_hang = False
|
||||
polkitd.hanging_actions = []
|
||||
polkitd.hanging_calls = []
|
||||
|
||||
mock.AddProperties(MAIN_IFACE,
|
||||
dbus.Dictionary({
|
||||
'BackendName': 'local',
|
||||
'BackendVersion': '0.8.15',
|
||||
'BackendFeatures': dbus.UInt32(1, variant_level=1),
|
||||
}, signature='sv'))
|
||||
|
||||
|
||||
@dbus.service.method(MAIN_IFACE,
|
||||
in_signature='(sa{sv})sa{ss}us', out_signature='(bba{ss})',
|
||||
async_callbacks=('ok_cb', 'err_cb'))
|
||||
def CheckAuthorization(self, subject, action_id, details, flags, cancellation_id,
|
||||
ok_cb, err_cb):
|
||||
time.sleep(self.delay)
|
||||
allowed = action_id in self.allowed or self.allow_unknown
|
||||
ret = (allowed, False, {'test': 'test'})
|
||||
|
||||
if self.simulate_hang or action_id in self.hanging_actions:
|
||||
self.hanging_calls.append((ok_cb, ret))
|
||||
else:
|
||||
ok_cb(ret)
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='b', out_signature='')
|
||||
def AllowUnknown(self, default):
|
||||
'''Control whether unknown actions are allowed
|
||||
|
||||
This controls the return value of CheckAuthorization for actions which were
|
||||
not explicitly allowed by SetAllowed().
|
||||
'''
|
||||
self.allow_unknown = default
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='d', out_signature='')
|
||||
def SetDelay(self, delay):
|
||||
'''Makes the CheckAuthorization() method to delay'''
|
||||
self.delay = delay
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='b', out_signature='')
|
||||
def SimulateHang(self, hang):
|
||||
'''Makes the CheckAuthorization() method to hang'''
|
||||
self.simulate_hang = hang
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='as', out_signature='')
|
||||
def SimulateHangActions(self, actions):
|
||||
'''Makes the CheckAuthorization() method to hang on such actions'''
|
||||
self.hanging_actions = actions
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='', out_signature='')
|
||||
def ReleaseHangingCalls(self):
|
||||
'''Calls all the hanging callbacks'''
|
||||
for (cb, ret) in self.hanging_calls:
|
||||
cb(ret)
|
||||
self.hanging_calls = []
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='', out_signature='b')
|
||||
def HaveHangingCalls(self):
|
||||
'''Check if we've hangling calls'''
|
||||
return len(self.hanging_calls)
|
||||
|
||||
@dbus.service.method(MOCK_IFACE, in_signature='as', out_signature='')
|
||||
def SetAllowed(self, actions):
|
||||
'''Set allowed actions'''
|
||||
|
||||
self.allowed = actions
|
||||
|
||||
@dbus.service.method(MAIN_IFACE,
|
||||
in_signature='', out_signature='o')
|
||||
def GetDefaultDevice(self):
|
||||
devices = self.GetDevices()
|
||||
if len(devices) < 1:
|
||||
raise dbus.exceptions.DBusException(
|
||||
'No devices available',
|
||||
name='net.reactivated.Fprint.Error.NoSuchDevice')
|
||||
return devices[0]
|
||||
1154
tests/fprintd.py
Executable file → Normal file
1154
tests/fprintd.py
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@ -1,36 +1,118 @@
|
||||
# Add a way to discover and run python unit tests separately
|
||||
# https://github.com/mesonbuild/meson/issues/6851
|
||||
python_tests = [
|
||||
# List all the python tests, must be in the form:
|
||||
# {
|
||||
# 'name': 'test name',
|
||||
# 'file': 'full test file path, use files('path')[0]',
|
||||
# Fields below are optional:
|
||||
# 'workdir': '',
|
||||
# 'env': [],
|
||||
# 'depends': [],
|
||||
# 'suite': [],
|
||||
# 'extra_args': [],
|
||||
# 'timeout': 30,
|
||||
# 'is_parallel': true,
|
||||
# }
|
||||
]
|
||||
|
||||
address_sanitizer = get_option('b_sanitize') == 'address'
|
||||
|
||||
tests = [
|
||||
'fprintd',
|
||||
'test_fprintd_utils',
|
||||
]
|
||||
|
||||
foreach t: tests
|
||||
test(t,
|
||||
python3,
|
||||
args: meson.current_source_dir() / t + '.py',
|
||||
suite: ['daemon'],
|
||||
depends: [
|
||||
fprintd,
|
||||
fprintd_utils,
|
||||
],
|
||||
env: [
|
||||
python_tests += [
|
||||
{
|
||||
'name': t,
|
||||
'file': files(meson.current_source_dir() / t + '.py')[0],
|
||||
'env': [
|
||||
'G_DEBUG=fatal-criticals',
|
||||
'G_MESSAGES_DEBUG=all',
|
||||
'FPRINT_BUILD_DIR=' + meson.build_root() / 'src',
|
||||
'TOPSRCDIR=' + meson.source_root(),
|
||||
],
|
||||
'depends': [
|
||||
fprintd,
|
||||
fprintd_utils,
|
||||
],
|
||||
'suite': [t == 'fprintd' ? 'daemon' : ''],
|
||||
}
|
||||
]
|
||||
endforeach
|
||||
|
||||
if get_option('pam')
|
||||
subdir('pam')
|
||||
endif
|
||||
|
||||
# Add a way to discover and run python unit tests separately
|
||||
# https://github.com/mesonbuild/meson/issues/6851
|
||||
unittest_inspector = find_program('unittest_inspector.py')
|
||||
|
||||
foreach pt: python_tests
|
||||
r = run_command(unittest_inspector, pt.get('file'))
|
||||
unit_tests = r.stdout().strip().split('\n')
|
||||
base_args = [ pt.get('file') ] + pt.get('extra_args', [])
|
||||
suite = pt.get('suite', [])
|
||||
|
||||
if r.returncode() == 0 and unit_tests.length() > 0
|
||||
suite += pt.get('name')
|
||||
else
|
||||
unit_tests = [pt.get('name')]
|
||||
endif
|
||||
|
||||
foreach ut: unit_tests
|
||||
ut_suite = suite
|
||||
ut_args = base_args
|
||||
if unit_tests.length() > 1
|
||||
ut_args += ut
|
||||
ut_suite += ut.split('.')[0]
|
||||
endif
|
||||
test(ut,
|
||||
python3,
|
||||
args: ut_args,
|
||||
suite: ut_suite,
|
||||
depends: pt.get('depends', []),
|
||||
workdir: pt.get('workdir', meson.build_root()),
|
||||
env: pt.get('env', []),
|
||||
timeout: pt.get('timeout', 30),
|
||||
is_parallel: pt.get('is_parallel', true),
|
||||
)
|
||||
endforeach
|
||||
endforeach
|
||||
|
||||
timeout_multiplier = 1
|
||||
test_envs = [
|
||||
'G_SLICE=always-malloc',
|
||||
'MALLOC_CHECK_=2',
|
||||
]
|
||||
|
||||
if address_sanitizer
|
||||
timeout_multiplier = 3
|
||||
test_envs += [
|
||||
'ADDRESS_SANITIZER=true',
|
||||
'ASAN_OPTIONS=@0@'.format(':'.join([
|
||||
'abort_on_error=true',
|
||||
'symbolize=true',
|
||||
])),
|
||||
'LSAN_OPTIONS=@0@'.format(':'.join([
|
||||
'exitcode=0',
|
||||
'strict_string_checks=true',
|
||||
'suppressions=@0@'.format(
|
||||
files(meson.current_source_dir() / 'LSAN-leaks-suppress.txt')[0]),
|
||||
])),
|
||||
]
|
||||
endif
|
||||
|
||||
add_test_setup('default_setup',
|
||||
is_default: true,
|
||||
env: [
|
||||
'G_SLICE=always-malloc',
|
||||
'MALLOC_CHECK_=2',
|
||||
'MALLOC_PERTURB_=55',
|
||||
],
|
||||
env: test_envs,
|
||||
timeout_multiplier: timeout_multiplier
|
||||
)
|
||||
|
||||
if find_program('valgrind', required: false).found()
|
||||
if not address_sanitizer and find_program('valgrind', required: false).found()
|
||||
glib_share = glib_dep.get_pkgconfig_variable('prefix') / 'share' / glib_dep.name()
|
||||
glib_suppressions = glib_share + '/valgrind/glib.supp'
|
||||
add_test_setup('valgrind',
|
||||
@ -42,6 +124,3 @@ if find_program('valgrind', required: false).found()
|
||||
)
|
||||
endif
|
||||
|
||||
if get_option('pam')
|
||||
subdir('pam')
|
||||
endif
|
||||
|
||||
@ -4,24 +4,56 @@ tests = [
|
||||
'test_pam_fprintd',
|
||||
]
|
||||
|
||||
preloaded_libs = []
|
||||
pam_tests_ld_preload = []
|
||||
|
||||
if address_sanitizer
|
||||
# ASAN has to be the first in list
|
||||
preloaded_libs += 'asan'
|
||||
endif
|
||||
|
||||
preloaded_libs += 'pam_wrapper'
|
||||
|
||||
foreach libname: preloaded_libs
|
||||
lib = run_command(meson.get_compiler('c'),
|
||||
'-print-file-name=lib@0@.so'.format(libname)
|
||||
).stdout().strip()
|
||||
|
||||
# Support linker script files
|
||||
if run_command('grep', '-qI', '^INPUT', files(lib)).returncode() == 0
|
||||
out = run_command('cat', lib).stdout()
|
||||
lib = out.split('(')[1].split(')')[0].strip()
|
||||
endif
|
||||
|
||||
if lib != '' and lib[0] == '/'
|
||||
message('Found library @0@ as @1@'.format(libname, lib))
|
||||
pam_tests_ld_preload += '@0@'.format(files(lib)[0])
|
||||
else
|
||||
tests = []
|
||||
warning('No library found for ' + libname + ', skipping PAM tests')
|
||||
endif
|
||||
endforeach
|
||||
|
||||
foreach t: tests
|
||||
test(t,
|
||||
python3,
|
||||
args: meson.current_source_dir() / t + '.py',
|
||||
suite: ['PAM'],
|
||||
depends: [
|
||||
pam_fprintd,
|
||||
pam_service_file,
|
||||
],
|
||||
env: [
|
||||
python_tests += [
|
||||
{
|
||||
'name': t,
|
||||
'file': files(meson.current_source_dir() / t + '.py')[0],
|
||||
'is_parallel': false,
|
||||
'env': [
|
||||
'TOPBUILDDIR=' + meson.build_root(),
|
||||
'TOPSRCDIR=' + meson.source_root(),
|
||||
'LD_PRELOAD=libpam_wrapper.so',
|
||||
'LD_PRELOAD=' + ' '.join(pam_tests_ld_preload),
|
||||
'PAM_WRAPPER=1',
|
||||
'PAM_WRAPPER_DEBUGLEVEL=2',
|
||||
'PAM_WRAPPER_SERVICE_DIR=' + meson.current_build_dir() / 'services',
|
||||
'G_DEBUG=fatal-warnings',
|
||||
],
|
||||
timeout: 60,
|
||||
)
|
||||
'depends': [
|
||||
pam_fprintd,
|
||||
pam_service_file,
|
||||
],
|
||||
'suite': ['PAM'],
|
||||
}
|
||||
]
|
||||
endforeach
|
||||
|
||||
@ -16,15 +16,14 @@ import unittest
|
||||
import sys
|
||||
import subprocess
|
||||
import dbus
|
||||
import dbus.mainloop.glib
|
||||
import dbusmock
|
||||
import fcntl
|
||||
import glob
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
import pypamtest
|
||||
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
PAM_SUCCESS = 0
|
||||
PAM_AUTH_ERR = 7
|
||||
PAM_AUTHINFO_UNAVAIL = 9
|
||||
@ -71,6 +70,9 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
||||
def tearDownClass(klass):
|
||||
klass.stop_monitor()
|
||||
|
||||
# Remove pam wrapper files, as they may break other tests
|
||||
[shutil.rmtree(i) for i in glob.glob('/tmp/pam.[0-9A-z]')]
|
||||
|
||||
def setUp(self):
|
||||
(self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
|
||||
self.template_name, {}, stdout=subprocess.PIPE)
|
||||
@ -88,6 +90,46 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
||||
self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
||||
self.device_mock.SetEnrolledFingers('toto', ['left-little-finger', 'right-little-finger'])
|
||||
|
||||
def test_pam_fprintd_identify_error(self):
|
||||
self.setup_device()
|
||||
script = [
|
||||
( 'verify-unknown-error', True, 2 )
|
||||
]
|
||||
self.device_mock.SetVerifyScript(script)
|
||||
|
||||
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTHINFO_UNAVAIL)
|
||||
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.assertEqual(len(res.errors), 0)
|
||||
|
||||
def test_pam_fprintd_identify_error2(self):
|
||||
self.setup_device()
|
||||
script = [
|
||||
( 'verify-disconnected', True, 2 )
|
||||
]
|
||||
self.device_mock.SetVerifyScript(script)
|
||||
|
||||
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTHINFO_UNAVAIL)
|
||||
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.assertEqual(len(res.errors), 0)
|
||||
|
||||
def test_pam_fprintd_identify_error3(self):
|
||||
self.setup_device()
|
||||
script = [
|
||||
( 'verify-INVALID', True, 2 )
|
||||
]
|
||||
self.device_mock.SetVerifyScript(script)
|
||||
|
||||
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTH_ERR)
|
||||
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.assertEqual(len(res.errors), 1)
|
||||
self.assertRegex(res.errors[0], r'An unknown error occurred')
|
||||
|
||||
def test_pam_fprintd_auth(self):
|
||||
self.setup_device()
|
||||
script = [
|
||||
|
||||
@ -22,9 +22,23 @@ import fcntl
|
||||
import os
|
||||
import time
|
||||
|
||||
|
||||
VALID_FINGER_NAMES = [
|
||||
'left-thumb',
|
||||
'left-index-finger',
|
||||
'left-middle-finger',
|
||||
'left-ring-finger',
|
||||
'left-little-finger',
|
||||
'right-thumb',
|
||||
'right-index-finger',
|
||||
'right-middle-finger',
|
||||
'right-ring-finger',
|
||||
'right-little-finger'
|
||||
]
|
||||
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
class TestFprintd(dbusmock.DBusTestCase):
|
||||
class TestFprintdUtilsBase(dbusmock.DBusTestCase):
|
||||
'''Test fprintd utilities'''
|
||||
|
||||
@classmethod
|
||||
@ -57,7 +71,11 @@ class TestFprintd(dbusmock.DBusTestCase):
|
||||
if os.path.exists(valgrind):
|
||||
klass.wrapper_args += ['--suppressions={}'.format(valgrind)]
|
||||
|
||||
if 'ADDRESS_SANITIZER' in os.environ:
|
||||
klass.sleep_time *= 2
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
(self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
|
||||
self.template_name, {}, stdout=subprocess.PIPE)
|
||||
# set log to nonblocking
|
||||
@ -68,119 +86,229 @@ class TestFprintd(dbusmock.DBusTestCase):
|
||||
def tearDown(self):
|
||||
self.p_mock.terminate()
|
||||
self.p_mock.wait()
|
||||
super().tearDown()
|
||||
|
||||
def setup_device(self):
|
||||
device_path = self.obj_fprintd_mock.AddDevice('FDO Trigger Finger Laser Reader', 3, 'swipe')
|
||||
self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
||||
self.device_mock.SetEnrolledFingers('toto', ['left-little-finger', 'right-little-finger'])
|
||||
self.device_path = self.obj_fprintd_mock.AddDevice(
|
||||
'FDO Trigger Finger Laser Reader', 3, 'swipe')
|
||||
self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint',
|
||||
self.device_path)
|
||||
self.set_enrolled_fingers(['left-little-finger', 'right-little-finger'])
|
||||
|
||||
def test_fprintd_enroll(self):
|
||||
self.setup_device()
|
||||
def set_enrolled_fingers(self, fingers, user='toto'):
|
||||
self.enrolled_fingers = fingers
|
||||
self.device_mock.SetEnrolledFingers('toto', self.enrolled_fingers,
|
||||
signature='sas')
|
||||
|
||||
mock_log = tempfile.NamedTemporaryFile()
|
||||
process = subprocess.Popen(self.wrapper_args + [self.tools_prefix + 'fprintd-enroll', '-f', 'right-index-finger', 'toto'],
|
||||
stdout=mock_log,
|
||||
def start_utility_process(self, utility_name, args=[], sleep=True):
|
||||
utility = [ os.path.join(self.tools_prefix, 'fprintd-{}'.format(utility_name)) ]
|
||||
process = subprocess.Popen(self.wrapper_args + utility + args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
flags = fcntl.fcntl(process.stdout, fcntl.F_GETFL)
|
||||
fcntl.fcntl(process.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
||||
|
||||
self.addCleanup(self.try_stop_utility_process, process)
|
||||
|
||||
if sleep:
|
||||
time.sleep(self.sleep_time)
|
||||
|
||||
with open(mock_log.name) as f:
|
||||
out = f.read()
|
||||
return process
|
||||
|
||||
def stop_utility_process(self, process):
|
||||
print(process.stdout.read())
|
||||
process.terminate()
|
||||
process.wait()
|
||||
|
||||
def try_stop_utility_process(self, process):
|
||||
try:
|
||||
self.stop_utility_process(process)
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_process_output(self, process):
|
||||
out = process.stdout.read()
|
||||
self.addCleanup(print, out)
|
||||
return out
|
||||
|
||||
def run_utility_process(self, utility_name, args=[], sleep=True, timeout=None):
|
||||
proc = self.start_utility_process(utility_name, args=args, sleep=sleep)
|
||||
ret = proc.wait(timeout=timeout if timeout is not None else self.sleep_time * 4)
|
||||
self.assertLessEqual(ret, 128)
|
||||
|
||||
return self.get_process_output(proc), ret
|
||||
|
||||
|
||||
class TestFprintdUtils(TestFprintdUtilsBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.setup_device()
|
||||
|
||||
def test_fprintd_enroll(self):
|
||||
process = self.start_utility_process('enroll', ['-f', 'right-index-finger', 'toto'])
|
||||
|
||||
out = self.get_process_output(process)
|
||||
self.assertRegex(out, r'right-index-finger')
|
||||
|
||||
self.device_mock.EmitEnrollStatus('enroll-completed', True)
|
||||
time.sleep(self.sleep_time)
|
||||
|
||||
with open(mock_log.name) as f:
|
||||
out = f.read()
|
||||
out = self.get_process_output(process)
|
||||
self.assertRegex(out, 'Enroll result: enroll-completed')
|
||||
|
||||
def test_fprintd_list(self):
|
||||
# Rick has no fingerprints enrolled
|
||||
out, ret = self.run_utility_process('list', ['rick'])
|
||||
self.assertRegex(out, r'has no fingers enrolled for')
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
# Toto does
|
||||
out, ret = self.run_utility_process('list', ['toto'])
|
||||
self.assertRegex(out, r'right-little-finger')
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
def test_fprintd_delete(self):
|
||||
# Has fingerprints enrolled
|
||||
out, ret = self.run_utility_process('list', ['toto'])
|
||||
self.assertRegex(out, r'left-little-finger')
|
||||
self.assertEqual(ret, 0)
|
||||
self.assertRegex(out, r'right-little-finger')
|
||||
|
||||
# Delete fingerprints
|
||||
out, ret = self.run_utility_process('delete', ['toto'])
|
||||
self.assertRegex(out, r'Fingerprints deleted')
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
# Doesn't have fingerprints
|
||||
out, ret = self.run_utility_process('list', ['toto'])
|
||||
self.assertRegex(out, r'has no fingers enrolled for')
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
|
||||
class TestFprintdUtilsNoDeviceTests(TestFprintdUtilsBase):
|
||||
def test_fprintd_enroll(self):
|
||||
out, ret = self.run_utility_process('enroll', ['toto'])
|
||||
self.assertIn('No devices available', out)
|
||||
self.assertEqual(ret, 1)
|
||||
|
||||
def test_fprintd_list(self):
|
||||
out, ret = self.run_utility_process('list', ['toto'])
|
||||
self.assertIn('No devices available', out)
|
||||
self.assertEqual(ret, 1)
|
||||
|
||||
def test_fprintd_delete(self):
|
||||
out, ret = self.run_utility_process('delete', ['toto'])
|
||||
self.assertIn('No devices available', out)
|
||||
self.assertEqual(ret, 1)
|
||||
|
||||
def test_fprintd_verify(self):
|
||||
out, ret = self.run_utility_process('verify', ['toto'])
|
||||
self.assertIn('No devices available', out)
|
||||
self.assertEqual(ret, 1)
|
||||
|
||||
|
||||
class TestFprintdUtilsVerify(TestFprintdUtilsBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.setup_device()
|
||||
|
||||
mock_log = tempfile.NamedTemporaryFile()
|
||||
process = subprocess.Popen(self.wrapper_args + [self.tools_prefix + 'fprintd-verify', 'toto'],
|
||||
stdout=mock_log,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
def start_verify_process(self, user='toto', finger=None, checkEnrolled=True):
|
||||
args = [user]
|
||||
if finger:
|
||||
args += ['-f', finger]
|
||||
|
||||
time.sleep(self.sleep_time)
|
||||
self.process = self.start_utility_process('verify', args)
|
||||
out = self.get_process_output(self.process)
|
||||
|
||||
with open(mock_log.name) as f:
|
||||
out = f.read()
|
||||
self.assertRegex(out, r'left-little-finger')
|
||||
self.assertNotRegex(out, 'Verify result: verify-match \(done\)')
|
||||
self.assertNotRegex(out, r'Device already in use by [A-z]+')
|
||||
self.assertNotIn('Verify result:', out)
|
||||
|
||||
if checkEnrolled and finger:
|
||||
self.assertNotIn('''Finger '{}' not enrolled for user {}'''.format(
|
||||
finger, user), out)
|
||||
|
||||
if checkEnrolled:
|
||||
for f in self.enrolled_fingers:
|
||||
self.assertIn(f, out)
|
||||
|
||||
if finger:
|
||||
expected_finger = finger
|
||||
if finger == 'any' and not self.device_mock.HasIdentification():
|
||||
expected_finger = self.enrolled_fingers[0]
|
||||
self.assertEqual(self.device_mock.GetSelectedFinger(), expected_finger)
|
||||
|
||||
def assertVerifyMatch(self, match):
|
||||
self.assertIn('Verify result: {} (done)'.format(
|
||||
'verify-match' if match else 'verify-no-match'),
|
||||
self.get_process_output(self.process))
|
||||
|
||||
def test_fprintd_verify(self):
|
||||
self.start_verify_process()
|
||||
|
||||
self.device_mock.EmitVerifyStatus('verify-match', True)
|
||||
time.sleep(self.sleep_time)
|
||||
self.assertVerifyMatch(True)
|
||||
|
||||
with open(mock_log.name) as f:
|
||||
out = f.read()
|
||||
self.assertRegex(out, 'Verify result: verify-match \(done\)')
|
||||
def test_fprintd_verify_enrolled_fingers(self):
|
||||
for finger in self.enrolled_fingers:
|
||||
self.start_verify_process(finger=finger)
|
||||
|
||||
self.device_mock.EmitVerifyStatus('verify-match', True)
|
||||
time.sleep(self.sleep_time)
|
||||
self.assertVerifyMatch(True)
|
||||
|
||||
def test_fprintd_verify_any_finger_no_identification(self):
|
||||
self.start_verify_process(finger='any')
|
||||
|
||||
self.device_mock.EmitVerifyStatus('verify-match', True)
|
||||
time.sleep(self.sleep_time)
|
||||
self.assertVerifyMatch(True)
|
||||
|
||||
def test_fprintd_verify_any_finger_identification(self):
|
||||
self.obj_fprintd_mock.RemoveDevice(self.device_path)
|
||||
self.device_path = self.obj_fprintd_mock.AddDevice('Full powered device',
|
||||
3, 'press', True)
|
||||
self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint',
|
||||
self.device_path)
|
||||
self.set_enrolled_fingers(VALID_FINGER_NAMES)
|
||||
self.start_verify_process(finger='any')
|
||||
|
||||
self.device_mock.EmitVerifyStatus('verify-match', True)
|
||||
time.sleep(self.sleep_time)
|
||||
self.assertVerifyMatch(True)
|
||||
|
||||
def test_fprintd_verify_not_enrolled_fingers(self):
|
||||
for finger in [f for f in VALID_FINGER_NAMES if f not in self.enrolled_fingers]:
|
||||
regex = r'Finger \'{}\' not enrolled'.format(finger)
|
||||
with self.assertRaisesRegex(AssertionError, regex):
|
||||
self.start_verify_process(finger=finger)
|
||||
self.device_mock.Release()
|
||||
|
||||
def test_fprintd_verify_no_enrolled_fingers(self):
|
||||
self.set_enrolled_fingers([])
|
||||
self.start_verify_process()
|
||||
self.assertEqual(self.process.poll(), 1)
|
||||
|
||||
def test_fprintd_list_all_fingers(self):
|
||||
self.set_enrolled_fingers(VALID_FINGER_NAMES)
|
||||
self.start_verify_process()
|
||||
|
||||
def test_fprintd_verify_script(self):
|
||||
self.setup_device()
|
||||
script = [
|
||||
( 'verify-match', True, 2 )
|
||||
]
|
||||
self.device_mock.SetVerifyScript(script)
|
||||
|
||||
mock_log = tempfile.NamedTemporaryFile()
|
||||
process = subprocess.Popen(self.wrapper_args + [self.tools_prefix + 'fprintd-verify', 'toto'],
|
||||
stdout=mock_log,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
self.start_verify_process()
|
||||
time.sleep(self.sleep_time * 4)
|
||||
self.assertVerifyMatch(True)
|
||||
|
||||
time.sleep(self.sleep_time)
|
||||
def test_fprintd_multiple_verify_fails(self):
|
||||
self.start_verify_process()
|
||||
|
||||
with open(mock_log.name) as f:
|
||||
out = f.read()
|
||||
self.assertRegex(out, r'left-little-finger')
|
||||
self.assertNotRegex(out, 'Verify result: verify-match \(done\)')
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
with open(mock_log.name) as f:
|
||||
out = f.read()
|
||||
self.assertRegex(out, 'Verify result: verify-match \(done\)')
|
||||
|
||||
def test_fprintd_list(self):
|
||||
self.setup_device()
|
||||
|
||||
# Rick has no fingerprints enrolled
|
||||
out = subprocess.check_output(self.wrapper_args + [self.tools_prefix + 'fprintd-list', 'rick'],
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
self.assertRegex(out, r'has no fingers enrolled for')
|
||||
|
||||
# Toto does
|
||||
out = subprocess.check_output(self.wrapper_args + [self.tools_prefix + 'fprintd-list', 'toto'],
|
||||
universal_newlines=True)
|
||||
self.assertRegex(out, r'left-little-finger')
|
||||
self.assertRegex(out, r'right-little-finger')
|
||||
|
||||
def test_fprintd_delete(self):
|
||||
self.setup_device()
|
||||
|
||||
# Has fingerprints enrolled
|
||||
out = subprocess.check_output(self.wrapper_args + [self.tools_prefix + 'fprintd-list', 'toto'],
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
self.assertRegex(out, r'left-little-finger')
|
||||
self.assertRegex(out, r'right-little-finger')
|
||||
|
||||
# Delete fingerprints
|
||||
out = subprocess.check_output(self.wrapper_args + [self.tools_prefix + 'fprintd-delete', 'toto'],
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
self.assertRegex(out, r'Fingerprints deleted')
|
||||
|
||||
# Doesn't have fingerprints
|
||||
out = subprocess.check_output(self.wrapper_args + [self.tools_prefix + 'fprintd-list', 'toto'],
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
self.assertRegex(out, r'has no fingers enrolled for')
|
||||
with self.assertRaisesRegex(AssertionError, r'Device already in use'):
|
||||
self.start_verify_process()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# avoid writing to stderr
|
||||
|
||||
46
tests/unittest_inspector.py
Executable file
46
tests/unittest_inspector.py
Executable file
@ -0,0 +1,46 @@
|
||||
#! /usr/bin/env python3
|
||||
# Copyright © 2020, Canonical Ltd
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
# Authors:
|
||||
# Marco Trevisan <marco.trevisan@canonical.com>
|
||||
|
||||
import argparse
|
||||
import importlib.util
|
||||
import inspect
|
||||
import os
|
||||
import unittest
|
||||
|
||||
def list_tests(module):
|
||||
tests = []
|
||||
for name, obj in inspect.getmembers(module):
|
||||
if inspect.isclass(obj) and issubclass(obj, unittest.TestCase):
|
||||
cases = unittest.defaultTestLoader.getTestCaseNames(obj)
|
||||
tests += [ (obj, '{}.{}'.format(name, t)) for t in cases ]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('unittest_source', type=argparse.FileType('r'))
|
||||
|
||||
args = parser.parse_args()
|
||||
source_path = args.unittest_source.name
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
os.path.basename(source_path), source_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
for machine, human in list_tests(module):
|
||||
print(human)
|
||||
113
utils/delete.c
113
utils/delete.c
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* fprintd example to delete fingerprints
|
||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -20,108 +21,116 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <dbus/dbus-glib-bindings.h>
|
||||
#include "manager-dbus-glue.h"
|
||||
#include "device-dbus-glue.h"
|
||||
#include "fprintd-dbus.h"
|
||||
|
||||
static DBusGProxy *manager = NULL;
|
||||
static DBusGConnection *connection = NULL;
|
||||
static FprintDBusManager *manager = NULL;
|
||||
static GDBusConnection *connection = NULL;
|
||||
|
||||
static void create_manager(void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
if (connection == NULL) {
|
||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
manager = dbus_g_proxy_new_for_name(connection,
|
||||
"net.reactivated.Fprint", "/net/reactivated/Fprint/Manager",
|
||||
"net.reactivated.Fprint.Manager");
|
||||
}
|
||||
|
||||
static void delete_fingerprints(DBusGProxy *dev, const char *username)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GHashTable *props;
|
||||
DBusGProxy *p;
|
||||
|
||||
p = dbus_g_proxy_new_from_proxy(dev, "org.freedesktop.DBus.Properties", NULL);
|
||||
if (!dbus_g_proxy_call (p, "GetAll", &error, G_TYPE_STRING, "net.reactivated.Fprint.Device", G_TYPE_INVALID,
|
||||
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &props, G_TYPE_INVALID)) {
|
||||
g_print("GetAll on the Properties interface failed: %s\n", error->message);
|
||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
"/net/reactivated/Fprint/Manager",
|
||||
NULL, &error);
|
||||
if (manager == NULL) {
|
||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!net_reactivated_Fprint_Device_claim(dev, username, &error)) {
|
||||
static void delete_fingerprints (FprintDBusDevice *dev, const char *username)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error)) {
|
||||
g_print("failed to claim device: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!net_reactivated_Fprint_Device_delete_enrolled_fingers2(dev, &error)) {
|
||||
if (dbus_g_error_has_name (error, "net.reactivated.Fprint.Error.NoEnrolledPrints") == FALSE) {
|
||||
g_print("ListEnrolledFingers failed: %s\n", error->message);
|
||||
if (!fprint_dbus_device_call_delete_enrolled_fingers2_sync (dev, NULL,
|
||||
&error)) {
|
||||
gboolean ignore_error = FALSE;
|
||||
if (g_dbus_error_is_remote_error (error)) {
|
||||
g_autofree char *dbus_error =
|
||||
g_dbus_error_get_remote_error (error);
|
||||
if (g_str_equal (dbus_error,
|
||||
"net.reactivated.Fprint.Error.NoEnrolledPrints")) {
|
||||
g_print ("No fingerprints to delete on %s\n",
|
||||
fprint_dbus_device_get_name (dev));
|
||||
ignore_error = TRUE;
|
||||
}
|
||||
}
|
||||
if (!ignore_error) {
|
||||
g_print("ListEnrolledFingers failed: %s\n",
|
||||
error->message);
|
||||
exit (1);
|
||||
} else {
|
||||
g_print ("No fingerprints to delete on %s\n", g_value_get_string (g_hash_table_lookup (props, "name")));
|
||||
g_print ("No fingerprints to delete on %s\n",
|
||||
fprint_dbus_device_get_name (dev));
|
||||
}
|
||||
} else {
|
||||
g_print ("Fingerprints deleted on %s\n", g_value_get_string (g_hash_table_lookup (props, "name")));
|
||||
g_print ("Fingerprints deleted on %s\n",
|
||||
fprint_dbus_device_get_name (dev));
|
||||
}
|
||||
g_clear_error (&error);
|
||||
|
||||
if (!net_reactivated_Fprint_Device_release(dev, &error)) {
|
||||
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error)) {
|
||||
g_print("ReleaseDevice failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (props);
|
||||
g_object_unref (p);
|
||||
}
|
||||
|
||||
static void process_devices(char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GPtrArray *devices;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) devices = NULL;
|
||||
char *path;
|
||||
guint num_devices;
|
||||
guint i;
|
||||
|
||||
if (!net_reactivated_Fprint_Manager_get_devices(manager, &devices, &error)) {
|
||||
g_print("list_devices failed: %s\n", error->message);
|
||||
if (!fprint_dbus_manager_call_get_devices_sync (manager, &devices,
|
||||
NULL, &error)) {
|
||||
g_print("Impossible to get devices: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (devices->len == 0) {
|
||||
g_print("No devices found\n");
|
||||
num_devices = g_strv_length (devices);
|
||||
if (num_devices == 0) {
|
||||
g_print("No devices available\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_print("found %d devices\n", devices->len);
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
path = g_ptr_array_index(devices, i);
|
||||
g_print ("found %u devices\n", num_devices);
|
||||
for (i = 0; devices[i] != NULL; i++) {
|
||||
path = devices[i];
|
||||
g_print("Device at %s\n", path);
|
||||
}
|
||||
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
for (i = 0; devices[i] != NULL; i++) {
|
||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||
guint j;
|
||||
DBusGProxy *dev;
|
||||
|
||||
path = g_ptr_array_index(devices, i);
|
||||
path = devices[i];
|
||||
g_print("Using device %s\n", path);
|
||||
|
||||
/* FIXME use for_name_owner?? */
|
||||
dev = dbus_g_proxy_new_for_name(connection, "net.reactivated.Fprint",
|
||||
path, "net.reactivated.Fprint.Device");
|
||||
/* NOTE: We should handle error cases! */
|
||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
path, NULL, NULL);
|
||||
|
||||
for (j = 1; argv[j] != NULL; j++)
|
||||
delete_fingerprints (dev, argv[j]);
|
||||
|
||||
g_object_unref (dev);
|
||||
}
|
||||
|
||||
g_ptr_array_foreach(devices, (GFunc) g_free, NULL);
|
||||
g_ptr_array_free(devices, TRUE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
113
utils/enroll.c
113
utils/enroll.c
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* fprintd example to enroll right index finger
|
||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -21,64 +22,67 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <dbus/dbus-glib-bindings.h>
|
||||
#include "manager-dbus-glue.h"
|
||||
#include "device-dbus-glue.h"
|
||||
#include "marshal.h"
|
||||
#include "fprintd-dbus.h"
|
||||
|
||||
#define N_(x) x
|
||||
#define TR(x) x
|
||||
#include "fingerprint-strings.h"
|
||||
|
||||
static DBusGProxy *manager = NULL;
|
||||
static DBusGConnection *connection = NULL;
|
||||
static FprintDBusManager *manager = NULL;
|
||||
static GDBusConnection *connection = NULL;
|
||||
static char *finger_name = NULL;
|
||||
static char **usernames = NULL;
|
||||
|
||||
static void create_manager(void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
if (connection == NULL) {
|
||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
manager = dbus_g_proxy_new_for_name(connection,
|
||||
"net.reactivated.Fprint", "/net/reactivated/Fprint/Manager",
|
||||
"net.reactivated.Fprint.Manager");
|
||||
}
|
||||
|
||||
static DBusGProxy *open_device(const char *username)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gchar *path;
|
||||
DBusGProxy *dev;
|
||||
|
||||
if (!net_reactivated_Fprint_Manager_get_default_device(manager, &path, &error)) {
|
||||
g_print("list_devices failed: %s\n", error->message);
|
||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
"/net/reactivated/Fprint/Manager",
|
||||
NULL, &error);
|
||||
if (manager == NULL) {
|
||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
g_print("No devices found\n");
|
||||
static FprintDBusDevice *open_device (const char *username)
|
||||
{
|
||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree char *path = NULL;
|
||||
|
||||
if (!fprint_dbus_manager_call_get_default_device_sync (manager, &path,
|
||||
NULL, &error)) {
|
||||
g_print("Impossible to enroll: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_print("Using device %s\n", path);
|
||||
|
||||
/* FIXME use for_name_owner?? */
|
||||
dev = dbus_g_proxy_new_for_name(connection, "net.reactivated.Fprint",
|
||||
path, "net.reactivated.Fprint.Device");
|
||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
path, NULL, &error);
|
||||
|
||||
g_free (path);
|
||||
if (error) {
|
||||
g_print ("failed to connect to device: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!net_reactivated_Fprint_Device_claim(dev, username, &error)) {
|
||||
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error)) {
|
||||
g_print("failed to claim device: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
return dev;
|
||||
return g_steal_pointer (&dev);
|
||||
}
|
||||
|
||||
static void enroll_result(GObject *object, const char *result, gboolean done, void *user_data)
|
||||
@ -89,16 +93,30 @@ static void enroll_result(GObject *object, const char *result, gboolean done, vo
|
||||
*enroll_completed = TRUE;
|
||||
}
|
||||
|
||||
static void do_enroll(DBusGProxy *dev)
|
||||
static void proxy_signal_cb (GDBusProxy *proxy,
|
||||
const gchar *sender_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (g_str_equal (signal_name, "EnrollStatus")) {
|
||||
const gchar *result;
|
||||
gboolean done;
|
||||
|
||||
g_variant_get (parameters, "(&sb)", &result, &done);
|
||||
enroll_result (G_OBJECT (proxy), result, done, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_enroll (FprintDBusDevice *dev)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
gboolean enroll_completed = FALSE;
|
||||
gboolean found;
|
||||
guint i;
|
||||
|
||||
dbus_g_proxy_add_signal(dev, "EnrollStatus", G_TYPE_STRING, G_TYPE_BOOLEAN, NULL);
|
||||
dbus_g_proxy_connect_signal(dev, "EnrollStatus", G_CALLBACK(enroll_result),
|
||||
&enroll_completed, NULL);
|
||||
g_signal_connect (dev, "g-signal", G_CALLBACK (proxy_signal_cb),
|
||||
&enroll_completed);
|
||||
|
||||
found = FALSE;
|
||||
for (i = 0; fingers[i].dbus_name != NULL; i++) {
|
||||
@ -108,7 +126,7 @@ static void do_enroll(DBusGProxy *dev)
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
GString *s;
|
||||
g_autoptr(GString) s = NULL;
|
||||
|
||||
s = g_string_new (NULL);
|
||||
g_string_append_printf (s, "Invalid finger name '%s'. Name must be one of ", finger_name);
|
||||
@ -118,12 +136,12 @@ static void do_enroll(DBusGProxy *dev)
|
||||
g_string_append (s, ", ");
|
||||
}
|
||||
g_warning ("%s", s->str);
|
||||
g_string_free (s, TRUE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_print("Enrolling %s finger.\n", finger_name);
|
||||
if (!net_reactivated_Fprint_Device_enroll_start(dev, finger_name, &error)) {
|
||||
if (!fprint_dbus_device_call_enroll_start_sync (dev, finger_name, NULL,
|
||||
&error)) {
|
||||
g_print("EnrollStart failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
@ -131,19 +149,18 @@ static void do_enroll(DBusGProxy *dev)
|
||||
while (!enroll_completed)
|
||||
g_main_context_iteration(NULL, TRUE);
|
||||
|
||||
dbus_g_proxy_disconnect_signal(dev, "EnrollStatus",
|
||||
G_CALLBACK(enroll_result), &enroll_completed);
|
||||
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb, &enroll_result);
|
||||
|
||||
if (!net_reactivated_Fprint_Device_enroll_stop(dev, &error)) {
|
||||
if (!fprint_dbus_device_call_enroll_stop_sync (dev, NULL, &error)) {
|
||||
g_print("VerifyStop failed: %s\n", error->message);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void release_device(DBusGProxy *dev)
|
||||
static void release_device (FprintDBusDevice *dev)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (!net_reactivated_Fprint_Device_release(dev, &error)) {
|
||||
g_autoptr(GError) error = NULL;
|
||||
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error)) {
|
||||
g_print("ReleaseDevice failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
@ -157,21 +174,17 @@ static const GOptionEntry entries[] = {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||
GOptionContext *context;
|
||||
GError *err = NULL;
|
||||
DBusGProxy *dev;
|
||||
g_autoptr(GError) err = NULL;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
dbus_g_object_register_marshaller (fprintd_marshal_VOID__STRING_BOOLEAN,
|
||||
G_TYPE_NONE, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID);
|
||||
|
||||
context = g_option_context_new ("Enroll a fingerprint");
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
|
||||
if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
|
||||
g_print ("couldn't parse command-line options: %s\n", err->message);
|
||||
g_error_free (err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -180,7 +193,7 @@ int main(int argc, char **argv)
|
||||
|
||||
create_manager();
|
||||
|
||||
dev = open_device(usernames ? usernames[0] : NULL);
|
||||
dev = open_device (usernames ? usernames[0] : "");
|
||||
do_enroll(dev);
|
||||
release_device(dev);
|
||||
g_free(finger_name);
|
||||
|
||||
107
utils/list.c
107
utils/list.c
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* fprintd example to list enrolled fingerprints
|
||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -20,113 +21,115 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <dbus/dbus-glib-bindings.h>
|
||||
#include "manager-dbus-glue.h"
|
||||
#include "device-dbus-glue.h"
|
||||
#include "fprintd-dbus.h"
|
||||
|
||||
static DBusGProxy *manager = NULL;
|
||||
static DBusGConnection *connection = NULL;
|
||||
static FprintDBusManager *manager = NULL;
|
||||
static GDBusConnection *connection = NULL;
|
||||
|
||||
static void create_manager(void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
if (connection == NULL) {
|
||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
manager = dbus_g_proxy_new_for_name(connection,
|
||||
"net.reactivated.Fprint", "/net/reactivated/Fprint/Manager",
|
||||
"net.reactivated.Fprint.Manager");
|
||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
"/net/reactivated/Fprint/Manager",
|
||||
NULL, &error);
|
||||
if (manager == NULL) {
|
||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void list_fingerprints(DBusGProxy *dev, const char *username)
|
||||
static void list_fingerprints (FprintDBusDevice *dev, const char *username)
|
||||
{
|
||||
GError *error = NULL;
|
||||
char **fingers;
|
||||
GHashTable *props;
|
||||
DBusGProxy *p;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) fingers = NULL;
|
||||
guint i;
|
||||
|
||||
if (!net_reactivated_Fprint_Device_list_enrolled_fingers(dev, username, &fingers, &error)) {
|
||||
if (dbus_g_error_has_name (error, "net.reactivated.Fprint.Error.NoEnrolledPrints") == FALSE) {
|
||||
g_print("ListEnrolledFingers failed: %s\n", error->message);
|
||||
exit (1);
|
||||
} else {
|
||||
fingers = NULL;
|
||||
if (!fprint_dbus_device_call_list_enrolled_fingers_sync (dev, username,
|
||||
&fingers, NULL,
|
||||
&error)) {
|
||||
gboolean ignore_error = FALSE;
|
||||
if (g_dbus_error_is_remote_error (error)) {
|
||||
g_autofree char *dbus_error =
|
||||
g_dbus_error_get_remote_error (error);
|
||||
if (g_str_equal (dbus_error,
|
||||
"net.reactivated.Fprint.Error.NoEnrolledPrints")) {
|
||||
ignore_error = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
p = dbus_g_proxy_new_from_proxy(dev, "org.freedesktop.DBus.Properties", NULL);
|
||||
if (!dbus_g_proxy_call (p, "GetAll", &error, G_TYPE_STRING, "net.reactivated.Fprint.Device", G_TYPE_INVALID,
|
||||
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &props, G_TYPE_INVALID)) {
|
||||
g_print("GetAll on the Properties interface failed: %s\n", error->message);
|
||||
if (!ignore_error) {
|
||||
g_print("ListEnrolledFingers failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (fingers == NULL || g_strv_length (fingers) == 0) {
|
||||
g_print("User %s has no fingers enrolled for %s.\n", username, g_value_get_string (g_hash_table_lookup (props, "name")));
|
||||
g_print ("User %s has no fingers enrolled for %s.\n", username,
|
||||
fprint_dbus_device_get_name (dev));
|
||||
return;
|
||||
}
|
||||
|
||||
g_print("Fingerprints for user %s on %s (%s):\n",
|
||||
username,
|
||||
g_value_get_string (g_hash_table_lookup (props, "name")),
|
||||
g_value_get_string (g_hash_table_lookup (props, "scan-type")));
|
||||
g_hash_table_destroy (props);
|
||||
g_object_unref (p);
|
||||
fprint_dbus_device_get_name (dev),
|
||||
fprint_dbus_device_get_scan_type (dev));
|
||||
|
||||
for (i = 0; fingers[i] != NULL; i++) {
|
||||
g_print(" - #%d: %s\n", i, fingers[i]);
|
||||
}
|
||||
|
||||
g_strfreev (fingers);
|
||||
}
|
||||
|
||||
static void process_devices(char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GPtrArray *devices;
|
||||
g_auto(GStrv) devices = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
char *path;
|
||||
guint num_devices;
|
||||
guint i;
|
||||
|
||||
if (!net_reactivated_Fprint_Manager_get_devices(manager, &devices, &error)) {
|
||||
g_print("list_devices failed: %s\n", error->message);
|
||||
if (!fprint_dbus_manager_call_get_devices_sync (manager, &devices, NULL,
|
||||
&error)) {
|
||||
g_print("Impossible to get devices: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (devices->len == 0) {
|
||||
g_print("No devices found\n");
|
||||
num_devices = g_strv_length (devices);
|
||||
if (num_devices == 0) {
|
||||
g_print("No devices available\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_print("found %d devices\n", devices->len);
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
path = g_ptr_array_index(devices, i);
|
||||
g_print ("found %u devices\n", num_devices);
|
||||
for (i = 0; devices[i] != NULL; i++) {
|
||||
path = devices[i];
|
||||
g_print("Device at %s\n", path);
|
||||
}
|
||||
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
for (i = 0; devices[i] != NULL; i++) {
|
||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||
guint j;
|
||||
DBusGProxy *dev;
|
||||
|
||||
path = g_ptr_array_index(devices, i);
|
||||
path = devices[i];
|
||||
g_print("Using device %s\n", path);
|
||||
|
||||
/* FIXME use for_name_owner?? */
|
||||
dev = dbus_g_proxy_new_for_name(connection, "net.reactivated.Fprint",
|
||||
path, "net.reactivated.Fprint.Device");
|
||||
/* NOTE: We should handle error cases! */
|
||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
path, NULL, NULL);
|
||||
|
||||
for (j = 1; argv[j] != NULL; j++)
|
||||
list_fingerprints (dev, argv[j]);
|
||||
|
||||
g_object_unref (dev);
|
||||
}
|
||||
|
||||
g_ptr_array_foreach(devices, (GFunc) g_free, NULL);
|
||||
g_ptr_array_free(devices, TRUE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
||||
@ -1,52 +1,19 @@
|
||||
dbus_client_glue_sources = []
|
||||
|
||||
foreach interface_name: dbus_interfaces
|
||||
interface = interface_name.to_lower()
|
||||
interface_file = meson.source_root() / 'src' / interface + '.xml'
|
||||
glue_name = interface + '-dbus-glue.h'
|
||||
dbus_client_glue_sources += custom_target(glue_name,
|
||||
input: interface_file,
|
||||
output: glue_name,
|
||||
command: [
|
||||
dbus_binding_tool,
|
||||
'--prefix=fprint_' + interface,
|
||||
'--mode=glib-client',
|
||||
'--output=@OUTPUT@',
|
||||
'@INPUT@',
|
||||
])
|
||||
endforeach
|
||||
|
||||
utils_marshal = custom_target('utils_marshal',
|
||||
depends: fprintd_marshal,
|
||||
input: fprintd_marshal,
|
||||
output: ['marshal.c', 'marshal.h'],
|
||||
command: [bash, '-c',
|
||||
'cp @INPUT0@ @OUTPUT0@;' +
|
||||
'cp @INPUT1@ @OUTPUT1@;' +
|
||||
'sed s/fprintd-//g -i ' + meson.current_build_dir() / 'marshal*.{h,c}']
|
||||
)
|
||||
|
||||
libfprintd_utils_dep = declare_dependency(
|
||||
include_directories: [
|
||||
include_directories('../src'),
|
||||
include_directories('../pam'),
|
||||
],
|
||||
dependencies: [
|
||||
glib_dep,
|
||||
dbus_glib_dep,
|
||||
gio_dep,
|
||||
gio_unix_dep,
|
||||
],
|
||||
sources: [
|
||||
utils_marshal,
|
||||
dbus_client_glue_sources,
|
||||
fprintd_dbus_sources,
|
||||
],
|
||||
link_with: static_library('fprintd_utils',
|
||||
sources: [
|
||||
dbus_client_glue_sources,
|
||||
utils_marshal,
|
||||
link_with: [
|
||||
libfprintd_private
|
||||
],
|
||||
dependencies: [
|
||||
glib_dep,
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
utils = [
|
||||
|
||||
140
utils/verify.c
140
utils/verify.c
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* fprintd example to verify a fingerprint
|
||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -21,71 +22,77 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <dbus/dbus-glib-bindings.h>
|
||||
#include "manager-dbus-glue.h"
|
||||
#include "device-dbus-glue.h"
|
||||
#include "marshal.h"
|
||||
#include <gio/gio.h>
|
||||
#include "fprintd-dbus.h"
|
||||
|
||||
static DBusGProxy *manager = NULL;
|
||||
static DBusGConnection *connection = NULL;
|
||||
static FprintDBusManager *manager = NULL;
|
||||
static GDBusConnection *connection = NULL;
|
||||
static char *finger_name = NULL;
|
||||
static gboolean g_fatal_warnings = FALSE;
|
||||
static char **usernames = NULL;
|
||||
|
||||
static void create_manager(void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
if (connection == NULL) {
|
||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
manager = dbus_g_proxy_new_for_name(connection,
|
||||
"net.reactivated.Fprint", "/net/reactivated/Fprint/Manager",
|
||||
"net.reactivated.Fprint.Manager");
|
||||
}
|
||||
|
||||
static DBusGProxy *open_device(const char *username)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gchar *path;
|
||||
DBusGProxy *dev;
|
||||
|
||||
if (!net_reactivated_Fprint_Manager_get_default_device(manager, &path, &error)) {
|
||||
g_print("list_devices failed: %s\n", error->message);
|
||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
"/net/reactivated/Fprint/Manager",
|
||||
NULL, &error);
|
||||
if (manager == NULL) {
|
||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
g_print("No devices found\n");
|
||||
static FprintDBusDevice *open_device (const char *username)
|
||||
{
|
||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree char *path = NULL;
|
||||
|
||||
if (!fprint_dbus_manager_call_get_default_device_sync (manager, &path,
|
||||
NULL, &error)) {
|
||||
g_print("Impossible to verify: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_print("Using device %s\n", path);
|
||||
|
||||
/* FIXME use for_name_owner?? */
|
||||
dev = dbus_g_proxy_new_for_name(connection, "net.reactivated.Fprint",
|
||||
path, "net.reactivated.Fprint.Device");
|
||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"net.reactivated.Fprint",
|
||||
path, NULL, &error);
|
||||
|
||||
g_free (path);
|
||||
if (error) {
|
||||
g_print ("failed to connect to device: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!net_reactivated_Fprint_Device_claim(dev, username, &error)) {
|
||||
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error)) {
|
||||
g_print("failed to claim device: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return dev;
|
||||
return g_steal_pointer (&dev);
|
||||
}
|
||||
|
||||
static void find_finger(DBusGProxy *dev, const char *username)
|
||||
static void find_finger (FprintDBusDevice *dev, const char *username)
|
||||
{
|
||||
GError *error = NULL;
|
||||
char **fingers;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) fingers = NULL;
|
||||
guint i;
|
||||
|
||||
if (!net_reactivated_Fprint_Device_list_enrolled_fingers(dev, username, &fingers, &error)) {
|
||||
if (!fprint_dbus_device_call_list_enrolled_fingers_sync (dev, username,
|
||||
&fingers,
|
||||
NULL, &error)) {
|
||||
g_print("ListEnrolledFingers failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
@ -100,12 +107,17 @@ static void find_finger(DBusGProxy *dev, const char *username)
|
||||
g_print(" - #%d: %s\n", i, fingers[i]);
|
||||
}
|
||||
|
||||
if (finger_name == NULL || strcmp (finger_name, "any") == 0) {
|
||||
if (finger_name && !g_str_equal (finger_name, "any") &&
|
||||
!g_strv_contains ((const char **) fingers, finger_name)) {
|
||||
g_print("Finger '%s' not enrolled for user %s.\n", finger_name,
|
||||
username);
|
||||
g_free (finger_name);
|
||||
finger_name = g_strdup (fingers[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_strfreev (fingers);
|
||||
if (finger_name == NULL) {
|
||||
finger_name = g_strdup (fingers[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void verify_result(GObject *object, const char *result, gboolean done, void *user_data)
|
||||
@ -121,19 +133,36 @@ static void verify_finger_selected(GObject *object, const char *name, void *user
|
||||
g_print("Verifying: %s\n", name);
|
||||
}
|
||||
|
||||
static void do_verify(DBusGProxy *dev)
|
||||
static void proxy_signal_cb (GDBusProxy *proxy,
|
||||
const gchar *sender_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (g_str_equal (signal_name, "VerifyStatus")) {
|
||||
const gchar *result;
|
||||
gboolean done;
|
||||
|
||||
g_variant_get (parameters, "(&sb)", &result, &done);
|
||||
verify_result (G_OBJECT (proxy), result, done, user_data);
|
||||
} else if (g_str_equal (signal_name, "VerifyFingerSelected")) {
|
||||
const gchar *name;
|
||||
|
||||
g_variant_get (parameters, "(&s)", &name);
|
||||
verify_finger_selected (G_OBJECT (proxy), name, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_verify (FprintDBusDevice *dev)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
gboolean verify_completed = FALSE;
|
||||
|
||||
dbus_g_proxy_add_signal(dev, "VerifyStatus", G_TYPE_STRING, G_TYPE_BOOLEAN, NULL);
|
||||
dbus_g_proxy_add_signal(dev, "VerifyFingerSelected", G_TYPE_INT, NULL);
|
||||
dbus_g_proxy_connect_signal(dev, "VerifyStatus", G_CALLBACK(verify_result),
|
||||
&verify_completed, NULL);
|
||||
dbus_g_proxy_connect_signal(dev, "VerifyFingerSelected", G_CALLBACK(verify_finger_selected),
|
||||
NULL, NULL);
|
||||
g_signal_connect (dev, "g-signal", G_CALLBACK (proxy_signal_cb),
|
||||
&verify_completed);
|
||||
|
||||
if (!net_reactivated_Fprint_Device_verify_start(dev, finger_name, &error)) {
|
||||
if (!fprint_dbus_device_call_verify_start_sync (dev, finger_name, NULL,
|
||||
&error)) {
|
||||
g_print("VerifyStart failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
@ -141,19 +170,20 @@ static void do_verify(DBusGProxy *dev)
|
||||
while (!verify_completed)
|
||||
g_main_context_iteration(NULL, TRUE);
|
||||
|
||||
dbus_g_proxy_disconnect_signal(dev, "VerifyStatus", G_CALLBACK(verify_result), &verify_completed);
|
||||
dbus_g_proxy_disconnect_signal(dev, "VerifyFingerSelected", G_CALLBACK(verify_finger_selected), NULL);
|
||||
|
||||
if (!net_reactivated_Fprint_Device_verify_stop(dev, &error)) {
|
||||
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb,
|
||||
&verify_completed);
|
||||
|
||||
if (!fprint_dbus_device_call_verify_stop_sync (dev, NULL, &error)) {
|
||||
g_print("VerifyStop failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void release_device(DBusGProxy *dev)
|
||||
static void release_device (FprintDBusDevice *dev)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (!net_reactivated_Fprint_Device_release(dev, &error)) {
|
||||
g_autoptr(GError) error = NULL;
|
||||
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error)) {
|
||||
g_print("ReleaseDevice failed: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
@ -168,22 +198,18 @@ static const GOptionEntry entries[] = {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||
g_autoptr(GError) err = NULL;
|
||||
GOptionContext *context;
|
||||
GError *err = NULL;
|
||||
DBusGProxy *dev;
|
||||
const char *username = NULL;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
dbus_g_object_register_marshaller (fprintd_marshal_VOID__STRING_BOOLEAN,
|
||||
G_TYPE_NONE, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID);
|
||||
|
||||
context = g_option_context_new ("Verify a fingerprint");
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
|
||||
if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
|
||||
g_print ("couldn't parse command-line options: %s\n", err->message);
|
||||
g_error_free (err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user