mirror of
https://gitlab.com/mishakmak/pam-fprint-grosshack.git
synced 2026-04-09 12:23:34 +02:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d22a2b5b9 | |||
| de725a91e4 | |||
| 18392cba54 | |||
| 783d82f359 | |||
| c00a3375d1 | |||
| 5aa61adabc | |||
| 1fc10f15ee | |||
| c24badfd68 | |||
| 4612c1f3ed | |||
| ca216a32af | |||
| 944493e472 | |||
| 34f24cbe19 | |||
| 9314069a88 | |||
| 66e21eac8f | |||
| f73429f062 | |||
| c18ebaf9da | |||
| 4a80bfacec | |||
| 52058c1ea0 | |||
| 22cdc0a7ea | |||
| 043fcaafec | |||
| bf2236620e | |||
| 0122d351f9 | |||
| 4435706d20 | |||
| c5877bbc12 | |||
| a170a3a09f | |||
| a76af6ce71 | |||
| 34a24eac77 | |||
| 47751548b2 | |||
| a30c45629e | |||
| 3242b99410 | |||
| 5ccb9ba0ec | |||
| f4eaacd0ec | |||
| 34b21fa917 | |||
| 2d98d4543f | |||
| 8c46fddd03 | |||
| 3a00643d5b | |||
| eb73e024e1 | |||
| a4b06c2219 | |||
| 5ccaa094a0 | |||
| fc7e4d0e5c | |||
| 583cd870d8 | |||
| 2ca2d5e62c | |||
| c5c81a2ea8 | |||
| c0ad5880a4 | |||
| 2dc3a4e2c5 | |||
| 3b0d93bcc2 | |||
| eac171ab0f | |||
| 7533f63a06 | |||
| a38917ab26 | |||
| a92b8e5f60 | |||
| 29f34cf23c | |||
| a10f0dc22d | |||
| 267b322f6d | |||
| 3b83240e57 | |||
| 897cbd341e | |||
| 9d0305ea05 | |||
| 3dbfdabe01 | |||
| 45cf63d589 | |||
| 29ed88a50a | |||
| e301779c20 | |||
| be5d283a3e | |||
| ebfcbdd13e | |||
| ec7376d7e6 | |||
| df568e1ce1 | |||
| 7ee61393ec | |||
| 57ca0dc95e | |||
| 85ba309e9d | |||
| 3f2174676e | |||
| 5e18d46971 | |||
| a8bd2bc25e |
7
.git-blame-ignore-revs
Normal file
7
.git-blame-ignore-revs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# The commits that did automated reformatting. You can ignore them
|
||||||
|
# during git-blame with `--ignore-rev` or `--ignore-revs-file`.
|
||||||
|
#
|
||||||
|
# $ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
|
||||||
|
#
|
||||||
|
|
||||||
|
f73429f06226f5423c92b1c504313657c9b6f9b5
|
||||||
@ -29,6 +29,11 @@ variables:
|
|||||||
|
|
||||||
image: "$FEDORA_IMAGE"
|
image: "$FEDORA_IMAGE"
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- check-source
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
|
||||||
.fprintd_build_preconditions:
|
.fprintd_build_preconditions:
|
||||||
except:
|
except:
|
||||||
variables:
|
variables:
|
||||||
@ -47,8 +52,17 @@ image: "$FEDORA_IMAGE"
|
|||||||
# So we don't get error about this libfprint file
|
# So we don't get error about this libfprint file
|
||||||
- echo "libfprint/demo/gtk-libfprint-test.ui" >> po/POTFILES.skip
|
- echo "libfprint/demo/gtk-libfprint-test.ui" >> po/POTFILES.skip
|
||||||
|
|
||||||
|
test_indent:
|
||||||
|
stage: check-source
|
||||||
|
extends: .fprintd_build_preconditions
|
||||||
|
script:
|
||||||
|
- scripts/uncrustify.sh
|
||||||
|
- git diff
|
||||||
|
- "! git status -s | grep -q ."
|
||||||
|
|
||||||
build_stable:
|
build_stable:
|
||||||
extends: .fprintd_build_preconditions
|
extends: .fprintd_build_preconditions
|
||||||
|
stage: build
|
||||||
script:
|
script:
|
||||||
- meson _build
|
- meson _build
|
||||||
- ninja -C _build -v
|
- ninja -C _build -v
|
||||||
@ -58,6 +72,7 @@ build_dev:
|
|||||||
extends:
|
extends:
|
||||||
- .fprintd_build_preconditions
|
- .fprintd_build_preconditions
|
||||||
- .install_libfprint_dev
|
- .install_libfprint_dev
|
||||||
|
stage: build
|
||||||
script:
|
script:
|
||||||
- meson _build --werror -Dgtk_doc=true
|
- meson _build --werror -Dgtk_doc=true
|
||||||
- ninja -C _build -v
|
- ninja -C _build -v
|
||||||
|
|||||||
51
NEWS
51
NEWS
@ -1,6 +1,57 @@
|
|||||||
This file lists notable changes in each release. For the full history of all
|
This file lists notable changes in each release. For the full history of all
|
||||||
changes, see ChangeLog.
|
changes, see ChangeLog.
|
||||||
|
|
||||||
|
Version 1.90.8:
|
||||||
|
|
||||||
|
It seems that we are finally reaching the end of the tunnel with regard
|
||||||
|
to regressions. One more issue that cropped up was that a pam_fprintd fix
|
||||||
|
to avoid a possible authentication bypass caused issues when fprintd was
|
||||||
|
just started on demand.
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
- pam: Only listen to NameOwnerChanged after fprintd is known to run (#94)
|
||||||
|
- Place new ObjectManager DBus API at /net/reactivated/Fprint
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.90.7:
|
||||||
|
|
||||||
|
While 1.90.6 fixed a number of issues, we did have a bad regression due
|
||||||
|
causing pam_fprintd to crash when there are no fingerprint devices
|
||||||
|
installed.
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
- pam: Guard strdup calls against NULL pointers
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.90.6:
|
||||||
|
|
||||||
|
The 1.90.5 release was unusable due to a number of inter-related issues
|
||||||
|
with the DBus interface and authorization. We also found a number of
|
||||||
|
problems with possible security implications.
|
||||||
|
|
||||||
|
Currently fprintd will do interactive authorization even if this was not
|
||||||
|
requested using the correct DBus method call flag. All API users MUST be
|
||||||
|
updated to set the flag as it will be enabled in the future!
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
- Fix fprintd DBus configuration
|
||||||
|
- Change details of what requires authorization
|
||||||
|
- Fix various race conditions in pam_fprintd
|
||||||
|
- Permit interactive authorization from fprintd utilities
|
||||||
|
- Do not allow deletion while another operation is ongoing
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
Version 1.90.4:
|
||||||
|
|
||||||
This fprintd release contains major core reworkings and improved testing.
|
This fprintd release contains major core reworkings and improved testing.
|
||||||
|
|||||||
@ -9,3 +9,6 @@
|
|||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#mesondefine VERSION
|
#mesondefine VERSION
|
||||||
|
|
||||||
|
/* Whether current polkit version supports autopointers */
|
||||||
|
#mesondefine POLKIT_HAS_AUTOPOINTERS
|
||||||
|
|||||||
@ -11,15 +11,17 @@ configure_file(
|
|||||||
install_dir: dbus_service_dir,
|
install_dir: dbus_service_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(
|
if get_option('systemd')
|
||||||
configuration: configuration_data({
|
configure_file(
|
||||||
'libexecdir': fprintd_installdir,
|
configuration: configuration_data({
|
||||||
}),
|
'libexecdir': fprintd_installdir,
|
||||||
input: 'fprintd.service.in',
|
}),
|
||||||
output: 'fprintd.service',
|
input: 'fprintd.service.in',
|
||||||
install: true,
|
output: 'fprintd.service',
|
||||||
install_dir: systemd_unit_dir,
|
install: true,
|
||||||
)
|
install_dir: systemd_unit_dir,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
polkit_policy = 'net.reactivated.fprint.device.policy'
|
polkit_policy = 'net.reactivated.fprint.device.policy'
|
||||||
polkit_policy_target = i18n.merge_file(polkit_policy,
|
polkit_policy_target = i18n.merge_file(polkit_policy,
|
||||||
|
|||||||
@ -12,8 +12,18 @@
|
|||||||
|
|
||||||
<!-- Anyone can talk to the service -->
|
<!-- Anyone can talk to the service -->
|
||||||
<policy context="default">
|
<policy context="default">
|
||||||
<allow send_destination="net.reactivated.Fprint"/>
|
<allow send_destination="net.reactivated.Fprint"
|
||||||
<allow send_interface="net.reactivated.Fprint"/>
|
send_interface="net.reactivated.Fprint.Manager"/>
|
||||||
|
<allow send_destination="net.reactivated.Fprint"
|
||||||
|
send_interface="net.reactivated.Fprint.Device"/>
|
||||||
|
|
||||||
|
<!-- 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>
|
</policy>
|
||||||
|
|
||||||
</busconfig>
|
</busconfig>
|
||||||
|
|||||||
102
meson.build
102
meson.build
@ -1,49 +1,10 @@
|
|||||||
project('fprintd', 'c',
|
project('fprintd', 'c',
|
||||||
version: '1.90.4',
|
version: '1.90.8',
|
||||||
license: 'GPLv2+',
|
license: 'GPLv2+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
'warning_level=1',
|
'warning_level=3',
|
||||||
'c_std=gnu99',
|
'c_std=gnu99',
|
||||||
'c_args=' + ' '.join([
|
|
||||||
'-fno-strict-aliasing',
|
|
||||||
'-Wall',
|
|
||||||
'-Wcast-align',
|
|
||||||
'-Werror=address',
|
|
||||||
'-Werror=array-bounds',
|
|
||||||
'-Werror=empty-body',
|
|
||||||
'-Werror=implicit',
|
|
||||||
'-Werror=init-self',
|
|
||||||
'-Werror=int-to-pointer-cast',
|
|
||||||
'-Werror=main',
|
|
||||||
'-Werror=missing-braces',
|
|
||||||
'-Werror=nonnull',
|
|
||||||
'-Werror=pointer-to-int-cast',
|
|
||||||
'-Werror=redundant-decls',
|
|
||||||
'-Werror=return-type',
|
|
||||||
'-Werror=sequence-point',
|
|
||||||
'-Werror=trigraphs',
|
|
||||||
'-Werror=write-strings',
|
|
||||||
'-Wformat-nonliteral',
|
|
||||||
'-Wformat-security',
|
|
||||||
'-Wformat=2',
|
|
||||||
'-Wignored-qualifiers',
|
|
||||||
'-Wimplicit-function-declaration',
|
|
||||||
'-Wlogical-op',
|
|
||||||
'-Wmissing-declarations',
|
|
||||||
'-Wmissing-format-attribute',
|
|
||||||
'-Wmissing-include-dirs',
|
|
||||||
'-Wmissing-noreturn',
|
|
||||||
'-Wmissing-prototypes',
|
|
||||||
'-Wnested-externs',
|
|
||||||
'-Wold-style-definition',
|
|
||||||
'-Wpointer-arith',
|
|
||||||
'-Wshadow',
|
|
||||||
'-Wstrict-prototypes',
|
|
||||||
'-Wtype-limits',
|
|
||||||
'-Wundef',
|
|
||||||
'-Wunused',
|
|
||||||
]),
|
|
||||||
],
|
],
|
||||||
meson_version: '>= 0.50.0')
|
meson_version: '>= 0.50.0')
|
||||||
|
|
||||||
@ -51,7 +12,57 @@ gnome = import('gnome')
|
|||||||
i18n = import('i18n')
|
i18n = import('i18n')
|
||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
common_cflags = cc.get_supported_arguments([
|
||||||
|
'-fno-strict-aliasing',
|
||||||
|
'-Wcast-align',
|
||||||
|
'-Werror=address',
|
||||||
|
'-Werror=array-bounds',
|
||||||
|
'-Werror=empty-body',
|
||||||
|
'-Werror=implicit',
|
||||||
|
'-Werror=init-self',
|
||||||
|
'-Werror=int-to-pointer-cast',
|
||||||
|
'-Werror=main',
|
||||||
|
'-Werror=missing-braces',
|
||||||
|
'-Werror=nonnull',
|
||||||
|
'-Werror=pointer-to-int-cast',
|
||||||
|
'-Werror=redundant-decls',
|
||||||
|
'-Werror=return-type',
|
||||||
|
'-Werror=sequence-point',
|
||||||
|
'-Werror=trigraphs',
|
||||||
|
'-Werror=write-strings',
|
||||||
|
'-Wformat-nonliteral',
|
||||||
|
'-Wformat-security',
|
||||||
|
'-Wformat=2',
|
||||||
|
'-Wignored-qualifiers',
|
||||||
|
'-Wimplicit-function-declaration',
|
||||||
|
'-Wlogical-op',
|
||||||
|
'-Wmissing-declarations',
|
||||||
|
'-Wmissing-format-attribute',
|
||||||
|
'-Wmissing-include-dirs',
|
||||||
|
'-Wmissing-noreturn',
|
||||||
|
'-Wmissing-prototypes',
|
||||||
|
'-Wnested-externs',
|
||||||
|
'-Wold-style-definition',
|
||||||
|
'-Wpointer-arith',
|
||||||
|
'-Wshadow',
|
||||||
|
'-Wstrict-prototypes',
|
||||||
|
'-Wtype-limits',
|
||||||
|
'-Wundef',
|
||||||
|
'-Wunused',
|
||||||
|
])
|
||||||
|
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()
|
host_system = host_machine.system()
|
||||||
|
# NOTE: Bump gdbus-codegen min version once we can depend on 2.64!
|
||||||
glib_min_version = '2.56'
|
glib_min_version = '2.56'
|
||||||
libfprint_min_version = '1.90.1'
|
libfprint_min_version = '1.90.1'
|
||||||
|
|
||||||
@ -83,13 +94,17 @@ pod2man = find_program('pod2man', required: get_option('man'))
|
|||||||
xsltproc = find_program('xsltproc', required: get_option('gtk_doc'))
|
xsltproc = find_program('xsltproc', required: get_option('gtk_doc'))
|
||||||
|
|
||||||
# StateDirectory was introduced in systemd 235
|
# StateDirectory was introduced in systemd 235
|
||||||
systemd_dep = dependency('systemd', version: '>= 235')
|
systemd_dep = dependency('systemd', version: '>= 235', required: false)
|
||||||
systemd_unit_dir = get_option('systemd_system_unit_dir')
|
systemd_unit_dir = get_option('systemd_system_unit_dir')
|
||||||
|
|
||||||
if systemd_unit_dir == ''
|
if systemd_unit_dir == '' and systemd_dep.found()
|
||||||
systemd_unit_dir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir')
|
systemd_unit_dir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if get_option('systemd') and systemd_unit_dir == ''
|
||||||
|
error('systemd development files or systemd_system_unit_dir is needed for systemd support.')
|
||||||
|
endif
|
||||||
|
|
||||||
dbus_service_dir = get_option('dbus_service_dir')
|
dbus_service_dir = get_option('dbus_service_dir')
|
||||||
dbus_data_dir = datadir
|
dbus_data_dir = datadir
|
||||||
dbus_interfaces_dir = ''
|
dbus_interfaces_dir = ''
|
||||||
@ -139,6 +154,7 @@ cdata.set_quoted('GETTEXT_PACKAGE', meson.project_name())
|
|||||||
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||||
cdata.set_quoted('VERSION', meson.project_version())
|
cdata.set_quoted('VERSION', meson.project_version())
|
||||||
cdata.set_quoted('SYSCONFDIR', sysconfdir)
|
cdata.set_quoted('SYSCONFDIR', sysconfdir)
|
||||||
|
cdata.set('POLKIT_HAS_AUTOPOINTERS', polkit_gobject_dep.version().version_compare('>= 0.114'))
|
||||||
|
|
||||||
config_h = configure_file(
|
config_h = configure_file(
|
||||||
input: 'config.h.in',
|
input: 'config.h.in',
|
||||||
|
|||||||
@ -6,6 +6,10 @@ option('man',
|
|||||||
description: 'Generate the man files',
|
description: 'Generate the man files',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: true)
|
value: true)
|
||||||
|
option('systemd',
|
||||||
|
description: 'Install system service files',
|
||||||
|
type: 'boolean',
|
||||||
|
value: true)
|
||||||
option('systemd_system_unit_dir',
|
option('systemd_system_unit_dir',
|
||||||
description: 'Directory for systemd service files',
|
description: 'Directory for systemd service files',
|
||||||
type: 'string')
|
type: 'string')
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Helper functions to translate statuses and actions to strings
|
* Helper functions to translate statuses and actions to strings
|
||||||
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
|
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
|
||||||
*
|
*
|
||||||
* Experimental code. This will be moved out of fprintd into it's own
|
* Experimental code. This will be moved out of fprintd into it's own
|
||||||
* package once the system has matured.
|
* package once the system has matured.
|
||||||
*
|
*
|
||||||
@ -9,12 +9,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -28,115 +28,128 @@
|
|||||||
|
|
||||||
#define GNUC_UNUSED __attribute__((__unused__))
|
#define GNUC_UNUSED __attribute__((__unused__))
|
||||||
|
|
||||||
static bool str_equal (const char *a, const char *b)
|
static bool
|
||||||
|
str_equal (const char *a, const char *b)
|
||||||
{
|
{
|
||||||
if (a == NULL && b == NULL)
|
if (a == NULL && b == NULL)
|
||||||
return true;
|
return true;
|
||||||
if (a == NULL || b == NULL)
|
if (a == NULL || b == NULL)
|
||||||
return false;
|
return false;
|
||||||
return (strcmp (a, b) == 0);
|
return strcmp (a, b) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
struct
|
||||||
const char *dbus_name;
|
{
|
||||||
const char *place_str_generic;
|
const char *dbus_name;
|
||||||
const char *place_str_specific;
|
const char *place_str_generic;
|
||||||
const char *swipe_str_generic;
|
const char *place_str_specific;
|
||||||
const char *swipe_str_specific;
|
const char *swipe_str_generic;
|
||||||
|
const char *swipe_str_specific;
|
||||||
} fingers[] = {
|
} fingers[] = {
|
||||||
{ "any",
|
{ "any",
|
||||||
N_("Place your finger on the fingerprint reader"),
|
N_("Place your finger on the fingerprint reader"),
|
||||||
N_("Place your finger on %s"),
|
N_("Place your finger on %s"),
|
||||||
N_("Swipe your finger across the fingerprint reader"),
|
N_("Swipe your finger across the fingerprint reader"),
|
||||||
N_("Swipe your finger across %s") },
|
N_("Swipe your finger across %s") },
|
||||||
{ "left-thumb",
|
{ "left-thumb",
|
||||||
N_("Place your left thumb on the fingerprint reader"),
|
N_("Place your left thumb on the fingerprint reader"),
|
||||||
N_("Place your left thumb on %s"),
|
N_("Place your left thumb on %s"),
|
||||||
N_("Swipe your left thumb across the fingerprint reader"),
|
N_("Swipe your left thumb across the fingerprint reader"),
|
||||||
N_("Swipe your left thumb across %s") },
|
N_("Swipe your left thumb across %s") },
|
||||||
{ "left-index-finger",
|
{ "left-index-finger",
|
||||||
N_("Place your left index finger on the fingerprint reader"),
|
N_("Place your left index finger on the fingerprint reader"),
|
||||||
N_("Place your left index finger on %s"),
|
N_("Place your left index finger on %s"),
|
||||||
N_("Swipe your left index finger across the fingerprint reader"),
|
N_("Swipe your left index finger across the fingerprint reader"),
|
||||||
N_("Swipe your left index finger across %s") },
|
N_("Swipe your left index finger across %s") },
|
||||||
{ "left-middle-finger",
|
{ "left-middle-finger",
|
||||||
N_("Place your left middle finger on the fingerprint reader"),
|
N_("Place your left middle finger on the fingerprint reader"),
|
||||||
N_("Place your left middle finger on %s"),
|
N_("Place your left middle finger on %s"),
|
||||||
N_("Swipe your left middle finger across the fingerprint reader"),
|
N_("Swipe your left middle finger across the fingerprint reader"),
|
||||||
N_("Swipe your left middle finger across %s") },
|
N_("Swipe your left middle finger across %s") },
|
||||||
{ "left-ring-finger",
|
{ "left-ring-finger",
|
||||||
N_("Place your left ring finger on the fingerprint reader"),
|
N_("Place your left ring finger on the fingerprint reader"),
|
||||||
N_("Place your left ring finger on %s"),
|
N_("Place your left ring finger on %s"),
|
||||||
N_("Swipe your left ring finger across the fingerprint reader"),
|
N_("Swipe your left ring finger across the fingerprint reader"),
|
||||||
N_("Swipe your left ring finger across %s") },
|
N_("Swipe your left ring finger across %s") },
|
||||||
{ "left-little-finger",
|
{ "left-little-finger",
|
||||||
N_("Place your left little finger on the fingerprint reader"),
|
N_("Place your left little finger on the fingerprint reader"),
|
||||||
N_("Place your left little finger on %s"),
|
N_("Place your left little finger on %s"),
|
||||||
N_("Swipe your left little finger across the fingerprint reader"),
|
N_("Swipe your left little finger across the fingerprint reader"),
|
||||||
N_("Swipe your left little finger across %s") },
|
N_("Swipe your left little finger across %s") },
|
||||||
{ "right-thumb",
|
{ "right-thumb",
|
||||||
N_("Place your right thumb on the fingerprint reader"),
|
N_("Place your right thumb on the fingerprint reader"),
|
||||||
N_("Place your right thumb on %s"),
|
N_("Place your right thumb on %s"),
|
||||||
N_("Swipe your right thumb across the fingerprint reader"),
|
N_("Swipe your right thumb across the fingerprint reader"),
|
||||||
N_("Swipe your right thumb across %s") },
|
N_("Swipe your right thumb across %s") },
|
||||||
{ "right-index-finger",
|
{ "right-index-finger",
|
||||||
N_("Place your right index finger on the fingerprint reader"),
|
N_("Place your right index finger on the fingerprint reader"),
|
||||||
N_("Place your right index finger on %s"),
|
N_("Place your right index finger on %s"),
|
||||||
N_("Swipe your right index finger across the fingerprint reader"),
|
N_("Swipe your right index finger across the fingerprint reader"),
|
||||||
N_("Swipe your right index finger across %s") },
|
N_("Swipe your right index finger across %s") },
|
||||||
{ "right-middle-finger",
|
{ "right-middle-finger",
|
||||||
N_("Place your right middle finger on the fingerprint reader"),
|
N_("Place your right middle finger on the fingerprint reader"),
|
||||||
N_("Place your right middle finger on %s"),
|
N_("Place your right middle finger on %s"),
|
||||||
N_("Swipe your right middle finger across the fingerprint reader"),
|
N_("Swipe your right middle finger across the fingerprint reader"),
|
||||||
N_("Swipe your right middle finger across %s") },
|
N_("Swipe your right middle finger across %s") },
|
||||||
{ "right-ring-finger",
|
{ "right-ring-finger",
|
||||||
N_("Place your right ring finger on the fingerprint reader"),
|
N_("Place your right ring finger on the fingerprint reader"),
|
||||||
N_("Place your right ring finger on %s"),
|
N_("Place your right ring finger on %s"),
|
||||||
N_("Swipe your right ring finger across the fingerprint reader"),
|
N_("Swipe your right ring finger across the fingerprint reader"),
|
||||||
N_("Swipe your right ring finger across %s") },
|
N_("Swipe your right ring finger across %s") },
|
||||||
{ "right-little-finger",
|
{ "right-little-finger",
|
||||||
N_("Place your right little finger on the fingerprint reader"),
|
N_("Place your right little finger on the fingerprint reader"),
|
||||||
N_("Place your right little finger on %s"),
|
N_("Place your right little finger on %s"),
|
||||||
N_("Swipe your right little finger across the fingerprint reader"),
|
N_("Swipe your right little finger across the fingerprint reader"),
|
||||||
N_("Swipe your right little finger across %s") },
|
N_("Swipe your right little finger across %s") },
|
||||||
{ NULL, NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||||
|
|
||||||
GNUC_UNUSED static char *finger_str_to_msg(const char *finger_name, const char *driver_name, bool is_swipe)
|
GNUC_UNUSED static char *
|
||||||
|
finger_str_to_msg (const char *finger_name, const char *driver_name, bool is_swipe)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (finger_name == NULL)
|
if (finger_name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; fingers[i].dbus_name != NULL; i++) {
|
for (i = 0; fingers[i].dbus_name != NULL; i++)
|
||||||
if (str_equal (fingers[i].dbus_name, finger_name)) {
|
{
|
||||||
if (is_swipe == false) {
|
if (!str_equal (fingers[i].dbus_name, finger_name))
|
||||||
if (driver_name) {
|
continue;
|
||||||
char *s;
|
if (is_swipe == false)
|
||||||
int ret;
|
{
|
||||||
ret = asprintf (&s, TR (fingers[i].place_str_specific), driver_name);
|
if (driver_name)
|
||||||
return ret >= 0 ? s : NULL;
|
{
|
||||||
} else {
|
char *s;
|
||||||
return strdup (TR (fingers[i].place_str_generic));
|
int ret;
|
||||||
}
|
ret = asprintf (&s, TR (fingers[i].place_str_specific), driver_name);
|
||||||
} else {
|
return ret >= 0 ? s : NULL;
|
||||||
if (driver_name) {
|
}
|
||||||
char *s;
|
else
|
||||||
int ret;
|
{
|
||||||
ret = asprintf (&s, TR (fingers[i].swipe_str_specific), driver_name);
|
return strdup (TR (fingers[i].place_str_generic));
|
||||||
return ret >= 0 ? s : NULL;
|
}
|
||||||
} else {
|
}
|
||||||
return strdup (TR (fingers[i].swipe_str_generic));
|
else
|
||||||
}
|
{
|
||||||
}
|
if (driver_name)
|
||||||
}
|
{
|
||||||
}
|
char *s;
|
||||||
|
int ret;
|
||||||
|
ret = asprintf (&s, TR (fingers[i].swipe_str_specific), driver_name);
|
||||||
|
return ret >= 0 ? s : NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return strdup (TR (fingers[i].swipe_str_generic));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
@ -146,25 +159,27 @@ GNUC_UNUSED static char *finger_str_to_msg(const char *finger_name, const char *
|
|||||||
* verify-match
|
* verify-match
|
||||||
* verify-unknown-error
|
* verify-unknown-error
|
||||||
*/
|
*/
|
||||||
GNUC_UNUSED static const char *verify_result_str_to_msg(const char *result, bool is_swipe)
|
GNUC_UNUSED static const char *
|
||||||
|
verify_result_str_to_msg (const char *result, bool is_swipe)
|
||||||
{
|
{
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strcmp (result, "verify-retry-scan") == 0) {
|
if (strcmp (result, "verify-retry-scan") == 0)
|
||||||
if (is_swipe == false)
|
{
|
||||||
return TR (N_("Place your finger on the reader again"));
|
if (is_swipe == false)
|
||||||
else
|
return TR (N_("Place your finger on the reader again"));
|
||||||
return TR (N_("Swipe your finger again"));
|
else
|
||||||
}
|
return TR (N_("Swipe your finger again"));
|
||||||
if (strcmp (result, "verify-swipe-too-short") == 0)
|
}
|
||||||
return TR (N_("Swipe was too short, try again"));
|
if (strcmp (result, "verify-swipe-too-short") == 0)
|
||||||
if (strcmp (result, "verify-finger-not-centered") == 0)
|
return TR (N_("Swipe was too short, try again"));
|
||||||
return TR (N_("Your finger was not centered, try swiping your finger again"));
|
if (strcmp (result, "verify-finger-not-centered") == 0)
|
||||||
if (strcmp (result, "verify-remove-and-retry") == 0)
|
return TR (N_("Your finger was not centered, try swiping your finger again"));
|
||||||
return TR (N_("Remove your finger, and try swiping your finger again"));
|
if (strcmp (result, "verify-remove-and-retry") == 0)
|
||||||
|
return TR (N_("Remove your finger, and try swiping your finger again"));
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cases not handled:
|
/* Cases not handled:
|
||||||
@ -172,24 +187,25 @@ GNUC_UNUSED static const char *verify_result_str_to_msg(const char *result, bool
|
|||||||
* enroll-failed
|
* enroll-failed
|
||||||
* enroll-unknown-error
|
* enroll-unknown-error
|
||||||
*/
|
*/
|
||||||
GNUC_UNUSED static const char *enroll_result_str_to_msg(const char *result, bool is_swipe)
|
GNUC_UNUSED static const char *
|
||||||
|
enroll_result_str_to_msg (const char *result, bool is_swipe)
|
||||||
{
|
{
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strcmp (result, "enroll-retry-scan") == 0 || strcmp (result, "enroll-stage-passed") == 0) {
|
if (strcmp (result, "enroll-retry-scan") == 0 || strcmp (result, "enroll-stage-passed") == 0)
|
||||||
if (is_swipe == false)
|
{
|
||||||
return TR (N_("Place your finger on the reader again"));
|
if (is_swipe == false)
|
||||||
else
|
return TR (N_("Place your finger on the reader again"));
|
||||||
return TR (N_("Swipe your finger again"));
|
else
|
||||||
}
|
return TR (N_("Swipe your finger again"));
|
||||||
if (strcmp (result, "enroll-swipe-too-short") == 0)
|
}
|
||||||
return TR (N_("Swipe was too short, try again"));
|
if (strcmp (result, "enroll-swipe-too-short") == 0)
|
||||||
if (strcmp (result, "enroll-finger-not-centered") == 0)
|
return TR (N_("Swipe was too short, try again"));
|
||||||
return TR (N_("Your finger was not centered, try swiping your finger again"));
|
if (strcmp (result, "enroll-finger-not-centered") == 0)
|
||||||
if (strcmp (result, "enroll-remove-and-retry") == 0)
|
return TR (N_("Your finger was not centered, try swiping your finger again"));
|
||||||
return TR (N_("Remove your finger, and try swiping your finger again"));
|
if (strcmp (result, "enroll-remove-and-retry") == 0)
|
||||||
|
return TR (N_("Remove your finger, and try swiping your finger again"));
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1107
pam/pam_fprintd.c
1107
pam/pam_fprintd.c
File diff suppressed because it is too large
Load Diff
61
pam/pam_fprintd_autoptrs.h
Normal file
61
pam/pam_fprintd_autoptrs.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* pam_fprint: PAM module for fingerprint authentication through fprintd
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Define auto-pointers functions, based on GLib Macros */
|
||||||
|
|
||||||
|
#define _CLEANUP_FUNC(func) __attribute__((cleanup (func)))
|
||||||
|
|
||||||
|
#define _PF_AUTOPTR_FUNC_NAME(TypeName) pf_autoptr_cleanup_ ## TypeName
|
||||||
|
#define _PF_AUTOPTR_TYPENAME(TypeName) TypeName ## _pf_autoptr
|
||||||
|
|
||||||
|
#define PF_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, cleanup) \
|
||||||
|
typedef TypeName *_PF_AUTOPTR_TYPENAME (TypeName); \
|
||||||
|
static __attribute__((__unused__)) inline void \
|
||||||
|
_PF_AUTOPTR_FUNC_NAME (TypeName) (TypeName **_ptr) \
|
||||||
|
{ if (_ptr) (cleanup) (*_ptr); }
|
||||||
|
|
||||||
|
#define PF_DEFINE_AUTO_CLEAN_FUNC(TypeName, cleanup) \
|
||||||
|
static __attribute__((__unused__)) inline void \
|
||||||
|
_PF_AUTOPTR_FUNC_NAME (TypeName) (TypeName *_ptr) \
|
||||||
|
{ cleanup (_ptr); }
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
autoptr_cleanup_generic_free (void *p)
|
||||||
|
{
|
||||||
|
void **pp = (void **) p;
|
||||||
|
|
||||||
|
free (*pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define pf_autofree _CLEANUP_FUNC (autoptr_cleanup_generic_free)
|
||||||
|
#define pf_autoptr(TypeName) \
|
||||||
|
_CLEANUP_FUNC (_PF_AUTOPTR_FUNC_NAME (TypeName)) \
|
||||||
|
_PF_AUTOPTR_TYPENAME (TypeName)
|
||||||
|
#define pf_auto(TypeName) \
|
||||||
|
_CLEANUP_FUNC (_PF_AUTOPTR_FUNC_NAME (TypeName)) TypeName
|
||||||
|
|
||||||
|
PF_DEFINE_AUTOPTR_CLEANUP_FUNC (sd_bus, sd_bus_unref)
|
||||||
|
PF_DEFINE_AUTOPTR_CLEANUP_FUNC (sd_bus_message, sd_bus_message_unref)
|
||||||
|
PF_DEFINE_AUTOPTR_CLEANUP_FUNC (sd_bus_slot, sd_bus_slot_unref)
|
||||||
|
|
||||||
|
PF_DEFINE_AUTO_CLEAN_FUNC (sd_bus_error, sd_bus_error_free)
|
||||||
137
scripts/uncrustify.cfg
Normal file
137
scripts/uncrustify.cfg
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
newlines lf
|
||||||
|
|
||||||
|
input_tab_size 8
|
||||||
|
output_tab_size 8
|
||||||
|
|
||||||
|
string_escape_char 92
|
||||||
|
string_escape_char2 0
|
||||||
|
|
||||||
|
# indenting
|
||||||
|
indent_columns 2
|
||||||
|
indent_with_tabs 0
|
||||||
|
indent_align_string True
|
||||||
|
indent_brace 2
|
||||||
|
indent_braces false
|
||||||
|
indent_braces_no_func True
|
||||||
|
indent_func_call_param false
|
||||||
|
indent_func_def_param false
|
||||||
|
indent_func_proto_param false
|
||||||
|
indent_switch_case 0
|
||||||
|
indent_case_brace 2
|
||||||
|
indent_paren_close 1
|
||||||
|
|
||||||
|
# spacing
|
||||||
|
sp_arith Add
|
||||||
|
sp_assign Add
|
||||||
|
sp_enum_assign Add
|
||||||
|
sp_bool Add
|
||||||
|
sp_compare Add
|
||||||
|
sp_inside_paren Remove
|
||||||
|
sp_inside_fparens Remove
|
||||||
|
sp_func_def_paren Force
|
||||||
|
sp_func_proto_paren Force
|
||||||
|
sp_paren_paren Remove
|
||||||
|
sp_balance_nested_parens False
|
||||||
|
sp_paren_brace Remove
|
||||||
|
sp_before_square Remove
|
||||||
|
sp_before_squares Remove
|
||||||
|
sp_inside_square Remove
|
||||||
|
sp_before_ptr_star Add
|
||||||
|
sp_between_ptr_star Remove
|
||||||
|
sp_after_comma Add
|
||||||
|
sp_before_comma Remove
|
||||||
|
sp_after_cast Add
|
||||||
|
sp_sizeof_paren Add
|
||||||
|
sp_not Remove
|
||||||
|
sp_inv Remove
|
||||||
|
sp_addr Remove
|
||||||
|
sp_member Remove
|
||||||
|
sp_deref Remove
|
||||||
|
sp_sign Remove
|
||||||
|
sp_incdec Remove
|
||||||
|
sp_attribute_paren remove
|
||||||
|
sp_macro Force
|
||||||
|
sp_func_call_paren Force
|
||||||
|
sp_func_call_user_paren Remove
|
||||||
|
set func_call_user _ N_ C_ g_autoptr g_auto
|
||||||
|
sp_brace_typedef add
|
||||||
|
sp_cond_colon add
|
||||||
|
sp_cond_question add
|
||||||
|
sp_defined_paren remove
|
||||||
|
|
||||||
|
# alignment
|
||||||
|
align_keep_tabs False
|
||||||
|
align_with_tabs False
|
||||||
|
align_on_tabstop False
|
||||||
|
align_number_right False
|
||||||
|
align_func_params True
|
||||||
|
align_var_def_span 0
|
||||||
|
align_var_def_amp_style 1
|
||||||
|
align_var_def_colon true
|
||||||
|
align_enum_equ_span 0
|
||||||
|
align_var_struct_span 2
|
||||||
|
align_var_def_star_style 2
|
||||||
|
align_var_def_amp_style 2
|
||||||
|
align_typedef_span 2
|
||||||
|
align_typedef_func 0
|
||||||
|
align_typedef_star_style 2
|
||||||
|
align_typedef_amp_style 2
|
||||||
|
|
||||||
|
# newlines
|
||||||
|
nl_assign_leave_one_liners True
|
||||||
|
nl_enum_leave_one_liners False
|
||||||
|
nl_func_leave_one_liners False
|
||||||
|
nl_if_leave_one_liners False
|
||||||
|
nl_end_of_file Add
|
||||||
|
nl_assign_brace Remove
|
||||||
|
nl_func_var_def_blk 1
|
||||||
|
nl_fcall_brace Add
|
||||||
|
nl_enum_brace Remove
|
||||||
|
nl_struct_brace Force
|
||||||
|
nl_union_brace Force
|
||||||
|
nl_if_brace Force
|
||||||
|
nl_brace_else Force
|
||||||
|
nl_elseif_brace Force
|
||||||
|
nl_else_brace Add
|
||||||
|
nl_for_brace Force
|
||||||
|
nl_while_brace Force
|
||||||
|
nl_do_brace Force
|
||||||
|
nl_brace_while Force
|
||||||
|
nl_switch_brace Force
|
||||||
|
nl_before_case True
|
||||||
|
nl_after_case False
|
||||||
|
nl_func_type_name Force
|
||||||
|
nl_func_proto_type_name Remove
|
||||||
|
nl_func_paren Remove
|
||||||
|
nl_func_decl_start Remove
|
||||||
|
nl_func_decl_args Force
|
||||||
|
nl_func_decl_end Remove
|
||||||
|
nl_fdef_brace Force
|
||||||
|
nl_after_return False
|
||||||
|
nl_define_macro False
|
||||||
|
nl_create_if_one_liner False
|
||||||
|
nl_create_for_one_liner False
|
||||||
|
nl_create_while_one_liner False
|
||||||
|
nl_after_semicolon True
|
||||||
|
nl_multi_line_cond true
|
||||||
|
|
||||||
|
# mod
|
||||||
|
# I'd like these to be remove, but that removes brackets in if { if { foo } }, which i dislike
|
||||||
|
# Not clear what to do about that...
|
||||||
|
mod_full_brace_for Remove
|
||||||
|
mod_full_brace_if Remove
|
||||||
|
mod_full_brace_if_chain True
|
||||||
|
mod_full_brace_while Remove
|
||||||
|
mod_full_brace_do Remove
|
||||||
|
mod_full_brace_nl 3
|
||||||
|
mod_paren_on_return Remove
|
||||||
|
|
||||||
|
# line splitting
|
||||||
|
#code_width = 78
|
||||||
|
ls_for_split_full True
|
||||||
|
ls_func_split_full True
|
||||||
|
|
||||||
|
# positioning
|
||||||
|
pos_bool Trail
|
||||||
|
pos_conditional Trail
|
||||||
|
|
||||||
19
scripts/uncrustify.sh
Executable file
19
scripts/uncrustify.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
SRCROOT=`git rev-parse --show-toplevel`
|
||||||
|
CFG="$SRCROOT/scripts/uncrustify.cfg"
|
||||||
|
echo "srcroot: $SRCROOT"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
-c|--check)
|
||||||
|
OPTS="--check"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
OPTS="--replace --no-backup"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
pushd "$SRCROOT"
|
||||||
|
uncrustify -c "$CFG" $OPTS `git ls-tree --name-only -r HEAD | grep -E '.*\.[ch]$' | grep -v build/`
|
||||||
|
RES=$?
|
||||||
|
popd
|
||||||
|
exit $RES
|
||||||
110
src/dbus-interactive-auth.patch
Normal file
110
src/dbus-interactive-auth.patch
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
--- a/src/fprintd-dbus.c 2020-12-04 16:38:28.527712626 +0100
|
||||||
|
+++ b/src/fprintd-dbus.c 2020-12-04 16:40:03.561692619 +0100
|
||||||
|
@@ -1149,7 +1149,7 @@
|
||||||
|
"ListEnrolledFingers",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_username),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
@@ -1213,7 +1213,7 @@
|
||||||
|
"ListEnrolledFingers",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_username),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
@@ -1253,7 +1253,7 @@
|
||||||
|
"DeleteEnrolledFingers",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_username),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
@@ -1312,7 +1312,7 @@
|
||||||
|
"DeleteEnrolledFingers",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_username),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
@@ -1348,7 +1348,7 @@
|
||||||
|
g_dbus_proxy_call (G_DBUS_PROXY (proxy),
|
||||||
|
"DeleteEnrolledFingers2",
|
||||||
|
g_variant_new ("()"),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
@@ -1404,7 +1404,7 @@
|
||||||
|
_ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
|
||||||
|
"DeleteEnrolledFingers2",
|
||||||
|
g_variant_new ("()"),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
@@ -1443,7 +1443,7 @@
|
||||||
|
"Claim",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_username),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
@@ -1502,7 +1502,7 @@
|
||||||
|
"Claim",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_username),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
@@ -1633,7 +1633,7 @@
|
||||||
|
"VerifyStart",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_finger_name),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
@@ -1692,7 +1692,7 @@
|
||||||
|
"VerifyStart",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_finger_name),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
@@ -1823,7 +1823,7 @@
|
||||||
|
"EnrollStart",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_finger_name),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
@@ -1882,7 +1882,7 @@
|
||||||
|
"EnrollStart",
|
||||||
|
g_variant_new ("(s)",
|
||||||
|
arg_finger_name),
|
||||||
|
- G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
2963
src/device.c
2963
src/device.c
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -44,271 +44,297 @@
|
|||||||
|
|
||||||
static char *storage_path = NULL;
|
static char *storage_path = NULL;
|
||||||
|
|
||||||
static const char *get_storage_path(void)
|
static const char *
|
||||||
|
get_storage_path (void)
|
||||||
{
|
{
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
|
|
||||||
if (storage_path != NULL)
|
if (storage_path != NULL)
|
||||||
return storage_path;
|
return storage_path;
|
||||||
|
|
||||||
/* set by systemd >= 240 to an absolute path
|
/* set by systemd >= 240 to an absolute path
|
||||||
* taking into account the StateDirectory
|
* taking into account the StateDirectory
|
||||||
* unit file setting */
|
* unit file setting */
|
||||||
path = g_getenv ("STATE_DIRECTORY");
|
path = g_getenv ("STATE_DIRECTORY");
|
||||||
if (path != NULL) {
|
if (path != NULL)
|
||||||
/* If multiple directories are set, then in the environment variable
|
{
|
||||||
* the paths are concatenated with colon (":"). */
|
/* If multiple directories are set, then in the environment variable
|
||||||
if (strchr (path, ':')) {
|
* the paths are concatenated with colon (":"). */
|
||||||
g_auto(GStrv) elems = NULL;
|
if (strchr (path, ':'))
|
||||||
elems = g_strsplit (path, ":", -1);
|
{
|
||||||
storage_path = g_strdup (elems[0]);
|
g_auto(GStrv) elems = NULL;
|
||||||
}
|
elems = g_strsplit (path, ":", -1);
|
||||||
}
|
storage_path = g_strdup (elems[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (storage_path == NULL)
|
if (storage_path == NULL)
|
||||||
storage_path = g_strdup (FILE_STORAGE_PATH);
|
storage_path = g_strdup (FILE_STORAGE_PATH);
|
||||||
|
|
||||||
return storage_path;
|
return storage_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_path_to_storedir(const char *driver, const char * device_id, char *base_store)
|
static char *
|
||||||
|
get_path_to_storedir (const char *driver, const char * device_id, char *base_store)
|
||||||
{
|
{
|
||||||
return g_build_filename(base_store, driver, device_id, NULL);
|
return g_build_filename (base_store, driver, device_id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *__get_path_to_print(const char *driver, const char * device_id,
|
static char *
|
||||||
FpFinger finger, char *base_store)
|
__get_path_to_print (const char *driver, const char * device_id,
|
||||||
|
FpFinger finger, char *base_store)
|
||||||
{
|
{
|
||||||
g_autofree char *dirpath = NULL;
|
g_autofree char *dirpath = NULL;
|
||||||
char *path;
|
char *path;
|
||||||
char fingername[2];
|
char fingername[2];
|
||||||
|
|
||||||
g_snprintf(fingername, 2, "%x", finger);
|
g_snprintf (fingername, 2, "%x", finger);
|
||||||
|
|
||||||
dirpath = get_path_to_storedir(driver, device_id, base_store);
|
dirpath = get_path_to_storedir (driver, device_id, base_store);
|
||||||
path = g_build_filename(dirpath, fingername, NULL);
|
path = g_build_filename (dirpath, fingername, NULL);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_path_to_print(FpDevice *dev, FpFinger finger, char *base_store)
|
static char *
|
||||||
|
get_path_to_print (FpDevice *dev, FpFinger finger, char *base_store)
|
||||||
{
|
{
|
||||||
return __get_path_to_print(fp_device_get_driver (dev),
|
return __get_path_to_print (fp_device_get_driver (dev),
|
||||||
fp_device_get_device_id(dev),
|
fp_device_get_device_id (dev),
|
||||||
finger,
|
finger,
|
||||||
base_store);
|
base_store);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_path_to_print_dscv(FpDevice *dev, FpFinger finger, char *base_store)
|
static char *
|
||||||
|
get_path_to_print_dscv (FpDevice *dev, FpFinger finger, char *base_store)
|
||||||
{
|
{
|
||||||
return __get_path_to_print(fp_device_get_driver (dev),
|
return __get_path_to_print (fp_device_get_driver (dev),
|
||||||
fp_device_get_device_id(dev),
|
fp_device_get_device_id (dev),
|
||||||
finger,
|
finger,
|
||||||
base_store);
|
base_store);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *file_storage_get_basestore_for_username(const char *username)
|
static char *
|
||||||
|
file_storage_get_basestore_for_username (const char *username)
|
||||||
{
|
{
|
||||||
return g_build_filename(get_storage_path(), username, NULL);
|
return g_build_filename (get_storage_path (), username, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_storage_print_data_save(FpPrint *print)
|
int
|
||||||
|
file_storage_print_data_save (FpPrint *print)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
g_autofree char *path = NULL;
|
g_autofree char *path = NULL;
|
||||||
g_autofree char *dirpath = NULL;
|
g_autofree char *dirpath = NULL;
|
||||||
g_autofree char *base_store = NULL;
|
g_autofree char *base_store = NULL;
|
||||||
g_autofree char *buf = NULL;
|
g_autofree char *buf = NULL;
|
||||||
gsize len;
|
gsize len;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
base_store = file_storage_get_basestore_for_username(fp_print_get_username (print));
|
base_store = file_storage_get_basestore_for_username (fp_print_get_username (print));
|
||||||
|
|
||||||
if (!fp_print_serialize (print, (guchar **) &buf, &len, &err)) {
|
if (!fp_print_serialize (print, (guchar **) &buf, &len, &err))
|
||||||
g_warning ("Error serializing data: %s", err->message);
|
{
|
||||||
return -ENOMEM;
|
g_warning ("Error serializing data: %s", err->message);
|
||||||
}
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
path = __get_path_to_print(fp_print_get_driver (print),
|
path = __get_path_to_print (fp_print_get_driver (print),
|
||||||
fp_print_get_device_id (print),
|
fp_print_get_device_id (print),
|
||||||
fp_print_get_finger (print),
|
fp_print_get_finger (print),
|
||||||
base_store);
|
base_store);
|
||||||
dirpath = g_path_get_dirname(path);
|
dirpath = g_path_get_dirname (path);
|
||||||
r = g_mkdir_with_parents(dirpath, DIR_PERMS);
|
r = g_mkdir_with_parents (dirpath, DIR_PERMS);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
g_debug("file_storage_print_data_save(): could not mkdir(\"%s\"): %s",
|
{
|
||||||
dirpath, g_strerror(r));
|
g_debug ("file_storage_print_data_save(): could not mkdir(\"%s\"): %s",
|
||||||
return r;
|
dirpath, g_strerror (r));
|
||||||
}
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
//fp_dbg("saving to %s", path);
|
//fp_dbg("saving to %s", path);
|
||||||
g_file_set_contents(path, buf, len, &err);
|
g_file_set_contents (path, buf, len, &err);
|
||||||
if (err) {
|
if (err)
|
||||||
g_debug("file_storage_print_data_save(): could not save '%s': %s",
|
{
|
||||||
path, err->message);
|
g_debug ("file_storage_print_data_save(): could not save '%s': %s",
|
||||||
/* FIXME interpret error codes */
|
path, err->message);
|
||||||
return err->code;
|
/* FIXME interpret error codes */
|
||||||
}
|
return err->code;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_from_file(char *path, FpPrint **print)
|
static int
|
||||||
|
load_from_file (char *path, FpPrint **print)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
gsize length;
|
gsize length;
|
||||||
g_autofree char *contents = NULL;
|
g_autofree char *contents = NULL;
|
||||||
FpPrint *new;
|
FpPrint *new;
|
||||||
|
|
||||||
//fp_dbg("from %s", path);
|
//fp_dbg("from %s", path);
|
||||||
g_file_get_contents(path, &contents, &length, &err);
|
g_file_get_contents (path, &contents, &length, &err);
|
||||||
if (err) {
|
if (err)
|
||||||
int r = err->code;
|
{
|
||||||
/* FIXME interpret more error codes */
|
int r = err->code;
|
||||||
if (r == G_FILE_ERROR_NOENT)
|
/* FIXME interpret more error codes */
|
||||||
return -ENOENT;
|
if (r == G_FILE_ERROR_NOENT)
|
||||||
else
|
return -ENOENT;
|
||||||
return r;
|
else
|
||||||
}
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
new = fp_print_deserialize ((guchar *) contents, length, &err);
|
new = fp_print_deserialize ((guchar *) contents, length, &err);
|
||||||
if (!new) {
|
if (!new)
|
||||||
g_print ("Error deserializing data: %s", err->message);
|
{
|
||||||
return -EIO;
|
g_print ("Error deserializing data: %s", err->message);
|
||||||
}
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
*print = new;
|
*print = new;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_storage_print_data_load(FpDevice *dev,
|
int
|
||||||
FpFinger finger,
|
file_storage_print_data_load (FpDevice *dev,
|
||||||
const char *username,
|
FpFinger finger,
|
||||||
FpPrint **print)
|
const char *username,
|
||||||
|
FpPrint **print)
|
||||||
{
|
{
|
||||||
g_autofree gchar *path = NULL;
|
g_autofree gchar *path = NULL;
|
||||||
g_autofree gchar *base_store = NULL;
|
g_autofree gchar *base_store = NULL;
|
||||||
g_autoptr(FpPrint) new = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
base_store = file_storage_get_basestore_for_username(username);
|
g_autoptr(FpPrint) new = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
path = get_path_to_print(dev, finger, base_store);
|
base_store = file_storage_get_basestore_for_username (username);
|
||||||
r = load_from_file(path, &new);
|
|
||||||
g_debug ("file_storage_print_data_load(): loaded '%s' %s",
|
|
||||||
path, g_strerror(r));
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!fp_print_compatible (new, dev)) {
|
path = get_path_to_print (dev, finger, base_store);
|
||||||
return -EINVAL;
|
r = load_from_file (path, &new);
|
||||||
}
|
g_debug ("file_storage_print_data_load(): loaded '%s' %s",
|
||||||
|
path, g_strerror (r));
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
*print = g_steal_pointer (&new);
|
if (!fp_print_compatible (new, dev))
|
||||||
return 0;
|
return -EINVAL;
|
||||||
|
|
||||||
|
*print = g_steal_pointer (&new);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_storage_print_data_delete(FpDevice *dev, FpFinger finger, const char *username)
|
int
|
||||||
|
file_storage_print_data_delete (FpDevice *dev, FpFinger finger, const char *username)
|
||||||
{
|
{
|
||||||
g_autofree gchar *base_store = NULL;
|
g_autofree gchar *base_store = NULL;
|
||||||
g_autofree gchar *path = NULL;
|
g_autofree gchar *path = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
base_store = file_storage_get_basestore_for_username(username);
|
base_store = file_storage_get_basestore_for_username (username);
|
||||||
|
|
||||||
path = get_path_to_print_dscv(dev, finger, base_store);
|
path = get_path_to_print_dscv (dev, finger, base_store);
|
||||||
|
|
||||||
r = g_unlink(path);
|
r = g_unlink (path);
|
||||||
g_debug("file_storage_print_data_delete(): unlink(\"%s\") %s",
|
g_debug ("file_storage_print_data_delete(): unlink(\"%s\") %s",
|
||||||
path, g_strerror(r));
|
path, g_strerror (r));
|
||||||
|
|
||||||
/* FIXME: cleanup empty directory */
|
/* FIXME: cleanup empty directory */
|
||||||
return g_unlink(path);
|
return g_unlink (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList *scan_dev_storedir(char *devpath,
|
static GSList *
|
||||||
GSList *list)
|
scan_dev_storedir (char *devpath,
|
||||||
|
GSList *list)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
const gchar *ent;
|
const gchar *ent;
|
||||||
|
|
||||||
GDir *dir = g_dir_open(devpath, 0, &err);
|
GDir *dir = g_dir_open (devpath, 0, &err);
|
||||||
if (!dir) {
|
|
||||||
g_debug("scan_dev_storedir(): opendir(\"%s\") failed: %s", devpath, err->message);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((ent = g_dir_read_name(dir))) {
|
if (!dir)
|
||||||
/* ent is an 1 hex character fp_finger code */
|
{
|
||||||
guint64 val;
|
g_debug ("scan_dev_storedir(): opendir(\"%s\") failed: %s", devpath, err->message);
|
||||||
gchar *endptr;
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
if (*ent == 0 || strlen(ent) != 1)
|
while ((ent = g_dir_read_name (dir)))
|
||||||
continue;
|
{
|
||||||
|
/* ent is an 1 hex character fp_finger code */
|
||||||
|
guint64 val;
|
||||||
|
gchar *endptr;
|
||||||
|
|
||||||
val = g_ascii_strtoull(ent, &endptr, 16);
|
if (*ent == 0 || strlen (ent) != 1)
|
||||||
if (endptr == ent || !FP_FINGER_IS_VALID(val)) {
|
continue;
|
||||||
g_debug("scan_dev_storedir(): skipping print file '%s'", ent);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = g_slist_prepend(list, GINT_TO_POINTER(val));
|
val = g_ascii_strtoull (ent, &endptr, 16);
|
||||||
}
|
if (endptr == ent || !FP_FINGER_IS_VALID (val))
|
||||||
|
{
|
||||||
|
g_debug ("scan_dev_storedir(): skipping print file '%s'", ent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
g_dir_close(dir);
|
list = g_slist_prepend (list, GUINT_TO_POINTER (val));
|
||||||
return list;
|
}
|
||||||
|
|
||||||
|
g_dir_close (dir);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList *file_storage_discover_prints(FpDevice *dev, const char *username)
|
GSList *
|
||||||
|
file_storage_discover_prints (FpDevice *dev, const char *username)
|
||||||
{
|
{
|
||||||
GSList *list = NULL;
|
GSList *list = NULL;
|
||||||
g_autofree gchar *base_store = NULL;
|
g_autofree gchar *base_store = NULL;
|
||||||
g_autofree gchar *storedir = NULL;
|
g_autofree gchar *storedir = NULL;
|
||||||
|
|
||||||
base_store = file_storage_get_basestore_for_username(username);
|
base_store = file_storage_get_basestore_for_username (username);
|
||||||
|
|
||||||
storedir = get_path_to_storedir(fp_device_get_driver (dev),
|
storedir = get_path_to_storedir (fp_device_get_driver (dev),
|
||||||
fp_device_get_device_id (dev),
|
fp_device_get_device_id (dev),
|
||||||
base_store);
|
base_store);
|
||||||
|
|
||||||
g_debug ("file_storage_discover_prints() for user '%s' in '%s'",
|
g_debug ("file_storage_discover_prints() for user '%s' in '%s'",
|
||||||
username, storedir);
|
username, storedir);
|
||||||
|
|
||||||
list = scan_dev_storedir(storedir, list);
|
list = scan_dev_storedir (storedir, list);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList *file_storage_discover_users(void)
|
GSList *
|
||||||
|
file_storage_discover_users (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
GSList *list = NULL;
|
GSList *list = NULL;
|
||||||
const gchar *ent;
|
const gchar *ent;
|
||||||
GDir *dir = g_dir_open(get_storage_path(), 0, &err);
|
GDir *dir = g_dir_open (get_storage_path (), 0, &err);
|
||||||
|
|
||||||
if (!dir) {
|
if (!dir)
|
||||||
return list;
|
return list;
|
||||||
}
|
|
||||||
|
|
||||||
while ((ent = g_dir_read_name(dir))) {
|
while ((ent = g_dir_read_name (dir)))
|
||||||
/* ent is a username */
|
{
|
||||||
if (*ent == 0)
|
/* ent is a username */
|
||||||
continue;
|
if (*ent == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
list = g_slist_prepend(list, g_strdup (ent));
|
list = g_slist_prepend (list, g_strdup (ent));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dir_close(dir);
|
g_dir_close (dir);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_storage_init(void)
|
int
|
||||||
|
file_storage_init (void)
|
||||||
{
|
{
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_storage_deinit(void)
|
int
|
||||||
|
file_storage_deinit (void)
|
||||||
{
|
{
|
||||||
g_clear_pointer (&storage_path, g_free);
|
g_clear_pointer (&storage_path, g_free);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -20,20 +20,21 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
int file_storage_print_data_save(FpPrint *print);
|
int file_storage_print_data_save (FpPrint *print);
|
||||||
|
|
||||||
int file_storage_print_data_load(FpDevice *dev,
|
int file_storage_print_data_load (FpDevice *dev,
|
||||||
FpFinger finger,
|
FpFinger finger,
|
||||||
const char *username,
|
const char *username,
|
||||||
FpPrint **print);
|
FpPrint **print);
|
||||||
|
|
||||||
int file_storage_print_data_delete(FpDevice *dev,
|
int file_storage_print_data_delete (FpDevice *dev,
|
||||||
FpFinger finger,
|
FpFinger finger,
|
||||||
const char *username);
|
const char *username);
|
||||||
|
|
||||||
int file_storage_init(void);
|
int file_storage_init (void);
|
||||||
|
|
||||||
int file_storage_deinit(void);
|
int file_storage_deinit (void);
|
||||||
|
|
||||||
GSList *file_storage_discover_prints(FpDevice *dev, const char *username);
|
GSList *file_storage_discover_prints (FpDevice *dev,
|
||||||
GSList *file_storage_discover_users(void);
|
const char *username);
|
||||||
|
GSList *file_storage_discover_users (void);
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -31,55 +31,63 @@
|
|||||||
#define FPRINT_SERVICE_PATH "/net/reactivated/Fprint"
|
#define FPRINT_SERVICE_PATH "/net/reactivated/Fprint"
|
||||||
|
|
||||||
/* Errors */
|
/* Errors */
|
||||||
GQuark fprint_error_quark(void);
|
GQuark fprint_error_quark (void);
|
||||||
|
|
||||||
#define FPRINT_ERROR fprint_error_quark()
|
#define FPRINT_ERROR fprint_error_quark ()
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* developer didn't claim the device */
|
/* developer didn't claim the device */
|
||||||
FPRINT_ERROR_CLAIM_DEVICE, /*< nick=net.reactivated.Fprint.Error.ClaimDevice >*/
|
FPRINT_ERROR_CLAIM_DEVICE, /*< nick=net.reactivated.Fprint.Error.ClaimDevice >*/
|
||||||
/* device is already claimed by somebody else */
|
/* device is already claimed by somebody else */
|
||||||
FPRINT_ERROR_ALREADY_IN_USE, /*< nick=net.reactivated.Fprint.Error.AlreadyInUse >*/
|
FPRINT_ERROR_ALREADY_IN_USE, /*< nick=net.reactivated.Fprint.Error.AlreadyInUse >*/
|
||||||
/* internal error occurred */
|
/* internal error occurred */
|
||||||
FPRINT_ERROR_INTERNAL, /*< nick=net.reactivated.Fprint.Error.Internal >*/
|
FPRINT_ERROR_INTERNAL, /*< nick=net.reactivated.Fprint.Error.Internal >*/
|
||||||
/* PolicyKit refused the action */
|
/* PolicyKit refused the action */
|
||||||
FPRINT_ERROR_PERMISSION_DENIED, /*< nick=net.reactivated.Fprint.Error.PermissionDenied >*/
|
FPRINT_ERROR_PERMISSION_DENIED, /*< nick=net.reactivated.Fprint.Error.PermissionDenied >*/
|
||||||
/* No prints are enrolled */
|
/* No prints are enrolled */
|
||||||
FPRINT_ERROR_NO_ENROLLED_PRINTS, /*< nick=net.reactivated.Fprint.Error.NoEnrolledPrints >*/
|
FPRINT_ERROR_NO_ENROLLED_PRINTS, /*< nick=net.reactivated.Fprint.Error.NoEnrolledPrints >*/
|
||||||
/* No actions currently in progress */
|
/* No actions currently in progress */
|
||||||
FPRINT_ERROR_NO_ACTION_IN_PROGRESS, /*< nick=net.reactivated.Fprint.Error.NoActionInProgress >*/
|
FPRINT_ERROR_NO_ACTION_IN_PROGRESS, /*< nick=net.reactivated.Fprint.Error.NoActionInProgress >*/
|
||||||
/* the finger name passed was invalid */
|
/* the finger name passed was invalid */
|
||||||
FPRINT_ERROR_INVALID_FINGERNAME, /*< nick=net.reactivated.Fprint.Error.InvalidFingername >*/
|
FPRINT_ERROR_INVALID_FINGERNAME, /*< nick=net.reactivated.Fprint.Error.InvalidFingername >*/
|
||||||
/* device does not exist */
|
/* device does not exist */
|
||||||
FPRINT_ERROR_NO_SUCH_DEVICE, /*< nick=net.reactivated.Fprint.Error.NoSuchDevice >*/
|
FPRINT_ERROR_NO_SUCH_DEVICE, /*< nick=net.reactivated.Fprint.Error.NoSuchDevice >*/
|
||||||
} FprintError;
|
} FprintError;
|
||||||
|
|
||||||
|
/* Enum of possible permissions, orders and nick matter here:
|
||||||
|
- The order controls the priority of a required permission when various are
|
||||||
|
accepted: the lowest the value, the more priorty it has.
|
||||||
|
- Nick must match the relative polkit rule.
|
||||||
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FPRINT_DEVICE_PERMISSION_NONE = 0,
|
FPRINT_DEVICE_PERMISSION_NONE = 0,
|
||||||
FPRINT_DEVICE_PERMISSION_ENROLL = (1 << 0), /*< nick=net.reactivated.fprint.device.enroll >*/
|
FPRINT_DEVICE_PERMISSION_VERIFY = (1 << 0), /*< nick=net.reactivated.fprint.device.verify >*/
|
||||||
FPRINT_DEVICE_PERMISSION_SETUSERNAME = (1 << 1), /*< nick=net.reactivated.fprint.device.setusername >*/
|
FPRINT_DEVICE_PERMISSION_ENROLL = (1 << 1), /*< nick=net.reactivated.fprint.device.enroll >*/
|
||||||
FPRINT_DEVICE_PERMISSION_VERIFY = (1 << 2), /*< nick=net.reactivated.fprint.device.verify >*/
|
FPRINT_DEVICE_PERMISSION_SETUSERNAME = (1 << 2), /*< nick=net.reactivated.fprint.device.setusername >*/
|
||||||
} FprintDevicePermission;
|
} FprintDevicePermission;
|
||||||
|
|
||||||
/* Manager */
|
/* Manager */
|
||||||
#define FPRINT_TYPE_MANAGER (fprint_manager_get_type())
|
#define FPRINT_TYPE_MANAGER (fprint_manager_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FprintManager, fprint_manager, FPRINT, MANAGER, GObject)
|
G_DECLARE_FINAL_TYPE (FprintManager, fprint_manager, FPRINT, MANAGER, GObject)
|
||||||
|
|
||||||
struct _FprintManager {
|
struct _FprintManager
|
||||||
GObject parent;
|
{
|
||||||
|
GObject parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
FprintManager *fprint_manager_new (GDBusConnection *connection, gboolean no_timeout);
|
FprintManager *fprint_manager_new (GDBusConnection *connection,
|
||||||
|
gboolean no_timeout);
|
||||||
|
|
||||||
/* Device */
|
/* Device */
|
||||||
#define FPRINT_TYPE_DEVICE (fprint_device_get_type())
|
#define FPRINT_TYPE_DEVICE (fprint_device_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FprintDevice, fprint_device, FPRINT, DEVICE,
|
G_DECLARE_FINAL_TYPE (FprintDevice, fprint_device, FPRINT, DEVICE,
|
||||||
FprintDBusDeviceSkeleton)
|
FprintDBusDeviceSkeleton)
|
||||||
|
|
||||||
struct _FprintDevice {
|
struct _FprintDevice
|
||||||
FprintDBusDeviceSkeleton parent;
|
{
|
||||||
|
FprintDBusDeviceSkeleton parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
FprintDevice *fprint_device_new(FpDevice *dev);
|
FprintDevice *fprint_device_new (FpDevice *dev);
|
||||||
guint32 _fprint_device_get_id(FprintDevice *rdev);
|
guint32 _fprint_device_get_id (FprintDevice *rdev);
|
||||||
/* Print */
|
/* Print */
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
|||||||
238
src/main.c
238
src/main.c
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -44,171 +44,179 @@ static gboolean g_fatal_warnings = FALSE;
|
|||||||
static void
|
static void
|
||||||
set_storage_file (void)
|
set_storage_file (void)
|
||||||
{
|
{
|
||||||
store.init = &file_storage_init;
|
store.init = &file_storage_init;
|
||||||
store.deinit = &file_storage_deinit;
|
store.deinit = &file_storage_deinit;
|
||||||
store.print_data_save = &file_storage_print_data_save;
|
store.print_data_save = &file_storage_print_data_save;
|
||||||
store.print_data_load = &file_storage_print_data_load;
|
store.print_data_load = &file_storage_print_data_load;
|
||||||
store.print_data_delete = &file_storage_print_data_delete;
|
store.print_data_delete = &file_storage_print_data_delete;
|
||||||
store.discover_prints = &file_storage_discover_prints;
|
store.discover_prints = &file_storage_discover_prints;
|
||||||
store.discover_users = &file_storage_discover_users;
|
store.discover_users = &file_storage_discover_users;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
load_storage_module (const char *module_name)
|
load_storage_module (const char *module_name)
|
||||||
{
|
{
|
||||||
GModule *module;
|
GModule *module;
|
||||||
g_autofree char *filename = NULL;
|
g_autofree char *filename = NULL;
|
||||||
|
|
||||||
filename = g_module_build_path (PLUGINDIR, module_name);
|
filename = g_module_build_path (PLUGINDIR, module_name);
|
||||||
module = g_module_open (filename, 0);
|
module = g_module_open (filename, 0);
|
||||||
if (module == NULL)
|
if (module == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!g_module_symbol (module, "init", (gpointer *) &store.init) ||
|
if (!g_module_symbol (module, "init", (gpointer *) &store.init) ||
|
||||||
!g_module_symbol (module, "deinit", (gpointer *) &store.deinit) ||
|
!g_module_symbol (module, "deinit", (gpointer *) &store.deinit) ||
|
||||||
!g_module_symbol (module, "print_data_save", (gpointer *) &store.print_data_save) ||
|
!g_module_symbol (module, "print_data_save", (gpointer *) &store.print_data_save) ||
|
||||||
!g_module_symbol (module, "print_data_load", (gpointer *) &store.print_data_load) ||
|
!g_module_symbol (module, "print_data_load", (gpointer *) &store.print_data_load) ||
|
||||||
!g_module_symbol (module, "print_data_delete", (gpointer *) &store.print_data_delete) ||
|
!g_module_symbol (module, "print_data_delete", (gpointer *) &store.print_data_delete) ||
|
||||||
!g_module_symbol (module, "discover_prints", (gpointer *) &store.discover_prints)) {
|
!g_module_symbol (module, "discover_prints", (gpointer *) &store.discover_prints))
|
||||||
g_module_close (module);
|
{
|
||||||
return FALSE;
|
g_module_close (module);
|
||||||
}
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
g_module_make_resident (module);
|
g_module_make_resident (module);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
load_conf (void)
|
load_conf (void)
|
||||||
{
|
{
|
||||||
g_autofree char *filename = NULL;
|
g_autofree char *filename = NULL;
|
||||||
g_autofree char *module_name = 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);
|
g_autoptr(GKeyFile) file = NULL;
|
||||||
file = g_key_file_new ();
|
g_autoptr(GError) error = NULL;
|
||||||
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);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_name = g_key_file_get_string (file, "storage", "type", &error);
|
filename = g_build_filename (SYSCONFDIR, "fprintd.conf", NULL);
|
||||||
if (module_name == NULL)
|
file = g_key_file_new ();
|
||||||
return FALSE;
|
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);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_str_equal (module_name, "file")) {
|
module_name = g_key_file_get_string (file, "storage", "type", &error);
|
||||||
set_storage_file ();
|
if (module_name == NULL)
|
||||||
return TRUE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
return load_storage_module (module_name);
|
if (g_str_equal (module_name, "file"))
|
||||||
|
{
|
||||||
|
set_storage_file ();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return load_storage_module (module_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GOptionEntry entries[] = {
|
static const GOptionEntry entries[] = {
|
||||||
{"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL},
|
{"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL},
|
||||||
{"no-timeout", 't', 0, G_OPTION_ARG_NONE, &no_timeout, "Do not exit after unused for a while", NULL},
|
{"no-timeout", 't', 0, G_OPTION_ARG_NONE, &no_timeout, "Do not exit after unused for a while", NULL},
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean sigterm_callback(gpointer data)
|
static gboolean
|
||||||
|
sigterm_callback (gpointer data)
|
||||||
{
|
{
|
||||||
GMainLoop *loop = data;
|
GMainLoop *loop = data;
|
||||||
|
|
||||||
g_main_loop_quit (loop);
|
g_main_loop_quit (loop);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_name_acquired (GDBusConnection *connection,
|
on_name_acquired (GDBusConnection *connection,
|
||||||
const char *name,
|
const char *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_debug ("D-Bus service launched with name: %s", name);
|
g_debug ("D-Bus service launched with name: %s", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_name_lost (GDBusConnection *connection,
|
on_name_lost (GDBusConnection *connection,
|
||||||
const char *name,
|
const char *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GMainLoop *loop = user_data;
|
GMainLoop *loop = user_data;
|
||||||
|
|
||||||
g_warning ("Failed to get name: %s", name);
|
g_warning ("Failed to get name: %s", name);
|
||||||
|
|
||||||
g_main_loop_quit (loop);
|
g_main_loop_quit (loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
g_autoptr(GOptionContext) context = NULL;
|
g_autoptr(GOptionContext) context = NULL;
|
||||||
g_autoptr(GMainLoop) loop = NULL;
|
g_autoptr(GMainLoop) loop = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autoptr(FprintManager) manager = NULL;
|
g_autoptr(FprintManager) manager = NULL;
|
||||||
g_autoptr(GDBusConnection) connection = NULL;
|
g_autoptr(GDBusConnection) connection = NULL;
|
||||||
guint32 request_name_ret;
|
guint32 request_name_ret;
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||||
textdomain (GETTEXT_PACKAGE);
|
textdomain (GETTEXT_PACKAGE);
|
||||||
|
|
||||||
context = g_option_context_new ("Fingerprint handler daemon");
|
context = g_option_context_new ("Fingerprint handler daemon");
|
||||||
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
|
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
|
||||||
|
|
||||||
if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
|
if (g_option_context_parse (context, &argc, &argv, &error) == FALSE)
|
||||||
g_warning ("couldn't parse command-line options: %s\n", error->message);
|
{
|
||||||
return 1;
|
g_warning ("couldn't parse command-line options: %s\n", error->message);
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_fatal_warnings) {
|
if (g_fatal_warnings)
|
||||||
GLogLevelFlags fatal_mask;
|
{
|
||||||
|
GLogLevelFlags fatal_mask;
|
||||||
|
|
||||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||||
g_log_set_always_fatal (fatal_mask);
|
g_log_set_always_fatal (fatal_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain a connection to the system bus */
|
/* Obtain a connection to the system bus */
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
if (!G_IS_DBUS_CONNECTION (connection)) {
|
if (!G_IS_DBUS_CONNECTION (connection))
|
||||||
g_warning("Failed to open connection to bus: %s", error->message);
|
{
|
||||||
return 1;
|
g_warning ("Failed to open connection to bus: %s", error->message);
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Load the configuration file,
|
/* Load the configuration file,
|
||||||
* and the default storage plugin */
|
* and the default storage plugin */
|
||||||
if (!load_conf())
|
if (!load_conf ())
|
||||||
set_storage_file ();
|
set_storage_file ();
|
||||||
store.init ();
|
store.init ();
|
||||||
|
|
||||||
loop = g_main_loop_new(NULL, FALSE);
|
loop = g_main_loop_new (NULL, FALSE);
|
||||||
g_unix_signal_add (SIGTERM, sigterm_callback, loop);
|
g_unix_signal_add (SIGTERM, sigterm_callback, loop);
|
||||||
|
|
||||||
g_debug("Launching FprintObject");
|
g_debug ("Launching FprintObject");
|
||||||
|
|
||||||
/* create the one instance of the Manager object to be shared between
|
/* create the one instance of the Manager object to be shared between
|
||||||
* all fprintd users. This blocks until all the devices are enumerated */
|
* all fprintd users. This blocks until all the devices are enumerated */
|
||||||
manager = fprint_manager_new (connection, no_timeout);
|
manager = fprint_manager_new (connection, no_timeout);
|
||||||
|
|
||||||
/* Obtain the well-known name after the manager has been initialized.
|
/* Obtain the well-known name after the manager has been initialized.
|
||||||
* Otherwise a client immediately enumerating the devices will not see
|
* Otherwise a client immediately enumerating the devices will not see
|
||||||
* any. */
|
* any. */
|
||||||
request_name_ret = g_bus_own_name_on_connection (connection,
|
request_name_ret = g_bus_own_name_on_connection (connection,
|
||||||
FPRINT_SERVICE_NAME,
|
FPRINT_SERVICE_NAME,
|
||||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||||
on_name_acquired,
|
on_name_acquired,
|
||||||
on_name_lost,
|
on_name_lost,
|
||||||
loop, NULL);
|
loop, NULL);
|
||||||
|
|
||||||
g_debug("entering main loop");
|
g_debug ("entering main loop");
|
||||||
g_main_loop_run(loop);
|
g_main_loop_run (loop);
|
||||||
g_bus_unown_name (request_name_ret);
|
g_bus_unown_name (request_name_ret);
|
||||||
g_debug("main loop completed");
|
g_debug ("main loop completed");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
560
src/manager.c
560
src/manager.c
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -28,294 +28,316 @@
|
|||||||
#include "fprintd.h"
|
#include "fprintd.h"
|
||||||
|
|
||||||
static void fprint_manager_constructed (GObject *object);
|
static void fprint_manager_constructed (GObject *object);
|
||||||
static gboolean fprint_manager_get_devices(FprintManager *manager,
|
static gboolean fprint_manager_get_devices (FprintManager *manager,
|
||||||
GPtrArray **devices, GError **error);
|
GPtrArray **devices,
|
||||||
static gboolean fprint_manager_get_default_device(FprintManager *manager,
|
GError **error);
|
||||||
const char **device, GError **error);
|
static gboolean fprint_manager_get_default_device (FprintManager *manager,
|
||||||
|
const char **device,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GDBusConnection *connection;
|
GDBusConnection *connection;
|
||||||
GDBusObjectManager *object_manager;
|
GDBusObjectManager *object_manager;
|
||||||
FprintDBusManager *dbus_manager;
|
FprintDBusManager *dbus_manager;
|
||||||
FpContext *context;
|
FpContext *context;
|
||||||
gboolean no_timeout;
|
gboolean no_timeout;
|
||||||
guint timeout_id;
|
guint timeout_id;
|
||||||
} FprintManagerPrivate;
|
} FprintManagerPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE(FprintManager, fprint_manager, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintManager))
|
G_DEFINE_TYPE_WITH_CODE (FprintManager, fprint_manager, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintManager))
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
FPRINT_MANAGER_CONNECTION,
|
FPRINT_MANAGER_CONNECTION,
|
||||||
N_PROPS
|
N_PROPS
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *properties[N_PROPS];
|
static GParamSpec *properties[N_PROPS];
|
||||||
|
|
||||||
static void fprint_manager_finalize(GObject *object)
|
static void
|
||||||
|
fprint_manager_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
|
||||||
|
|
||||||
g_clear_object (&priv->object_manager);
|
g_clear_object (&priv->object_manager);
|
||||||
g_clear_object (&priv->dbus_manager);
|
g_clear_object (&priv->dbus_manager);
|
||||||
g_clear_object (&priv->connection);
|
g_clear_object (&priv->connection);
|
||||||
g_clear_object (&priv->context);
|
g_clear_object (&priv->context);
|
||||||
|
|
||||||
G_OBJECT_CLASS(fprint_manager_parent_class)->finalize(object);
|
G_OBJECT_CLASS (fprint_manager_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FprintDevice *
|
static FprintDevice *
|
||||||
fprint_dbus_object_skeleton_get_device (FprintDBusObjectSkeleton *object) {
|
fprint_dbus_object_skeleton_get_device (FprintDBusObjectSkeleton *object)
|
||||||
FprintDevice *rdev;
|
{
|
||||||
|
FprintDevice *rdev;
|
||||||
|
|
||||||
g_object_get (object, "device", &rdev, NULL);
|
g_object_get (object, "device", &rdev, NULL);
|
||||||
return rdev;
|
return rdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fprint_manager_set_property (GObject *object, guint property_id,
|
static void
|
||||||
const GValue *value, GParamSpec *pspec)
|
fprint_manager_set_property (GObject *object, guint property_id,
|
||||||
|
const GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
FprintManager *self = FPRINT_MANAGER (object);
|
FprintManager *self = FPRINT_MANAGER (object);
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
|
||||||
|
|
||||||
switch (property_id) {
|
switch (property_id)
|
||||||
case FPRINT_MANAGER_CONNECTION:
|
{
|
||||||
priv->connection = g_value_dup_object (value);
|
case FPRINT_MANAGER_CONNECTION:
|
||||||
break;
|
priv->connection = g_value_dup_object (value);
|
||||||
default:
|
break;
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
||||||
break;
|
default:
|
||||||
}
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fprint_manager_get_property (GObject *object, guint property_id,
|
static void
|
||||||
GValue *value, GParamSpec *pspec)
|
fprint_manager_get_property (GObject *object, guint property_id,
|
||||||
|
GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
FprintManager *self = FPRINT_MANAGER (object);
|
FprintManager *self = FPRINT_MANAGER (object);
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
|
||||||
|
|
||||||
switch (property_id) {
|
switch (property_id)
|
||||||
case FPRINT_MANAGER_CONNECTION:
|
{
|
||||||
g_value_set_object (value, priv->connection);
|
case FPRINT_MANAGER_CONNECTION:
|
||||||
break;
|
g_value_set_object (value, priv->connection);
|
||||||
default:
|
break;
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
||||||
break;
|
default:
|
||||||
}
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fprint_manager_class_init(FprintManagerClass *klass)
|
static void
|
||||||
|
fprint_manager_class_init (FprintManagerClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->constructed = fprint_manager_constructed;
|
object_class->constructed = fprint_manager_constructed;
|
||||||
object_class->set_property = fprint_manager_set_property;
|
object_class->set_property = fprint_manager_set_property;
|
||||||
object_class->get_property = fprint_manager_get_property;
|
object_class->get_property = fprint_manager_get_property;
|
||||||
object_class->finalize = fprint_manager_finalize;
|
object_class->finalize = fprint_manager_finalize;
|
||||||
|
|
||||||
properties[FPRINT_MANAGER_CONNECTION] =
|
properties[FPRINT_MANAGER_CONNECTION] =
|
||||||
g_param_spec_object ("connection",
|
g_param_spec_object ("connection",
|
||||||
"Connection",
|
"Connection",
|
||||||
"Set GDBus connection property",
|
"Set GDBus connection property",
|
||||||
G_TYPE_DBUS_CONNECTION,
|
G_TYPE_DBUS_CONNECTION,
|
||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_READWRITE);
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *get_device_path(FprintDevice *rdev)
|
static gchar *
|
||||||
|
get_device_path (FprintDevice *rdev)
|
||||||
{
|
{
|
||||||
return g_strdup_printf (FPRINT_SERVICE_PATH "/Device/%d",
|
return g_strdup_printf (FPRINT_SERVICE_PATH "/Device/%d",
|
||||||
_fprint_device_get_id(rdev));
|
_fprint_device_get_id (rdev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fprint_manager_timeout_cb (FprintManager *manager)
|
fprint_manager_timeout_cb (FprintManager *manager)
|
||||||
{
|
{
|
||||||
//FIXME kill all the devices
|
//FIXME kill all the devices
|
||||||
exit(0);
|
exit (0);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintManager *manager)
|
fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintManager *manager)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||||
guint num_devices_used = 0;
|
guint num_devices_used = 0;
|
||||||
g_autolist(GDBusObject) devices = NULL;
|
|
||||||
GList *l;
|
|
||||||
gboolean in_use;
|
|
||||||
|
|
||||||
if (priv->timeout_id > 0) {
|
g_autolist (GDBusObject) devices = NULL;
|
||||||
g_source_remove (priv->timeout_id);
|
GList *l;
|
||||||
priv->timeout_id = 0;
|
gboolean in_use;
|
||||||
}
|
|
||||||
if (priv->no_timeout)
|
|
||||||
return;
|
|
||||||
|
|
||||||
devices = g_dbus_object_manager_get_objects (priv->object_manager);
|
if (priv->timeout_id > 0)
|
||||||
|
{
|
||||||
|
g_source_remove (priv->timeout_id);
|
||||||
|
priv->timeout_id = 0;
|
||||||
|
}
|
||||||
|
if (priv->no_timeout)
|
||||||
|
return;
|
||||||
|
|
||||||
for (l = devices; l != NULL; l = l->next) {
|
devices = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||||
g_autoptr(FprintDevice) dev = NULL;
|
|
||||||
FprintDBusObjectSkeleton *object = l->data;
|
|
||||||
|
|
||||||
dev = fprint_dbus_object_skeleton_get_device (object);
|
for (l = devices; l != NULL; l = l->next)
|
||||||
g_object_get (G_OBJECT(dev), "in-use", &in_use, NULL);
|
{
|
||||||
if (in_use != FALSE)
|
g_autoptr(FprintDevice) dev = NULL;
|
||||||
num_devices_used++;
|
FprintDBusObjectSkeleton *object = l->data;
|
||||||
}
|
|
||||||
|
|
||||||
if (num_devices_used == 0)
|
dev = fprint_dbus_object_skeleton_get_device (object);
|
||||||
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
|
g_object_get (G_OBJECT (dev), "in-use", &in_use, NULL);
|
||||||
|
if (in_use != FALSE)
|
||||||
|
num_devices_used++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_devices_used == 0)
|
||||||
|
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_get_devices (FprintManager *manager, GDBusMethodInvocation *invocation,
|
handle_get_devices (FprintManager *manager, GDBusMethodInvocation *invocation,
|
||||||
FprintDBusManager *skeleton)
|
FprintDBusManager *skeleton)
|
||||||
{
|
{
|
||||||
g_autoptr(GPtrArray) devices = NULL;
|
g_autoptr(GPtrArray) devices = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
if (!fprint_manager_get_devices (manager, &devices, &error)) {
|
if (!fprint_manager_get_devices (manager, &devices, &error))
|
||||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
{
|
||||||
return TRUE;
|
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||||
}
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
fprint_dbus_manager_complete_get_devices (skeleton, invocation,
|
fprint_dbus_manager_complete_get_devices (skeleton, invocation,
|
||||||
(const gchar *const *)
|
(const gchar *const *)
|
||||||
devices->pdata);
|
devices->pdata);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_get_default_device (FprintManager *manager,
|
handle_get_default_device (FprintManager *manager,
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
FprintDBusManager *skeleton)
|
FprintDBusManager *skeleton)
|
||||||
{
|
{
|
||||||
const gchar *device;
|
const gchar *device;
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
|
|
||||||
if (!fprint_manager_get_default_device (manager, &device, &error)) {
|
g_autoptr(GError) error = NULL;
|
||||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprint_dbus_manager_complete_get_default_device (skeleton, invocation,
|
if (!fprint_manager_get_default_device (manager, &device, &error))
|
||||||
device);
|
{
|
||||||
|
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
fprint_dbus_manager_complete_get_default_device (skeleton, invocation,
|
||||||
|
device);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||||
g_autoptr(FprintDBusObjectSkeleton) object = NULL;
|
|
||||||
g_autoptr(FprintDevice) rdev = NULL;
|
|
||||||
g_autofree gchar *path = NULL;
|
|
||||||
|
|
||||||
rdev = fprint_device_new(device);
|
g_autoptr(FprintDBusObjectSkeleton) object = NULL;
|
||||||
|
g_autoptr(FprintDevice) rdev = NULL;
|
||||||
|
g_autofree gchar *path = NULL;
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT(rdev), "notify::in-use",
|
rdev = fprint_device_new (device);
|
||||||
G_CALLBACK (fprint_manager_in_use_notified), manager);
|
|
||||||
|
|
||||||
path = get_device_path (rdev);
|
g_signal_connect (G_OBJECT (rdev), "notify::in-use",
|
||||||
|
G_CALLBACK (fprint_manager_in_use_notified), manager);
|
||||||
|
|
||||||
object = fprint_dbus_object_skeleton_new (path);
|
path = get_device_path (rdev);
|
||||||
fprint_dbus_object_skeleton_set_device (object,
|
|
||||||
FPRINT_DBUS_DEVICE (rdev));
|
object = fprint_dbus_object_skeleton_new (path);
|
||||||
g_dbus_object_manager_server_export (
|
fprint_dbus_object_skeleton_set_device (object,
|
||||||
G_DBUS_OBJECT_MANAGER_SERVER (priv->object_manager),
|
FPRINT_DBUS_DEVICE (rdev));
|
||||||
G_DBUS_OBJECT_SKELETON (object));
|
g_dbus_object_manager_server_export (
|
||||||
|
G_DBUS_OBJECT_MANAGER_SERVER (priv->object_manager),
|
||||||
|
G_DBUS_OBJECT_SKELETON (object));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||||
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
|
||||||
GList *item;
|
|
||||||
|
|
||||||
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
||||||
|
GList *item;
|
||||||
|
|
||||||
for (item = objects; item; item = item->next) {
|
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||||
g_autoptr(FprintDevice) rdev = NULL;
|
|
||||||
g_autoptr(FpDevice) dev = NULL;
|
|
||||||
FprintDBusObjectSkeleton *object = item->data;
|
|
||||||
|
|
||||||
rdev = fprint_dbus_object_skeleton_get_device (object);
|
for (item = objects; item; item = item->next)
|
||||||
g_object_get (rdev, "dev", &dev, NULL);
|
{
|
||||||
if (dev != device)
|
g_autoptr(FprintDevice) rdev = NULL;
|
||||||
continue;
|
g_autoptr(FpDevice) dev = NULL;
|
||||||
|
FprintDBusObjectSkeleton *object = item->data;
|
||||||
|
|
||||||
g_dbus_object_manager_server_unexport (
|
rdev = fprint_dbus_object_skeleton_get_device (object);
|
||||||
G_DBUS_OBJECT_MANAGER_SERVER (priv->object_manager),
|
g_object_get (rdev, "dev", &dev, NULL);
|
||||||
g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (rdev)));
|
if (dev != device)
|
||||||
|
continue;
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_data (rdev, manager);
|
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)));
|
||||||
|
|
||||||
/* We cannot continue to iterate at this point, but we don't need to either */
|
g_signal_handlers_disconnect_by_data (rdev, manager);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The device that disappeared might have been in-use.
|
/* We cannot continue to iterate at this point, but we don't need to either */
|
||||||
* Do we need to do anything else in this case to clean up more gracefully? */
|
break;
|
||||||
fprint_manager_in_use_notified (NULL, NULL, manager);
|
}
|
||||||
|
|
||||||
|
/* The device that disappeared might have been in-use.
|
||||||
|
* Do we need to do anything else in this case to clean up more gracefully? */
|
||||||
|
fprint_manager_in_use_notified (NULL, NULL, manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fprint_manager_constructed (GObject *object)
|
static void
|
||||||
|
fprint_manager_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
FprintManager *manager = FPRINT_MANAGER (object);
|
FprintManager *manager = FPRINT_MANAGER (object);
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||||
GDBusObjectManagerServer *object_manager_server;
|
GDBusObjectManagerServer *object_manager_server;
|
||||||
|
|
||||||
object_manager_server =
|
object_manager_server =
|
||||||
g_dbus_object_manager_server_new (FPRINT_SERVICE_PATH "/Device");
|
g_dbus_object_manager_server_new (FPRINT_SERVICE_PATH);
|
||||||
|
|
||||||
priv->object_manager = G_DBUS_OBJECT_MANAGER (object_manager_server);
|
priv->object_manager = G_DBUS_OBJECT_MANAGER (object_manager_server);
|
||||||
priv->dbus_manager = fprint_dbus_manager_skeleton_new ();
|
priv->dbus_manager = fprint_dbus_manager_skeleton_new ();
|
||||||
priv->context = fp_context_new ();
|
priv->context = fp_context_new ();
|
||||||
|
|
||||||
g_signal_connect_object (priv->dbus_manager,
|
g_signal_connect_object (priv->dbus_manager,
|
||||||
"handle-get-devices",
|
"handle-get-devices",
|
||||||
G_CALLBACK (handle_get_devices),
|
G_CALLBACK (handle_get_devices),
|
||||||
manager,
|
manager,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
g_signal_connect_object (priv->dbus_manager,
|
g_signal_connect_object (priv->dbus_manager,
|
||||||
"handle-get-default-device",
|
"handle-get-default-device",
|
||||||
G_CALLBACK (handle_get_default_device),
|
G_CALLBACK (handle_get_default_device),
|
||||||
manager,
|
manager,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
|
|
||||||
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_manager),
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_manager),
|
||||||
priv->connection,
|
priv->connection,
|
||||||
FPRINT_SERVICE_PATH "/Manager", NULL);
|
FPRINT_SERVICE_PATH "/Manager", NULL);
|
||||||
|
|
||||||
g_dbus_object_manager_server_set_connection (object_manager_server,
|
g_dbus_object_manager_server_set_connection (object_manager_server,
|
||||||
priv->connection);
|
priv->connection);
|
||||||
|
|
||||||
/* And register the signals for initial enumeration and hotplug. */
|
/* And register the signals for initial enumeration and hotplug. */
|
||||||
g_signal_connect_object (priv->context,
|
g_signal_connect_object (priv->context,
|
||||||
"device-added",
|
"device-added",
|
||||||
(GCallback) device_added_cb,
|
(GCallback) device_added_cb,
|
||||||
manager,
|
manager,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
|
|
||||||
g_signal_connect_object (priv->context,
|
g_signal_connect_object (priv->context,
|
||||||
"device-removed",
|
"device-removed",
|
||||||
(GCallback) device_removed_cb,
|
(GCallback) device_removed_cb,
|
||||||
manager,
|
manager,
|
||||||
G_CONNECT_SWAPPED);
|
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
|
* This blocks the main loop until the existing devices are enumerated
|
||||||
*/
|
*/
|
||||||
fp_context_enumerate (priv->context);
|
fp_context_enumerate (priv->context);
|
||||||
|
|
||||||
G_OBJECT_CLASS (fprint_manager_parent_class)->constructed (object);
|
G_OBJECT_CLASS (fprint_manager_parent_class)->constructed (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -323,99 +345,113 @@ fprint_manager_init (FprintManager *manager)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FprintManager *fprint_manager_new (GDBusConnection *connection, gboolean no_timeout)
|
FprintManager *
|
||||||
|
fprint_manager_new (GDBusConnection *connection, gboolean no_timeout)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv;
|
FprintManagerPrivate *priv;
|
||||||
GObject *object;
|
GObject *object;
|
||||||
|
|
||||||
object = g_object_new (FPRINT_TYPE_MANAGER, "connection", connection, NULL);
|
object = g_object_new (FPRINT_TYPE_MANAGER, "connection", connection, NULL);
|
||||||
priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
|
priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
|
||||||
priv->no_timeout = no_timeout;
|
priv->no_timeout = no_timeout;
|
||||||
|
|
||||||
if (!priv->no_timeout)
|
if (!priv->no_timeout)
|
||||||
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, object);
|
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, object);
|
||||||
|
|
||||||
return FPRINT_MANAGER (object);
|
return FPRINT_MANAGER (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean fprint_manager_get_devices(FprintManager *manager,
|
static gboolean
|
||||||
GPtrArray **devices, GError **error)
|
fprint_manager_get_devices (FprintManager *manager,
|
||||||
|
GPtrArray **devices, GError **error)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||||
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
|
||||||
GList *l;
|
|
||||||
int num_open;
|
|
||||||
GPtrArray *devs;
|
|
||||||
|
|
||||||
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
||||||
objects = g_list_reverse (objects);
|
GList *l;
|
||||||
|
int num_open;
|
||||||
|
GPtrArray *devs;
|
||||||
|
|
||||||
num_open = g_list_length (objects);
|
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||||
devs = g_ptr_array_sized_new(num_open);
|
objects = g_list_reverse (objects);
|
||||||
|
|
||||||
if (num_open > 0) {
|
num_open = g_list_length (objects);
|
||||||
for (l = objects; l != NULL; l = l->next) {
|
devs = g_ptr_array_sized_new (num_open);
|
||||||
g_autoptr(FprintDevice) rdev = NULL;
|
|
||||||
FprintDBusObjectSkeleton *object = l->data;
|
|
||||||
const char *path;
|
|
||||||
|
|
||||||
rdev = fprint_dbus_object_skeleton_get_device (object);
|
if (num_open > 0)
|
||||||
path = g_dbus_interface_skeleton_get_object_path (
|
{
|
||||||
G_DBUS_INTERFACE_SKELETON (rdev));
|
for (l = objects; l != NULL; l = l->next)
|
||||||
g_ptr_array_add (devs, (char *) path);
|
{
|
||||||
}
|
g_autoptr(FprintDevice) rdev = NULL;
|
||||||
}
|
FprintDBusObjectSkeleton *object = l->data;
|
||||||
g_ptr_array_add (devs, NULL);
|
const char *path;
|
||||||
|
|
||||||
*devices = devs;
|
rdev = fprint_dbus_object_skeleton_get_device (object);
|
||||||
return TRUE;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean fprint_manager_get_default_device(FprintManager *manager,
|
static gboolean
|
||||||
const char **device, GError **error)
|
fprint_manager_get_default_device (FprintManager *manager,
|
||||||
|
const char **device, GError **error)
|
||||||
{
|
{
|
||||||
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
|
||||||
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
|
||||||
int num_open;
|
|
||||||
|
|
||||||
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
g_autolist (FprintDBusObjectSkeleton) objects = NULL;
|
||||||
num_open = g_list_length (objects);
|
int num_open;
|
||||||
|
|
||||||
if (num_open > 0) {
|
objects = g_dbus_object_manager_get_objects (priv->object_manager);
|
||||||
g_autoptr(FprintDevice) rdev = NULL;
|
num_open = g_list_length (objects);
|
||||||
FprintDBusObjectSkeleton *object = g_list_last (objects)->data;
|
|
||||||
|
|
||||||
rdev = fprint_dbus_object_skeleton_get_device (object);
|
if (num_open > 0)
|
||||||
*device = g_dbus_interface_skeleton_get_object_path (
|
{
|
||||||
G_DBUS_INTERFACE_SKELETON (rdev));
|
g_autoptr(FprintDevice) rdev = NULL;
|
||||||
return TRUE;
|
FprintDBusObjectSkeleton *object = g_list_last (objects)->data;
|
||||||
} else {
|
|
||||||
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE,
|
rdev = fprint_dbus_object_skeleton_get_device (object);
|
||||||
"No devices available");
|
*device = g_dbus_interface_skeleton_get_object_path (
|
||||||
*device = NULL;
|
G_DBUS_INTERFACE_SKELETON (rdev));
|
||||||
return FALSE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE,
|
||||||
|
"No devices available");
|
||||||
|
*device = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GQuark fprint_error_quark (void)
|
GQuark
|
||||||
|
fprint_error_quark (void)
|
||||||
{
|
{
|
||||||
static volatile gsize quark = 0;
|
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");
|
if (g_once_init_enter (&quark))
|
||||||
errors_enum = g_type_class_ref (FPRINT_TYPE_ERROR);
|
{
|
||||||
|
g_autoptr(GEnumClass) errors_enum = NULL;
|
||||||
|
GQuark domain;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < errors_enum->n_values; ++i) {
|
domain = g_quark_from_static_string ("fprintd-error-quark");
|
||||||
GEnumValue *value = &errors_enum->values[i];
|
errors_enum = g_type_class_ref (FPRINT_TYPE_ERROR);
|
||||||
|
|
||||||
g_dbus_error_register_error (domain, value->value,
|
for (i = 0; i < errors_enum->n_values; ++i)
|
||||||
value->value_nick);
|
{
|
||||||
}
|
GEnumValue *value = &errors_enum->values[i];
|
||||||
|
|
||||||
g_once_init_leave (&quark, domain);
|
g_dbus_error_register_error (domain, value->value,
|
||||||
}
|
value->value_nick);
|
||||||
return (GQuark) quark;
|
}
|
||||||
|
|
||||||
|
g_once_init_leave (&quark, domain);
|
||||||
|
}
|
||||||
|
return (GQuark) quark;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,8 @@ foreach interface_name: dbus_interfaces
|
|||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
fprintd_dbus_sources = gnome.gdbus_codegen('fprintd-dbus',
|
# NOTE: We should pass "--glib-min-required 2.64" but cannot
|
||||||
|
fprintd_dbus_sources_base = gnome.gdbus_codegen('fprintd-dbus',
|
||||||
sources: dbus_interfaces_files,
|
sources: dbus_interfaces_files,
|
||||||
autocleanup: 'all',
|
autocleanup: 'all',
|
||||||
interface_prefix: 'net.reactivated.Fprint.',
|
interface_prefix: 'net.reactivated.Fprint.',
|
||||||
@ -22,6 +23,23 @@ fprintd_dbus_sources = gnome.gdbus_codegen('fprintd-dbus',
|
|||||||
object_manager: true,
|
object_manager: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# FIXME: remove this and just use fprintd_dbus_sources when we're on glib 2.64
|
||||||
|
fprintd_dbus_sources = [
|
||||||
|
fprintd_dbus_sources_base[1] # header file
|
||||||
|
]
|
||||||
|
|
||||||
|
fprintd_dbus_sources += custom_target('fprintd-dbus-interactive',
|
||||||
|
input: fprintd_dbus_sources_base[0], # c file,
|
||||||
|
output: 'fprintd-dbus-interactive.c',
|
||||||
|
command: [
|
||||||
|
find_program('patch'),
|
||||||
|
'-p1',
|
||||||
|
'--merge',
|
||||||
|
'@INPUT@',
|
||||||
|
files('dbus-interactive-auth.patch'),
|
||||||
|
'-o', '@OUTPUT@',
|
||||||
|
])
|
||||||
|
|
||||||
fprintd_enum_files = gnome.mkenums_simple('fprintd-enums',
|
fprintd_enum_files = gnome.mkenums_simple('fprintd-enums',
|
||||||
sources: 'fprintd.h',
|
sources: 'fprintd.h',
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -28,19 +28,21 @@ typedef int (*storage_print_data_load)(FpDevice *dev,
|
|||||||
typedef int (*storage_print_data_delete)(FpDevice *dev,
|
typedef int (*storage_print_data_delete)(FpDevice *dev,
|
||||||
FpFinger finger,
|
FpFinger finger,
|
||||||
const char *username);
|
const char *username);
|
||||||
typedef GSList *(*storage_discover_prints)(FpDevice *dev, const char *username);
|
typedef GSList *(*storage_discover_prints)(FpDevice *dev,
|
||||||
|
const char *username);
|
||||||
typedef GSList *(*storage_discover_users)(void);
|
typedef GSList *(*storage_discover_users)(void);
|
||||||
typedef int (*storage_init)(void);
|
typedef int (*storage_init)(void);
|
||||||
typedef int (*storage_deinit)(void);
|
typedef int (*storage_deinit)(void);
|
||||||
|
|
||||||
struct storage {
|
struct storage
|
||||||
storage_init init;
|
{
|
||||||
storage_deinit deinit;
|
storage_init init;
|
||||||
storage_print_data_save print_data_save;
|
storage_deinit deinit;
|
||||||
storage_print_data_load print_data_load;
|
storage_print_data_save print_data_save;
|
||||||
storage_print_data_delete print_data_delete;
|
storage_print_data_load print_data_load;
|
||||||
storage_discover_prints discover_prints;
|
storage_print_data_delete print_data_delete;
|
||||||
storage_discover_users discover_users;
|
storage_discover_prints discover_prints;
|
||||||
|
storage_discover_users discover_users;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct storage fp_storage;
|
typedef struct storage fp_storage;
|
||||||
|
|||||||
@ -18,6 +18,8 @@ __email__ = 'hadess@hadess.net'
|
|||||||
__copyright__ = '(c) 2020 Red Hat Inc.'
|
__copyright__ = '(c) 2020 Red Hat Inc.'
|
||||||
__license__ = 'LGPL 3+'
|
__license__ = 'LGPL 3+'
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from gi.repository import GLib
|
||||||
import dbus
|
import dbus
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@ -213,13 +215,26 @@ def can_verify_finger(device, finger_name):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def send_verify_script(device, script):
|
def glib_sleep(timeout):
|
||||||
for [result, done, timeout] in device.verify_script:
|
waiting = True
|
||||||
await asyncio.sleep(timeout)
|
|
||||||
device.EmitSignal(DEVICE_IFACE, 'VerifyStatus', 'sb', [
|
def done_waiting():
|
||||||
result,
|
nonlocal waiting
|
||||||
done
|
waiting = False
|
||||||
])
|
|
||||||
|
GLib.timeout_add(timeout, done_waiting)
|
||||||
|
while (waiting):
|
||||||
|
GLib.main_context_default().iteration(True)
|
||||||
|
|
||||||
|
def device_run_script(device, result, done):
|
||||||
|
if result == 'MOCK: quit':
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# Emit signal
|
||||||
|
device.EmitSignal(DEVICE_IFACE, 'VerifyStatus', 'sb', [
|
||||||
|
result,
|
||||||
|
done
|
||||||
|
])
|
||||||
|
|
||||||
@dbus.service.method(DEVICE_IFACE,
|
@dbus.service.method(DEVICE_IFACE,
|
||||||
in_signature='s', out_signature='')
|
in_signature='s', out_signature='')
|
||||||
@ -249,13 +264,44 @@ def VerifyStart(device, finger_name):
|
|||||||
if finger_name == 'any' and not device.has_identification:
|
if finger_name == 'any' and not device.has_identification:
|
||||||
finger_name = device.fingers[device.claimed_user][0]
|
finger_name = device.fingers[device.claimed_user][0]
|
||||||
device.selected_finger = finger_name
|
device.selected_finger = finger_name
|
||||||
device.EmitSignal(DEVICE_IFACE, 'VerifyFingerSelected', 's', [
|
# Needs to happen after method return
|
||||||
finger_name
|
GLib.idle_add(device.EmitSignal,
|
||||||
])
|
DEVICE_IFACE, 'VerifyFingerSelected', 's', [
|
||||||
|
device.selected_finger
|
||||||
|
])
|
||||||
|
|
||||||
if device.verify_script is not None and len(device.verify_script) > 0:
|
error = None
|
||||||
asyncio.run(send_verify_script(device, device.verify_script))
|
base_delay = 0
|
||||||
|
while device.verify_script is not None and len(device.verify_script) > 0:
|
||||||
|
result, done, timeout = device.verify_script.pop(0)
|
||||||
|
|
||||||
|
# We stop when "timeout >= 0 and done"
|
||||||
|
if result == 'MOCK: no-prints':
|
||||||
|
# Special case to change return value of DBus call, ignores timeout
|
||||||
|
error = dbus.exceptions.DBusException(
|
||||||
|
'No enrolled prints for user \'%s\'' % device.claimed_user,
|
||||||
|
name='net.reactivated.Fprint.Error.NoEnrolledPrints')
|
||||||
|
|
||||||
|
elif timeout < 0:
|
||||||
|
# Negative timeouts mean emitting before the DBus call returns
|
||||||
|
device_run_script(device, result, done)
|
||||||
|
glib_sleep(-timeout)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Positive or zero means emitting afterwards the given timeout
|
||||||
|
base_delay += timeout
|
||||||
|
GLib.timeout_add(base_delay,
|
||||||
|
device_run_script,
|
||||||
|
device,
|
||||||
|
result,
|
||||||
|
done)
|
||||||
|
|
||||||
|
# Stop processing commands when the done flag is set
|
||||||
|
if done:
|
||||||
|
break
|
||||||
|
|
||||||
|
if error:
|
||||||
|
raise error
|
||||||
|
|
||||||
@dbus.service.method(DEVICE_MOCK_IFACE,
|
@dbus.service.method(DEVICE_MOCK_IFACE,
|
||||||
in_signature='sb', out_signature='')
|
in_signature='sb', out_signature='')
|
||||||
@ -383,3 +429,11 @@ def SetVerifyScript(device, script):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
device.verify_script = script
|
device.verify_script = script
|
||||||
|
|
||||||
|
@dbus.service.method(DEVICE_MOCK_IFACE,
|
||||||
|
in_signature='s', out_signature='')
|
||||||
|
def SetClaimed(device, user):
|
||||||
|
if user == '':
|
||||||
|
device.claimed_user = None
|
||||||
|
else:
|
||||||
|
device.claimed_user = user
|
||||||
|
|||||||
142
tests/fprintd.py
142
tests/fprintd.py
@ -138,6 +138,8 @@ class FPrintdTest(dbusmock.DBusTestCase):
|
|||||||
fprintd = None
|
fprintd = None
|
||||||
cls._polkitd = None
|
cls._polkitd = None
|
||||||
|
|
||||||
|
cls._has_hotplug = FPrint.Device.find_property("removed") is not None
|
||||||
|
|
||||||
if 'FPRINT_BUILD_DIR' in os.environ:
|
if 'FPRINT_BUILD_DIR' in os.environ:
|
||||||
print('Testing local build')
|
print('Testing local build')
|
||||||
build_dir = os.environ['FPRINT_BUILD_DIR']
|
build_dir = os.environ['FPRINT_BUILD_DIR']
|
||||||
@ -491,32 +493,55 @@ class FPrintdManagerPreStartTests(FPrintdTest):
|
|||||||
self.manager.GetDefaultDevice()
|
self.manager.GetDefaultDevice()
|
||||||
|
|
||||||
def test_manager_get_devices_on_name_appeared(self):
|
def test_manager_get_devices_on_name_appeared(self):
|
||||||
self._appeared_res = []
|
self._appeared_name = None
|
||||||
|
|
||||||
def on_name_appeared(connection, name, name_owner):
|
def on_name_appeared(connection, name, name_owner):
|
||||||
self._appeared_res.append(connection.call_sync('net.reactivated.Fprint',
|
self._appeared_name = name
|
||||||
'/net/reactivated/Fprint/Manager',
|
|
||||||
'net.reactivated.Fprint.Manager',
|
def on_name_vanished(connection, name):
|
||||||
'GetDefaultDevice', None, None,
|
self._appeared_name = 'NAME_VANISHED'
|
||||||
Gio.DBusCallFlags.NO_AUTO_START, 500, None))
|
|
||||||
|
|
||||||
id = Gio.bus_watch_name_on_connection(self.dbus,
|
id = Gio.bus_watch_name_on_connection(self.dbus,
|
||||||
'net.reactivated.Fprint', Gio.BusNameWatcherFlags.NONE,
|
'net.reactivated.Fprint', Gio.BusNameWatcherFlags.NONE,
|
||||||
on_name_appeared, None)
|
on_name_appeared, on_name_vanished)
|
||||||
|
self.addCleanup(Gio.bus_unwatch_name, id)
|
||||||
|
|
||||||
self.daemon_start()
|
self.daemon_start()
|
||||||
while not self._appeared_res:
|
while not self._appeared_name:
|
||||||
ctx.iteration(True)
|
ctx.iteration(True)
|
||||||
|
|
||||||
self.assertIsNotNone(self._appeared_res[0])
|
self.assertEqual(self._appeared_name, 'net.reactivated.Fprint')
|
||||||
dev_path = self._appeared_res[0][0]
|
|
||||||
self.assertTrue(dev_path.startswith('/net/reactivated/Fprint/Device/'))
|
|
||||||
|
|
||||||
Gio.bus_unwatch_name(id)
|
try:
|
||||||
|
appeared_device = self.dbus.call_sync(
|
||||||
|
'net.reactivated.Fprint',
|
||||||
|
'/net/reactivated/Fprint/Manager',
|
||||||
|
'net.reactivated.Fprint.Manager',
|
||||||
|
'GetDefaultDevice', None, None,
|
||||||
|
Gio.DBusCallFlags.NO_AUTO_START, 500, None)
|
||||||
|
except GLib.GError as e:
|
||||||
|
if 'net.reactivated.Fprint.Error.NoSuchDevice' in e.message:
|
||||||
|
self.skipTest("Need virtual_image device to run the test")
|
||||||
|
raise(e)
|
||||||
|
|
||||||
|
self.assertIsNotNone(appeared_device)
|
||||||
|
[dev_path] = appeared_device
|
||||||
|
self.assertTrue(dev_path.startswith('/net/reactivated/Fprint/Device/'))
|
||||||
|
|
||||||
|
|
||||||
class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
||||||
|
|
||||||
|
def test_name_property(self):
|
||||||
|
self.assertEqual(self.device.get_cached_property('name').unpack(),
|
||||||
|
'Virtual image device for debugging')
|
||||||
|
|
||||||
|
def test_enroll_stages_property(self):
|
||||||
|
self.assertEqual(self.device.get_cached_property('num-enroll-stages').unpack(), 5)
|
||||||
|
|
||||||
|
def test_scan_type(self):
|
||||||
|
self.assertEqual(self.device.get_cached_property('scan-type').unpack(),
|
||||||
|
'swipe')
|
||||||
|
|
||||||
def test_allowed_claim_release_enroll(self):
|
def test_allowed_claim_release_enroll(self):
|
||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
|
||||||
'net.reactivated.fprint.device.enroll'])
|
'net.reactivated.fprint.device.enroll'])
|
||||||
@ -578,6 +603,34 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
with self.assertFprintError('PermissionDenied'):
|
with self.assertFprintError('PermissionDenied'):
|
||||||
self.device.Claim('(s)', 'testuser')
|
self.device.Claim('(s)', 'testuser')
|
||||||
|
|
||||||
|
def test_unallowed_enroll_with_verify_claim(self):
|
||||||
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
||||||
|
self.device.Claim('(s)', '')
|
||||||
|
|
||||||
|
with self.assertFprintError('PermissionDenied'):
|
||||||
|
self.enroll_image('whorl', finger='right-thumb')
|
||||||
|
|
||||||
|
def test_unallowed_delete_with_verify_claim(self):
|
||||||
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
||||||
|
self.device.Claim('(s)', '')
|
||||||
|
|
||||||
|
with self.assertFprintError('PermissionDenied'):
|
||||||
|
self.device.DeleteEnrolledFingers('(s)', 'testuser')
|
||||||
|
|
||||||
|
def test_unallowed_delete2_with_verify_claim(self):
|
||||||
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
||||||
|
self.device.Claim('(s)', '')
|
||||||
|
|
||||||
|
with self.assertFprintError('PermissionDenied'):
|
||||||
|
self.device.DeleteEnrolledFingers2()
|
||||||
|
|
||||||
|
def test_unallowed_verify_with_enroll_claim(self):
|
||||||
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
||||||
|
self.device.Claim('(s)', '')
|
||||||
|
|
||||||
|
with self.assertFprintError('PermissionDenied'):
|
||||||
|
self.device.VerifyStart('(s)', 'any')
|
||||||
|
|
||||||
def test_unallowed_claim_current_user(self):
|
def test_unallowed_claim_current_user(self):
|
||||||
self._polkitd_obj.SetAllowed([''])
|
self._polkitd_obj.SetAllowed([''])
|
||||||
|
|
||||||
@ -595,20 +648,11 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
|
|
||||||
self.device.Release()
|
self.device.Release()
|
||||||
|
|
||||||
def test_unallowed_release(self):
|
def test_always_allowed_release(self):
|
||||||
self.device.Claim('(s)', 'testuser')
|
self.device.Claim('(s)', 'testuser')
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed([''])
|
self._polkitd_obj.SetAllowed([''])
|
||||||
|
|
||||||
with self.assertFprintError('PermissionDenied'):
|
|
||||||
self.device.Release()
|
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername'])
|
|
||||||
|
|
||||||
with self.assertFprintError('PermissionDenied'):
|
|
||||||
self.device.Release()
|
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
||||||
self.device.Release()
|
self.device.Release()
|
||||||
|
|
||||||
def test_unclaimed_release(self):
|
def test_unclaimed_release(self):
|
||||||
@ -688,6 +732,9 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
def test_removal_during_enroll(self):
|
def test_removal_during_enroll(self):
|
||||||
|
if not self._has_hotplug:
|
||||||
|
self.skipTest("libfprint is too old for hotplug")
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
|
||||||
'net.reactivated.fprint.device.enroll'])
|
'net.reactivated.fprint.device.enroll'])
|
||||||
self.device.Claim('(s)', 'testuser')
|
self.device.Claim('(s)', 'testuser')
|
||||||
@ -732,6 +779,11 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
self.device.VerifyStart('(s)', 'any')
|
self.device.VerifyStart('(s)', 'any')
|
||||||
|
|
||||||
def test_enroll_verify_list_delete(self):
|
def test_enroll_verify_list_delete(self):
|
||||||
|
# This test can trigger a race in older libfprint, only run if we have
|
||||||
|
# hotplug support, which coincides with the fixed release.
|
||||||
|
if not self._has_hotplug:
|
||||||
|
self.skipTest("libfprint is too old for hotplug")
|
||||||
|
|
||||||
with self.assertFprintError('NoEnrolledPrints'):
|
with self.assertFprintError('NoEnrolledPrints'):
|
||||||
self.device.ListEnrolledFingers('(s)', 'testuser')
|
self.device.ListEnrolledFingers('(s)', 'testuser')
|
||||||
|
|
||||||
@ -770,6 +822,7 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
self.wait_for_result()
|
self.wait_for_result()
|
||||||
self.assertTrue(self._verify_stopped)
|
self.assertTrue(self._verify_stopped)
|
||||||
self.assertEqual(self._last_result, 'verify-match')
|
self.assertEqual(self._last_result, 'verify-match')
|
||||||
|
self.device.VerifyStop()
|
||||||
|
|
||||||
self.assertEqual(self.device.ListEnrolledFingers('(s)', 'testuser'), ['right-index-finger'])
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', 'testuser'), ['right-index-finger'])
|
||||||
|
|
||||||
@ -792,18 +845,29 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
||||||
|
|
||||||
def test_enroll_invalid_storage_dir(self):
|
def test_enroll_invalid_storage_dir(self):
|
||||||
if 'CI_PROJECT_NAME' in os.environ:
|
# Directory wil not exist yet
|
||||||
self.skipTest('Permissions aren\'t respected in CI environment')
|
|
||||||
os.makedirs(self.state_dir, mode=0o500)
|
os.makedirs(self.state_dir, mode=0o500)
|
||||||
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.open(os.path.join(self.state_dir, "testfile"), os.O_CREAT | os.O_WRONLY)
|
||||||
|
self.skipTest('Permissions aren\'t respected (CI environment?)')
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
|
||||||
self.enroll_image('whorl', expected_result='enroll-failed')
|
self.enroll_image('whorl', expected_result='enroll-failed')
|
||||||
|
|
||||||
def test_verify_invalid_storage_dir(self):
|
def test_verify_invalid_storage_dir(self):
|
||||||
if 'CI_PROJECT_NAME' in os.environ:
|
|
||||||
self.skipTest('Permissions aren\'t respected in CI environment')
|
|
||||||
self.enroll_image('whorl')
|
self.enroll_image('whorl')
|
||||||
os.chmod(self.state_dir, mode=0o000)
|
os.chmod(self.state_dir, mode=0o000)
|
||||||
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.open(os.path.join(self.state_dir, "testfile"), os.O_CREAT | os.O_WRONLY)
|
||||||
|
self.skipTest('Permissions aren\'t respected (CI environment?)')
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
|
||||||
with self.assertFprintError('NoEnrolledPrints'):
|
with self.assertFprintError('NoEnrolledPrints'):
|
||||||
self.device.VerifyStart('(s)', 'any')
|
self.device.VerifyStart('(s)', 'any')
|
||||||
|
|
||||||
@ -938,15 +1002,11 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
||||||
self.enroll_image('whorl')
|
self.enroll_image('whorl')
|
||||||
|
|
||||||
def test_unallowed_enroll_stop(self):
|
def test_always_allowed_enroll_stop(self):
|
||||||
self.device.EnrollStart('(s)', 'right-index-finger')
|
self.device.EnrollStart('(s)', 'right-index-finger')
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed([''])
|
self._polkitd_obj.SetAllowed([''])
|
||||||
|
|
||||||
with self.assertFprintError('PermissionDenied'):
|
|
||||||
self.device.EnrollStop()
|
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
||||||
self.device.EnrollStop()
|
self.device.EnrollStop()
|
||||||
|
|
||||||
def test_unallowed_verify_start(self):
|
def test_unallowed_verify_start(self):
|
||||||
@ -955,15 +1015,11 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
with self.assertFprintError('PermissionDenied'):
|
with self.assertFprintError('PermissionDenied'):
|
||||||
self.device.VerifyStart('(s)', 'any')
|
self.device.VerifyStart('(s)', 'any')
|
||||||
|
|
||||||
def test_unallowed_verify_stop(self):
|
def test_always_allowed_verify_stop(self):
|
||||||
self.enroll_image('whorl')
|
self.enroll_image('whorl')
|
||||||
self.device.VerifyStart('(s)', 'any')
|
self.device.VerifyStart('(s)', 'any')
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed([''])
|
self._polkitd_obj.SetAllowed([''])
|
||||||
with self.assertFprintError('PermissionDenied'):
|
|
||||||
self.device.VerifyStop()
|
|
||||||
|
|
||||||
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
|
||||||
self.device.VerifyStop()
|
self.device.VerifyStop()
|
||||||
|
|
||||||
def test_list_enrolled_fingers_current_user(self):
|
def test_list_enrolled_fingers_current_user(self):
|
||||||
@ -1419,6 +1475,10 @@ class FPrintdUtilsTest(FPrintdVirtualDeviceBaseTest):
|
|||||||
print('Testing JHBuild version')
|
print('Testing JHBuild version')
|
||||||
jhbuild_prefix = os.environ['JHBUILD_PREFIX']
|
jhbuild_prefix = os.environ['JHBUILD_PREFIX']
|
||||||
path = os.path.join(jhbuild_prefix, 'bin', util_bin)
|
path = os.path.join(jhbuild_prefix, 'bin', util_bin)
|
||||||
|
else:
|
||||||
|
# Assume it is in path
|
||||||
|
utils[util] = util_bin
|
||||||
|
continue
|
||||||
|
|
||||||
assert os.path.exists(path), 'failed to find {} in {}'.format(util, path)
|
assert os.path.exists(path), 'failed to find {} in {}'.format(util, path)
|
||||||
utils[util] = path
|
utils[util] = path
|
||||||
@ -1480,4 +1540,12 @@ if __name__ == '__main__':
|
|||||||
print("%s %s" % (machine, human), end="\n")
|
print("%s %s" % (machine, human), end="\n")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
unittest.main(verbosity=2)
|
prog = unittest.main(verbosity=2, exit=False)
|
||||||
|
if prog.result.errors or prog.result.failures:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Translate to skip error
|
||||||
|
if prog.result.testsRun == len(prog.result.skipped):
|
||||||
|
sys.exit(77)
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|||||||
148
tests/output_checker.py
Normal file
148
tests/output_checker.py
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
# Copyright © 2020, RedHat Inc.
|
||||||
|
#
|
||||||
|
# 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:
|
||||||
|
# Benjamin Berg <bberg@redhat.com>
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import fcntl
|
||||||
|
import io
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class OutputChecker(object):
|
||||||
|
|
||||||
|
def __init__(self, out=sys.stdout):
|
||||||
|
self._output = out
|
||||||
|
self._pipe_fd_r, self._pipe_fd_w = os.pipe()
|
||||||
|
self._partial_buf = b''
|
||||||
|
self._lines_sem = threading.Semaphore()
|
||||||
|
self._lines = []
|
||||||
|
self._reader_io = io.StringIO()
|
||||||
|
|
||||||
|
# Just to be sure, shouldn't be a problem even if we didn't set it
|
||||||
|
fcntl.fcntl(self._pipe_fd_r, fcntl.F_SETFL,
|
||||||
|
fcntl.fcntl(self._pipe_fd_r, fcntl.F_GETFL) | os.O_CLOEXEC)
|
||||||
|
fcntl.fcntl(self._pipe_fd_w, fcntl.F_SETFL,
|
||||||
|
fcntl.fcntl(self._pipe_fd_w, fcntl.F_GETFL) | os.O_CLOEXEC)
|
||||||
|
|
||||||
|
# Start copier thread
|
||||||
|
self._thread = threading.Thread(target=self._copy)
|
||||||
|
self._thread.start()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
while True:
|
||||||
|
r = os.read(self._pipe_fd_r, 1024)
|
||||||
|
if not r:
|
||||||
|
return
|
||||||
|
|
||||||
|
l = r.split(b'\n')
|
||||||
|
l[0] = self._partial_buf + l[0]
|
||||||
|
self._lines.extend(l[:-1])
|
||||||
|
self._partial_buf = l[-1]
|
||||||
|
|
||||||
|
self._lines_sem.release()
|
||||||
|
|
||||||
|
os.write(self._output.fileno(), r)
|
||||||
|
|
||||||
|
def check_line_re(self, needle_re, timeout=0, failmsg=None):
|
||||||
|
deadline = time.time() + timeout
|
||||||
|
|
||||||
|
if isinstance(needle_re, str):
|
||||||
|
needle_re = needle_re.encode('ascii')
|
||||||
|
|
||||||
|
r = re.compile(needle_re)
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
l = self._lines.pop(0)
|
||||||
|
except IndexError:
|
||||||
|
# Check if should wake up
|
||||||
|
if not self._lines_sem.acquire(timeout = deadline - time.time()):
|
||||||
|
if failmsg:
|
||||||
|
raise AssertionError(failmsg)
|
||||||
|
else:
|
||||||
|
raise AssertionError('Timed out waiting for needle %s (timeout: %0.2f)' % (str(needle_re), timeout))
|
||||||
|
continue
|
||||||
|
|
||||||
|
ret.append(l)
|
||||||
|
if r.search(l):
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def check_line(self, needle, timeout=0, failmsg=None):
|
||||||
|
if isinstance(needle, str):
|
||||||
|
needle = needle.encode('ascii')
|
||||||
|
|
||||||
|
needle_re = re.escape(needle)
|
||||||
|
|
||||||
|
return self.check_line_re(needle_re, timeout=timeout, failmsg=failmsg)
|
||||||
|
|
||||||
|
def check_no_line_re(self, needle_re, wait=0, failmsg=None):
|
||||||
|
deadline = time.time() + wait
|
||||||
|
|
||||||
|
if isinstance(needle_re, str):
|
||||||
|
needle_re = needle_re.encode('ascii')
|
||||||
|
|
||||||
|
r = re.compile(needle_re)
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
l = self._lines.pop(0)
|
||||||
|
except IndexError:
|
||||||
|
# Check if should wake up
|
||||||
|
if not self._lines_sem.acquire(timeout = deadline - time.time()):
|
||||||
|
# Timed out, so everything is good
|
||||||
|
break
|
||||||
|
continue
|
||||||
|
|
||||||
|
ret.append(l)
|
||||||
|
if r.search(l):
|
||||||
|
if failmsg:
|
||||||
|
raise AssertionError(failmsg)
|
||||||
|
else:
|
||||||
|
raise AssertionError('Found needle %s but shouldn\'t have been there (timeout: %0.2f)' % (str(needle_re), timeout))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def check_no_line(self, needle, wait=0, failmsg=None):
|
||||||
|
if isinstance(needle, str):
|
||||||
|
needle = needle.encode('ascii')
|
||||||
|
|
||||||
|
needle_re = re.escape(needle)
|
||||||
|
|
||||||
|
return self.check_no_line_re(needle_re, wait=wait, failmsg=failmsg)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
ret = self._lines
|
||||||
|
self._lines = []
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def assert_closed(self, timeout=1):
|
||||||
|
self._thread.join(timeout)
|
||||||
|
if self._thread.is_alive() != False:
|
||||||
|
raise AssertionError("OutputCheck: Write side has not been closed yet!")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fd(self):
|
||||||
|
return self._pipe_fd_w
|
||||||
|
|
||||||
|
def writer_attached(self):
|
||||||
|
os.close(self._pipe_fd_w)
|
||||||
|
self._pipe_fd_w = -1
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ foreach t: tests
|
|||||||
{
|
{
|
||||||
'name': t,
|
'name': t,
|
||||||
'file': files(meson.current_source_dir() / t + '.py')[0],
|
'file': files(meson.current_source_dir() / t + '.py')[0],
|
||||||
|
'is_parallel': false,
|
||||||
'env': [
|
'env': [
|
||||||
'TOPBUILDDIR=' + meson.build_root(),
|
'TOPBUILDDIR=' + meson.build_root(),
|
||||||
'TOPSRCDIR=' + meson.source_root(),
|
'TOPSRCDIR=' + meson.source_root(),
|
||||||
|
|||||||
@ -17,8 +17,9 @@ import sys
|
|||||||
import subprocess
|
import subprocess
|
||||||
import dbus
|
import dbus
|
||||||
import dbusmock
|
import dbusmock
|
||||||
import fcntl
|
import glob
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import time
|
import time
|
||||||
import pypamtest
|
import pypamtest
|
||||||
|
|
||||||
@ -68,12 +69,12 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
def tearDownClass(klass):
|
def tearDownClass(klass):
|
||||||
klass.stop_monitor()
|
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):
|
def setUp(self):
|
||||||
(self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
|
(self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
|
||||||
self.template_name, {}, stdout=subprocess.PIPE)
|
self.template_name, {})
|
||||||
# set log to nonblocking
|
|
||||||
flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL)
|
|
||||||
fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
self.obj_fprintd_mock = dbus.Interface(self.obj_fprintd_manager, 'net.reactivated.Fprint.Manager.Mock')
|
self.obj_fprintd_mock = dbus.Interface(self.obj_fprintd_manager, 'net.reactivated.Fprint.Manager.Mock')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -85,6 +86,10 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
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_mock.SetEnrolledFingers('toto', ['left-little-finger', 'right-little-finger'])
|
||||||
|
|
||||||
|
def test_pam_no_device(self):
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTHINFO_UNAVAIL)
|
||||||
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
|
|
||||||
def test_pam_fprintd_identify_error(self):
|
def test_pam_fprintd_identify_error(self):
|
||||||
self.setup_device()
|
self.setup_device()
|
||||||
script = [
|
script = [
|
||||||
@ -138,6 +143,66 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
self.assertRegex(res.info[0], r'Swipe your left little finger across the fingerprint reader')
|
self.assertRegex(res.info[0], r'Swipe your left little finger across the fingerprint reader')
|
||||||
self.assertEqual(len(res.errors), 0)
|
self.assertEqual(len(res.errors), 0)
|
||||||
|
|
||||||
|
def test_pam_fprintd_no_fingers(self):
|
||||||
|
self.setup_device()
|
||||||
|
self.device_mock.SetEnrolledFingers('toto', dbus.Array(set([]), signature='s'))
|
||||||
|
script = [
|
||||||
|
( 'verify-match', True, 1 )
|
||||||
|
]
|
||||||
|
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' ])
|
||||||
|
|
||||||
|
def test_pam_fprintd_no_fingers_while_verifying(self):
|
||||||
|
self.setup_device()
|
||||||
|
script = [
|
||||||
|
( 'MOCK: no-prints', True, 1),
|
||||||
|
( 'verify-match', True, 1 )
|
||||||
|
]
|
||||||
|
self.device_mock.SetVerifyScript(script)
|
||||||
|
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_USER_UNKNOWN)
|
||||||
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
|
|
||||||
|
def test_pam_fprintd_blocks_unexpected_auth(self):
|
||||||
|
self.setup_device()
|
||||||
|
script = [
|
||||||
|
( 'verify-match', True, -500 ), # This one is sent before VerifyStart has completed
|
||||||
|
( 'verify-no-match', True, 1 ),
|
||||||
|
( 'verify-no-match', True, 1 ),
|
||||||
|
( 'verify-no-match', True, 1 ),
|
||||||
|
]
|
||||||
|
self.device_mock.SetVerifyScript(script)
|
||||||
|
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_MAXTRIES)
|
||||||
|
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), 3)
|
||||||
|
self.assertRegex(res.errors[0], r'Failed to match fingerprint')
|
||||||
|
self.assertRegex(res.errors[0], r'Failed to match fingerprint')
|
||||||
|
self.assertRegex(res.errors[0], r'Failed to match fingerprint')
|
||||||
|
|
||||||
|
def test_pam_fprintd_blocks_unexpected_auth2(self):
|
||||||
|
self.setup_device()
|
||||||
|
script = [
|
||||||
|
( 'verify-no-match', True, 1 ),
|
||||||
|
( 'verify-match', True, -500 ), # This one is sent before VerifyStart has completed
|
||||||
|
( 'verify-no-match', True, 1 ),
|
||||||
|
( 'verify-no-match', True, 1 ),
|
||||||
|
]
|
||||||
|
self.device_mock.SetVerifyScript(script)
|
||||||
|
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_MAXTRIES)
|
||||||
|
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), 3)
|
||||||
|
self.assertRegex(res.errors[0], r'Failed to match fingerprint')
|
||||||
|
self.assertRegex(res.errors[0], r'Failed to match fingerprint')
|
||||||
|
self.assertRegex(res.errors[0], r'Failed to match fingerprint')
|
||||||
|
|
||||||
def test_pam_fprintd_dual_reader_auth(self):
|
def test_pam_fprintd_dual_reader_auth(self):
|
||||||
device_path = self.obj_fprintd_mock.AddDevice('FDO Sandpaper Reader', 3, 'press')
|
device_path = self.obj_fprintd_mock.AddDevice('FDO Sandpaper Reader', 3, 'press')
|
||||||
sandpaper_device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
sandpaper_device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path)
|
||||||
@ -191,6 +256,20 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
self.assertRegex(res.errors[1], r'Failed to match fingerprint')
|
self.assertRegex(res.errors[1], r'Failed to match fingerprint')
|
||||||
self.assertRegex(res.errors[2], r'Failed to match fingerprint')
|
self.assertRegex(res.errors[2], r'Failed to match fingerprint')
|
||||||
|
|
||||||
|
def test_pam_already_claimed(self):
|
||||||
|
self.setup_device()
|
||||||
|
script = [
|
||||||
|
( 'verify-match', True, 2 )
|
||||||
|
]
|
||||||
|
self.device_mock.SetVerifyScript(script)
|
||||||
|
self.device_mock.SetClaimed('toto')
|
||||||
|
|
||||||
|
tc = pypamtest.TestCase(pypamtest.PAMTEST_AUTHENTICATE, expected_rv=PAM_AUTHINFO_UNAVAIL)
|
||||||
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
|
|
||||||
|
self.assertEqual(len(res.info), 0)
|
||||||
|
self.assertEqual(len(res.errors), 0)
|
||||||
|
|
||||||
def test_pam_timeout(self):
|
def test_pam_timeout(self):
|
||||||
self.setup_device()
|
self.setup_device()
|
||||||
|
|
||||||
@ -198,6 +277,19 @@ class TestPamFprintd(dbusmock.DBusTestCase):
|
|||||||
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
res = pypamtest.run_pamtest("toto", "fprintd-pam-test", [tc], [ 'unused' ])
|
||||||
self.assertRegex(res.info[1], r'Verification timed out')
|
self.assertRegex(res.info[1], r'Verification timed out')
|
||||||
|
|
||||||
|
def test_pam_notices_fprintd_disappearing(self):
|
||||||
|
self.setup_device()
|
||||||
|
|
||||||
|
script = [
|
||||||
|
( 'MOCK: quit', True, 0 ),
|
||||||
|
]
|
||||||
|
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.assertEqual(len(res.errors), 0)
|
||||||
|
self.assertEqual(len(res.info), 0)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if 'PAM_WRAPPER_SERVICE_DIR' not in os.environ:
|
if 'PAM_WRAPPER_SERVICE_DIR' not in os.environ:
|
||||||
print('Cannot run test without environment set correctly, run "meson test" instead')
|
print('Cannot run test without environment set correctly, run "meson test" instead')
|
||||||
|
|||||||
@ -18,9 +18,9 @@ import subprocess
|
|||||||
import dbus
|
import dbus
|
||||||
import dbus.mainloop.glib
|
import dbus.mainloop.glib
|
||||||
import dbusmock
|
import dbusmock
|
||||||
import fcntl
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
from output_checker import OutputChecker
|
||||||
|
|
||||||
|
|
||||||
VALID_FINGER_NAMES = [
|
VALID_FINGER_NAMES = [
|
||||||
@ -77,10 +77,8 @@ class TestFprintdUtilsBase(dbusmock.DBusTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
(self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
|
(self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
|
||||||
self.template_name, {}, stdout=subprocess.PIPE)
|
self.template_name, {})
|
||||||
# set log to nonblocking
|
# set log to nonblocking
|
||||||
flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL)
|
|
||||||
fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
self.obj_fprintd_mock = dbus.Interface(self.obj_fprintd_manager, 'net.reactivated.Fprint.Manager.Mock')
|
self.obj_fprintd_mock = dbus.Interface(self.obj_fprintd_manager, 'net.reactivated.Fprint.Manager.Mock')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -102,22 +100,21 @@ class TestFprintdUtilsBase(dbusmock.DBusTestCase):
|
|||||||
|
|
||||||
def start_utility_process(self, utility_name, args=[], sleep=True):
|
def start_utility_process(self, utility_name, args=[], sleep=True):
|
||||||
utility = [ os.path.join(self.tools_prefix, 'fprintd-{}'.format(utility_name)) ]
|
utility = [ os.path.join(self.tools_prefix, 'fprintd-{}'.format(utility_name)) ]
|
||||||
|
output = OutputChecker()
|
||||||
process = subprocess.Popen(self.wrapper_args + utility + args,
|
process = subprocess.Popen(self.wrapper_args + utility + args,
|
||||||
stdout=subprocess.PIPE,
|
stdout=output.fd,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT)
|
||||||
universal_newlines=True)
|
output.writer_attached()
|
||||||
flags = fcntl.fcntl(process.stdout, fcntl.F_GETFL)
|
|
||||||
fcntl.fcntl(process.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
|
|
||||||
|
self.addCleanup(output.assert_closed)
|
||||||
self.addCleanup(self.try_stop_utility_process, process)
|
self.addCleanup(self.try_stop_utility_process, process)
|
||||||
|
|
||||||
if sleep:
|
if sleep:
|
||||||
time.sleep(self.sleep_time)
|
time.sleep(self.sleep_time)
|
||||||
|
|
||||||
return process
|
return process, output
|
||||||
|
|
||||||
def stop_utility_process(self, process):
|
def stop_utility_process(self, process):
|
||||||
print(process.stdout.read())
|
|
||||||
process.terminate()
|
process.terminate()
|
||||||
process.wait()
|
process.wait()
|
||||||
|
|
||||||
@ -127,17 +124,12 @@ class TestFprintdUtilsBase(dbusmock.DBusTestCase):
|
|||||||
except:
|
except:
|
||||||
pass
|
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):
|
def run_utility_process(self, utility_name, args=[], sleep=True, timeout=None):
|
||||||
proc = self.start_utility_process(utility_name, args=args, sleep=sleep)
|
proc, output = 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)
|
ret = proc.wait(timeout=timeout if timeout is not None else self.sleep_time * 4)
|
||||||
self.assertLessEqual(ret, 128)
|
self.assertLessEqual(ret, 128)
|
||||||
|
|
||||||
return self.get_process_output(proc), ret
|
return b''.join(output.clear()), ret
|
||||||
|
|
||||||
|
|
||||||
class TestFprintdUtils(TestFprintdUtilsBase):
|
class TestFprintdUtils(TestFprintdUtilsBase):
|
||||||
@ -146,65 +138,62 @@ class TestFprintdUtils(TestFprintdUtilsBase):
|
|||||||
self.setup_device()
|
self.setup_device()
|
||||||
|
|
||||||
def test_fprintd_enroll(self):
|
def test_fprintd_enroll(self):
|
||||||
process = self.start_utility_process('enroll', ['-f', 'right-index-finger', 'toto'])
|
process, out = self.start_utility_process('enroll', ['-f', 'right-index-finger', 'toto'])
|
||||||
|
|
||||||
out = self.get_process_output(process)
|
out.check_line(rb'right-index-finger', 0)
|
||||||
self.assertRegex(out, r'right-index-finger')
|
|
||||||
|
|
||||||
self.device_mock.EmitEnrollStatus('enroll-completed', True)
|
self.device_mock.EmitEnrollStatus('enroll-completed', True)
|
||||||
time.sleep(self.sleep_time)
|
|
||||||
|
|
||||||
out = self.get_process_output(process)
|
out.check_line(rb'Enroll result: enroll-completed', self.sleep_time)
|
||||||
self.assertRegex(out, 'Enroll result: enroll-completed')
|
|
||||||
|
|
||||||
def test_fprintd_list(self):
|
def test_fprintd_list(self):
|
||||||
# Rick has no fingerprints enrolled
|
# Rick has no fingerprints enrolled
|
||||||
out, ret = self.run_utility_process('list', ['rick'])
|
out, ret = self.run_utility_process('list', ['rick'])
|
||||||
self.assertRegex(out, r'has no fingers enrolled for')
|
self.assertRegex(out, rb'has no fingers enrolled for')
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
|
|
||||||
# Toto does
|
# Toto does
|
||||||
out, ret = self.run_utility_process('list', ['toto'])
|
out, ret = self.run_utility_process('list', ['toto'])
|
||||||
self.assertRegex(out, r'right-little-finger')
|
self.assertRegex(out, rb'right-little-finger')
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
|
|
||||||
def test_fprintd_delete(self):
|
def test_fprintd_delete(self):
|
||||||
# Has fingerprints enrolled
|
# Has fingerprints enrolled
|
||||||
out, ret = self.run_utility_process('list', ['toto'])
|
out, ret = self.run_utility_process('list', ['toto'])
|
||||||
self.assertRegex(out, r'left-little-finger')
|
self.assertRegex(out, rb'left-little-finger')
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
self.assertRegex(out, r'right-little-finger')
|
self.assertRegex(out, rb'right-little-finger')
|
||||||
|
|
||||||
# Delete fingerprints
|
# Delete fingerprints
|
||||||
out, ret = self.run_utility_process('delete', ['toto'])
|
out, ret = self.run_utility_process('delete', ['toto'])
|
||||||
self.assertRegex(out, r'Fingerprints deleted')
|
self.assertRegex(out, rb'Fingerprints deleted')
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
|
|
||||||
# Doesn't have fingerprints
|
# Doesn't have fingerprints
|
||||||
out, ret = self.run_utility_process('list', ['toto'])
|
out, ret = self.run_utility_process('list', ['toto'])
|
||||||
self.assertRegex(out, r'has no fingers enrolled for')
|
self.assertRegex(out, rb'has no fingers enrolled for')
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
|
|
||||||
|
|
||||||
class TestFprintdUtilsNoDeviceTests(TestFprintdUtilsBase):
|
class TestFprintdUtilsNoDeviceTests(TestFprintdUtilsBase):
|
||||||
def test_fprintd_enroll(self):
|
def test_fprintd_enroll(self):
|
||||||
out, ret = self.run_utility_process('enroll', ['toto'])
|
out, ret = self.run_utility_process('enroll', ['toto'])
|
||||||
self.assertIn('No devices available', out)
|
self.assertIn(b'No devices available', out)
|
||||||
self.assertEqual(ret, 1)
|
self.assertEqual(ret, 1)
|
||||||
|
|
||||||
def test_fprintd_list(self):
|
def test_fprintd_list(self):
|
||||||
out, ret = self.run_utility_process('list', ['toto'])
|
out, ret = self.run_utility_process('list', ['toto'])
|
||||||
self.assertIn('No devices available', out)
|
self.assertIn(b'No devices available', out)
|
||||||
self.assertEqual(ret, 1)
|
self.assertEqual(ret, 1)
|
||||||
|
|
||||||
def test_fprintd_delete(self):
|
def test_fprintd_delete(self):
|
||||||
out, ret = self.run_utility_process('delete', ['toto'])
|
out, ret = self.run_utility_process('delete', ['toto'])
|
||||||
self.assertIn('No devices available', out)
|
self.assertIn(b'No devices available', out)
|
||||||
self.assertEqual(ret, 1)
|
self.assertEqual(ret, 1)
|
||||||
|
|
||||||
def test_fprintd_verify(self):
|
def test_fprintd_verify(self):
|
||||||
out, ret = self.run_utility_process('verify', ['toto'])
|
out, ret = self.run_utility_process('verify', ['toto'])
|
||||||
self.assertIn('No devices available', out)
|
self.assertIn(b'No devices available', out)
|
||||||
self.assertEqual(ret, 1)
|
self.assertEqual(ret, 1)
|
||||||
|
|
||||||
|
|
||||||
@ -213,24 +202,20 @@ class TestFprintdUtilsVerify(TestFprintdUtilsBase):
|
|||||||
super().setUp()
|
super().setUp()
|
||||||
self.setup_device()
|
self.setup_device()
|
||||||
|
|
||||||
def start_verify_process(self, user='toto', finger=None, checkEnrolled=True):
|
def start_verify_process(self, user='toto', finger=None, nowait=False):
|
||||||
args = [user]
|
args = [user]
|
||||||
if finger:
|
if finger:
|
||||||
args += ['-f', finger]
|
args += ['-f', finger]
|
||||||
|
|
||||||
self.process = self.start_utility_process('verify', args)
|
self.process, self.output = self.start_utility_process('verify', args)
|
||||||
out = self.get_process_output(self.process)
|
if nowait:
|
||||||
|
return
|
||||||
|
|
||||||
self.assertNotRegex(out, r'Device already in use by [A-z]+')
|
preamble = self.output.check_line(b'Verify started!')
|
||||||
self.assertNotIn('Verify result:', out)
|
|
||||||
|
|
||||||
if checkEnrolled and finger:
|
out = b''.join(preamble)
|
||||||
self.assertNotIn('''Finger '{}' not enrolled for user {}'''.format(
|
|
||||||
finger, user), out)
|
|
||||||
|
|
||||||
if checkEnrolled:
|
self.assertNotIn(b'Verify result:', out)
|
||||||
for f in self.enrolled_fingers:
|
|
||||||
self.assertIn(f, out)
|
|
||||||
|
|
||||||
if finger:
|
if finger:
|
||||||
expected_finger = finger
|
expected_finger = finger
|
||||||
@ -239,9 +224,8 @@ class TestFprintdUtilsVerify(TestFprintdUtilsBase):
|
|||||||
self.assertEqual(self.device_mock.GetSelectedFinger(), expected_finger)
|
self.assertEqual(self.device_mock.GetSelectedFinger(), expected_finger)
|
||||||
|
|
||||||
def assertVerifyMatch(self, match):
|
def assertVerifyMatch(self, match):
|
||||||
self.assertIn('Verify result: {} (done)'.format(
|
self.output.check_line(r'Verify result: {} (done)'.format(
|
||||||
'verify-match' if match else 'verify-no-match'),
|
'verify-match' if match else 'verify-no-match'))
|
||||||
self.get_process_output(self.process))
|
|
||||||
|
|
||||||
def test_fprintd_verify(self):
|
def test_fprintd_verify(self):
|
||||||
self.start_verify_process()
|
self.start_verify_process()
|
||||||
@ -280,14 +264,16 @@ class TestFprintdUtilsVerify(TestFprintdUtilsBase):
|
|||||||
|
|
||||||
def test_fprintd_verify_not_enrolled_fingers(self):
|
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]:
|
for finger in [f for f in VALID_FINGER_NAMES if f not in self.enrolled_fingers]:
|
||||||
|
self.start_verify_process(finger=finger, nowait=True)
|
||||||
regex = r'Finger \'{}\' not enrolled'.format(finger)
|
regex = r'Finger \'{}\' not enrolled'.format(finger)
|
||||||
with self.assertRaisesRegex(AssertionError, regex):
|
self.output.check_line_re(regex, timeout=self.sleep_time)
|
||||||
self.start_verify_process(finger=finger)
|
|
||||||
self.device_mock.Release()
|
self.device_mock.Release()
|
||||||
|
|
||||||
def test_fprintd_verify_no_enrolled_fingers(self):
|
def test_fprintd_verify_no_enrolled_fingers(self):
|
||||||
self.set_enrolled_fingers([])
|
self.set_enrolled_fingers([])
|
||||||
self.start_verify_process()
|
self.start_verify_process(nowait=True)
|
||||||
|
self.output.check_line(b'No fingers enrolled for this device.', timeout=self.sleep_time)
|
||||||
self.assertEqual(self.process.poll(), 1)
|
self.assertEqual(self.process.poll(), 1)
|
||||||
|
|
||||||
def test_fprintd_list_all_fingers(self):
|
def test_fprintd_list_all_fingers(self):
|
||||||
@ -299,16 +285,17 @@ class TestFprintdUtilsVerify(TestFprintdUtilsBase):
|
|||||||
( 'verify-match', True, 2 )
|
( 'verify-match', True, 2 )
|
||||||
]
|
]
|
||||||
self.device_mock.SetVerifyScript(script)
|
self.device_mock.SetVerifyScript(script)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
self.start_verify_process()
|
self.start_verify_process()
|
||||||
time.sleep(self.sleep_time * 4)
|
time.sleep(2 + self.sleep_time)
|
||||||
self.assertVerifyMatch(True)
|
self.assertVerifyMatch(True)
|
||||||
|
|
||||||
def test_fprintd_multiple_verify_fails(self):
|
def test_fprintd_multiple_verify_fails(self):
|
||||||
self.start_verify_process()
|
self.start_verify_process()
|
||||||
|
|
||||||
with self.assertRaisesRegex(AssertionError, r'Device already in use'):
|
self.start_verify_process(nowait=True)
|
||||||
self.start_verify_process()
|
self.output.check_line_re(rb'Device already in use by [A-z]+', timeout=self.sleep_time)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# avoid writing to stderr
|
# avoid writing to stderr
|
||||||
|
|||||||
216
utils/delete.c
216
utils/delete.c
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -26,126 +26,146 @@
|
|||||||
static FprintDBusManager *manager = NULL;
|
static FprintDBusManager *manager = NULL;
|
||||||
static GDBusConnection *connection = NULL;
|
static GDBusConnection *connection = NULL;
|
||||||
|
|
||||||
static void create_manager(void)
|
static void
|
||||||
|
create_manager (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
if (connection == NULL) {
|
if (connection == NULL)
|
||||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to connect to session bus: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
"/net/reactivated/Fprint/Manager",
|
"/net/reactivated/Fprint/Manager",
|
||||||
NULL, &error);
|
NULL, &error);
|
||||||
if (manager == NULL) {
|
if (manager == NULL)
|
||||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_fingerprints (FprintDBusDevice *dev, const char *username)
|
static void
|
||||||
|
delete_fingerprints (FprintDBusDevice *dev, const char *username)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error)) {
|
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error))
|
||||||
g_print("failed to claim device: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("failed to claim device: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_delete_enrolled_fingers2_sync (dev, NULL,
|
if (!fprint_dbus_device_call_delete_enrolled_fingers2_sync (dev, NULL,
|
||||||
&error)) {
|
&error))
|
||||||
gboolean ignore_error = FALSE;
|
{
|
||||||
if (g_dbus_error_is_remote_error (error)) {
|
gboolean ignore_error = FALSE;
|
||||||
g_autofree char *dbus_error =
|
if (g_dbus_error_is_remote_error (error))
|
||||||
g_dbus_error_get_remote_error (error);
|
{
|
||||||
if (g_str_equal (dbus_error,
|
g_autofree char *dbus_error =
|
||||||
"net.reactivated.Fprint.Error.NoEnrolledPrints")) {
|
g_dbus_error_get_remote_error (error);
|
||||||
g_print ("No fingerprints to delete on %s\n",
|
if (g_str_equal (dbus_error,
|
||||||
fprint_dbus_device_get_name (dev));
|
"net.reactivated.Fprint.Error.NoEnrolledPrints"))
|
||||||
ignore_error = TRUE;
|
{
|
||||||
}
|
g_print ("No fingerprints to delete on %s\n",
|
||||||
}
|
fprint_dbus_device_get_name (dev));
|
||||||
if (!ignore_error) {
|
ignore_error = TRUE;
|
||||||
g_print("ListEnrolledFingers failed: %s\n",
|
}
|
||||||
error->message);
|
}
|
||||||
exit (1);
|
if (!ignore_error)
|
||||||
} else {
|
{
|
||||||
g_print ("No fingerprints to delete on %s\n",
|
g_print ("ListEnrolledFingers failed: %s\n",
|
||||||
fprint_dbus_device_get_name (dev));
|
error->message);
|
||||||
}
|
exit (1);
|
||||||
} else {
|
}
|
||||||
g_print ("Fingerprints deleted on %s\n",
|
else
|
||||||
fprint_dbus_device_get_name (dev));
|
{
|
||||||
}
|
g_print ("No fingerprints to delete on %s\n",
|
||||||
g_clear_error (&error);
|
fprint_dbus_device_get_name (dev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_print ("Fingerprints deleted on %s\n",
|
||||||
|
fprint_dbus_device_get_name (dev));
|
||||||
|
}
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error)) {
|
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error))
|
||||||
g_print("ReleaseDevice failed: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("ReleaseDevice failed: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_devices(char **argv)
|
static void
|
||||||
|
process_devices (char **argv)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_auto(GStrv) devices = NULL;
|
g_auto(GStrv) devices = NULL;
|
||||||
char *path;
|
char *path;
|
||||||
guint num_devices;
|
guint num_devices;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
if (!fprint_dbus_manager_call_get_devices_sync (manager, &devices,
|
if (!fprint_dbus_manager_call_get_devices_sync (manager, &devices,
|
||||||
NULL, &error)) {
|
NULL, &error))
|
||||||
g_print("Impossible to get devices: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Impossible to get devices: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
num_devices = g_strv_length (devices);
|
num_devices = g_strv_length (devices);
|
||||||
if (num_devices == 0) {
|
if (num_devices == 0)
|
||||||
g_print("No devices available\n");
|
{
|
||||||
exit(1);
|
g_print ("No devices available\n");
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
g_print ("found %u devices\n", num_devices);
|
g_print ("found %u devices\n", num_devices);
|
||||||
for (i = 0; devices[i] != NULL; i++) {
|
for (i = 0; devices[i] != NULL; i++)
|
||||||
path = devices[i];
|
{
|
||||||
g_print("Device at %s\n", path);
|
path = devices[i];
|
||||||
}
|
g_print ("Device at %s\n", path);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; devices[i] != NULL; i++) {
|
for (i = 0; devices[i] != NULL; i++)
|
||||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
{
|
||||||
guint j;
|
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||||
|
guint j;
|
||||||
|
|
||||||
path = devices[i];
|
path = devices[i];
|
||||||
g_print("Using device %s\n", path);
|
g_print ("Using device %s\n", path);
|
||||||
|
|
||||||
/* NOTE: We should handle error cases! */
|
/* NOTE: We should handle error cases! */
|
||||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
path, NULL, NULL);
|
path, NULL, NULL);
|
||||||
|
|
||||||
for (j = 1; argv[j] != NULL; j++)
|
for (j = 1; argv[j] != NULL; j++)
|
||||||
delete_fingerprints (dev, argv[j]);
|
delete_fingerprints (dev, argv[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
create_manager();
|
create_manager ();
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2)
|
||||||
g_print ("Usage: %s <username> [usernames...]\n", argv[0]);
|
{
|
||||||
return 1;
|
g_print ("Usage: %s <username> [usernames...]\n", argv[0]);
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
process_devices (argv);
|
process_devices (argv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
274
utils/enroll.c
274
utils/enroll.c
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -33,171 +33,193 @@ static GDBusConnection *connection = NULL;
|
|||||||
static char *finger_name = NULL;
|
static char *finger_name = NULL;
|
||||||
static char **usernames = NULL;
|
static char **usernames = NULL;
|
||||||
|
|
||||||
static void create_manager(void)
|
static void
|
||||||
|
create_manager (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
if (connection == NULL) {
|
if (connection == NULL)
|
||||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to connect to session bus: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
"/net/reactivated/Fprint/Manager",
|
"/net/reactivated/Fprint/Manager",
|
||||||
NULL, &error);
|
NULL, &error);
|
||||||
if (manager == NULL) {
|
if (manager == NULL)
|
||||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FprintDBusDevice *open_device (const char *username)
|
static FprintDBusDevice *
|
||||||
|
open_device (const char *username)
|
||||||
{
|
{
|
||||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autofree char *path = NULL;
|
g_autofree char *path = NULL;
|
||||||
|
|
||||||
if (!fprint_dbus_manager_call_get_default_device_sync (manager, &path,
|
if (!fprint_dbus_manager_call_get_default_device_sync (manager, &path,
|
||||||
NULL, &error)) {
|
NULL, &error))
|
||||||
g_print("Impossible to enroll: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Impossible to enroll: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
g_print("Using device %s\n", path);
|
g_print ("Using device %s\n", path);
|
||||||
|
|
||||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
path, NULL, &error);
|
path, NULL, &error);
|
||||||
|
|
||||||
if (error) {
|
if (error)
|
||||||
g_print ("failed to connect to device: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("failed to connect to device: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error)) {
|
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error))
|
||||||
g_print("failed to claim device: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("failed to claim device: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
return g_steal_pointer (&dev);
|
}
|
||||||
|
return g_steal_pointer (&dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enroll_result(GObject *object, const char *result, gboolean done, void *user_data)
|
static void
|
||||||
|
enroll_result (GObject *object, const char *result, gboolean done, void *user_data)
|
||||||
{
|
{
|
||||||
gboolean *enroll_completed = user_data;
|
gboolean *enroll_completed = user_data;
|
||||||
g_print("Enroll result: %s\n", result);
|
|
||||||
if (done != FALSE)
|
g_print ("Enroll result: %s\n", result);
|
||||||
*enroll_completed = TRUE;
|
if (done != FALSE)
|
||||||
|
*enroll_completed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proxy_signal_cb (GDBusProxy *proxy,
|
static void
|
||||||
const gchar *sender_name,
|
proxy_signal_cb (GDBusProxy *proxy,
|
||||||
const gchar *signal_name,
|
const gchar *sender_name,
|
||||||
GVariant *parameters,
|
const gchar *signal_name,
|
||||||
gpointer user_data)
|
GVariant *parameters,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
if (g_str_equal (signal_name, "EnrollStatus")) {
|
if (g_str_equal (signal_name, "EnrollStatus"))
|
||||||
const gchar *result;
|
{
|
||||||
gboolean done;
|
const gchar *result;
|
||||||
|
gboolean done;
|
||||||
|
|
||||||
g_variant_get (parameters, "(&sb)", &result, &done);
|
g_variant_get (parameters, "(&sb)", &result, &done);
|
||||||
enroll_result (G_OBJECT (proxy), result, done, user_data);
|
enroll_result (G_OBJECT (proxy), result, done, user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_enroll (FprintDBusDevice *dev)
|
static void
|
||||||
|
do_enroll (FprintDBusDevice *dev)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
gboolean enroll_completed = FALSE;
|
gboolean enroll_completed = FALSE;
|
||||||
gboolean found;
|
gboolean found;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
g_signal_connect (dev, "g-signal", G_CALLBACK (proxy_signal_cb),
|
g_signal_connect (dev, "g-signal", G_CALLBACK (proxy_signal_cb),
|
||||||
&enroll_completed);
|
&enroll_completed);
|
||||||
|
|
||||||
found = FALSE;
|
found = FALSE;
|
||||||
for (i = 0; fingers[i].dbus_name != NULL; i++) {
|
for (i = 0; fingers[i].dbus_name != NULL; i++)
|
||||||
if (g_strcmp0 (fingers[i].dbus_name, finger_name) == 0) {
|
{
|
||||||
found = TRUE;
|
if (g_strcmp0 (fingers[i].dbus_name, finger_name) == 0)
|
||||||
break;
|
{
|
||||||
}
|
found = TRUE;
|
||||||
}
|
break;
|
||||||
if (!found) {
|
}
|
||||||
g_autoptr(GString) s = NULL;
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
g_autoptr(GString) s = NULL;
|
||||||
|
|
||||||
s = g_string_new (NULL);
|
s = g_string_new (NULL);
|
||||||
g_string_append_printf (s, "Invalid finger name '%s'. Name must be one of ", finger_name);
|
g_string_append_printf (s, "Invalid finger name '%s'. Name must be one of ", finger_name);
|
||||||
for (i = 0; fingers[i].dbus_name != NULL; i++) {
|
for (i = 0; fingers[i].dbus_name != NULL; i++)
|
||||||
g_string_append_printf (s, "%s", fingers[i].dbus_name);
|
{
|
||||||
if (fingers[i + 1].dbus_name != NULL)
|
g_string_append_printf (s, "%s", fingers[i].dbus_name);
|
||||||
g_string_append (s, ", ");
|
if (fingers[i + 1].dbus_name != NULL)
|
||||||
}
|
g_string_append (s, ", ");
|
||||||
g_warning ("%s", s->str);
|
}
|
||||||
exit (1);
|
g_warning ("%s", s->str);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
g_print("Enrolling %s finger.\n", finger_name);
|
g_print ("Enrolling %s finger.\n", finger_name);
|
||||||
if (!fprint_dbus_device_call_enroll_start_sync (dev, finger_name, NULL,
|
if (!fprint_dbus_device_call_enroll_start_sync (dev, finger_name, NULL,
|
||||||
&error)) {
|
&error))
|
||||||
g_print("EnrollStart failed: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("EnrollStart failed: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
while (!enroll_completed)
|
while (!enroll_completed)
|
||||||
g_main_context_iteration(NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb, &enroll_result);
|
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb, &enroll_result);
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_enroll_stop_sync (dev, NULL, &error)) {
|
if (!fprint_dbus_device_call_enroll_stop_sync (dev, NULL, &error))
|
||||||
g_print("VerifyStop failed: %s\n", error->message);
|
{
|
||||||
exit(1);
|
g_print ("VerifyStop failed: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_device (FprintDBusDevice *dev)
|
static void
|
||||||
|
release_device (FprintDBusDevice *dev)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error)) {
|
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error))
|
||||||
g_print("ReleaseDevice failed: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("ReleaseDevice failed: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GOptionEntry entries[] = {
|
static const GOptionEntry entries[] = {
|
||||||
{ "finger", 'f', 0, G_OPTION_ARG_STRING, &finger_name, "Finger selected to verify (default is automatic)", NULL },
|
{ "finger", 'f', 0, G_OPTION_ARG_STRING, &finger_name, "Finger selected to verify (default is automatic)", NULL },
|
||||||
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &usernames, NULL, "[username]" },
|
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &usernames, NULL, "[username]" },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
g_autoptr(GError) err = NULL;
|
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
g_autoptr(GError) err = NULL;
|
||||||
|
|
||||||
context = g_option_context_new ("Enroll a fingerprint");
|
setlocale (LC_ALL, "");
|
||||||
g_option_context_add_main_entries (context, entries, NULL);
|
|
||||||
|
|
||||||
if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
|
context = g_option_context_new ("Enroll a fingerprint");
|
||||||
g_print ("couldn't parse command-line options: %s\n", err->message);
|
g_option_context_add_main_entries (context, entries, NULL);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finger_name == NULL)
|
if (g_option_context_parse (context, &argc, &argv, &err) == FALSE)
|
||||||
finger_name = g_strdup("right-index-finger");
|
{
|
||||||
|
g_print ("couldn't parse command-line options: %s\n", err->message);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
create_manager();
|
if (finger_name == NULL)
|
||||||
|
finger_name = g_strdup ("right-index-finger");
|
||||||
|
|
||||||
dev = open_device (usernames ? usernames[0] : "");
|
create_manager ();
|
||||||
do_enroll(dev);
|
|
||||||
release_device(dev);
|
dev = open_device (usernames ? usernames[0] : "");
|
||||||
g_free(finger_name);
|
do_enroll (dev);
|
||||||
g_strfreev(usernames);
|
release_device (dev);
|
||||||
return 0;
|
g_free (finger_name);
|
||||||
|
g_strfreev (usernames);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
202
utils/list.c
202
utils/list.c
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -26,125 +26,137 @@
|
|||||||
static FprintDBusManager *manager = NULL;
|
static FprintDBusManager *manager = NULL;
|
||||||
static GDBusConnection *connection = NULL;
|
static GDBusConnection *connection = NULL;
|
||||||
|
|
||||||
static void create_manager(void)
|
static void
|
||||||
|
create_manager (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
if (connection == NULL) {
|
if (connection == NULL)
|
||||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to connect to session bus: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
"/net/reactivated/Fprint/Manager",
|
"/net/reactivated/Fprint/Manager",
|
||||||
NULL, &error);
|
NULL, &error);
|
||||||
if (manager == NULL) {
|
if (manager == NULL)
|
||||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_fingerprints (FprintDBusDevice *dev, const char *username)
|
static void
|
||||||
|
list_fingerprints (FprintDBusDevice *dev, const char *username)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_auto(GStrv) fingers = NULL;
|
g_auto(GStrv) fingers = NULL;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_list_enrolled_fingers_sync (dev, username,
|
if (!fprint_dbus_device_call_list_enrolled_fingers_sync (dev, username,
|
||||||
&fingers, NULL,
|
&fingers, NULL,
|
||||||
&error)) {
|
&error))
|
||||||
gboolean ignore_error = FALSE;
|
{
|
||||||
if (g_dbus_error_is_remote_error (error)) {
|
gboolean ignore_error = FALSE;
|
||||||
g_autofree char *dbus_error =
|
if (g_dbus_error_is_remote_error (error))
|
||||||
g_dbus_error_get_remote_error (error);
|
{
|
||||||
if (g_str_equal (dbus_error,
|
g_autofree char *dbus_error =
|
||||||
"net.reactivated.Fprint.Error.NoEnrolledPrints")) {
|
g_dbus_error_get_remote_error (error);
|
||||||
ignore_error = TRUE;
|
if (g_str_equal (dbus_error,
|
||||||
}
|
"net.reactivated.Fprint.Error.NoEnrolledPrints"))
|
||||||
}
|
ignore_error = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ignore_error) {
|
if (!ignore_error)
|
||||||
g_print("ListEnrolledFingers failed: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("ListEnrolledFingers failed: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fingers == NULL || g_strv_length (fingers) == 0) {
|
if (fingers == NULL || g_strv_length (fingers) == 0)
|
||||||
g_print ("User %s has no fingers enrolled for %s.\n", username,
|
{
|
||||||
fprint_dbus_device_get_name (dev));
|
g_print ("User %s has no fingers enrolled for %s.\n", username,
|
||||||
return;
|
fprint_dbus_device_get_name (dev));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
g_print("Fingerprints for user %s on %s (%s):\n",
|
g_print ("Fingerprints for user %s on %s (%s):\n",
|
||||||
username,
|
username,
|
||||||
fprint_dbus_device_get_name (dev),
|
fprint_dbus_device_get_name (dev),
|
||||||
fprint_dbus_device_get_scan_type (dev));
|
fprint_dbus_device_get_scan_type (dev));
|
||||||
|
|
||||||
for (i = 0; fingers[i] != NULL; i++) {
|
for (i = 0; fingers[i] != NULL; i++)
|
||||||
g_print(" - #%d: %s\n", i, fingers[i]);
|
g_print (" - #%d: %s\n", i, fingers[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_devices(char **argv)
|
static void
|
||||||
|
process_devices (char **argv)
|
||||||
{
|
{
|
||||||
g_auto(GStrv) devices = NULL;
|
g_auto(GStrv) devices = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
char *path;
|
char *path;
|
||||||
guint num_devices;
|
guint num_devices;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
if (!fprint_dbus_manager_call_get_devices_sync (manager, &devices, NULL,
|
if (!fprint_dbus_manager_call_get_devices_sync (manager, &devices, NULL,
|
||||||
&error)) {
|
&error))
|
||||||
g_print("Impossible to get devices: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Impossible to get devices: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
num_devices = g_strv_length (devices);
|
num_devices = g_strv_length (devices);
|
||||||
if (num_devices == 0) {
|
if (num_devices == 0)
|
||||||
g_print("No devices available\n");
|
{
|
||||||
exit(1);
|
g_print ("No devices available\n");
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
g_print ("found %u devices\n", num_devices);
|
g_print ("found %u devices\n", num_devices);
|
||||||
for (i = 0; devices[i] != NULL; i++) {
|
for (i = 0; devices[i] != NULL; i++)
|
||||||
path = devices[i];
|
{
|
||||||
g_print("Device at %s\n", path);
|
path = devices[i];
|
||||||
}
|
g_print ("Device at %s\n", path);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; devices[i] != NULL; i++) {
|
for (i = 0; devices[i] != NULL; i++)
|
||||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
{
|
||||||
guint j;
|
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||||
|
guint j;
|
||||||
|
|
||||||
path = devices[i];
|
path = devices[i];
|
||||||
g_print("Using device %s\n", path);
|
g_print ("Using device %s\n", path);
|
||||||
|
|
||||||
/* NOTE: We should handle error cases! */
|
/* NOTE: We should handle error cases! */
|
||||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
path, NULL, NULL);
|
path, NULL, NULL);
|
||||||
|
|
||||||
for (j = 1; argv[j] != NULL; j++)
|
for (j = 1; argv[j] != NULL; j++)
|
||||||
list_fingerprints (dev, argv[j]);
|
list_fingerprints (dev, argv[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
create_manager();
|
create_manager ();
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2)
|
||||||
g_print ("Usage: %s <username> [usernames...]\n", argv[0]);
|
{
|
||||||
return 1;
|
g_print ("Usage: %s <username> [usernames...]\n", argv[0]);
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
process_devices (argv);
|
process_devices (argv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
372
utils/verify.c
372
utils/verify.c
@ -7,12 +7,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
@ -31,208 +31,276 @@ static char *finger_name = NULL;
|
|||||||
static gboolean g_fatal_warnings = FALSE;
|
static gboolean g_fatal_warnings = FALSE;
|
||||||
static char **usernames = NULL;
|
static char **usernames = NULL;
|
||||||
|
|
||||||
static void create_manager(void)
|
static void
|
||||||
|
create_manager (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
if (connection == NULL) {
|
if (connection == NULL)
|
||||||
g_print("Failed to connect to session bus: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to connect to session bus: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
manager = fprint_dbus_manager_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
"/net/reactivated/Fprint/Manager",
|
"/net/reactivated/Fprint/Manager",
|
||||||
NULL, &error);
|
NULL, &error);
|
||||||
if (manager == NULL) {
|
if (manager == NULL)
|
||||||
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Failed to get Fprintd manager: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FprintDBusDevice *open_device (const char *username)
|
static FprintDBusDevice *
|
||||||
|
open_device (const char *username)
|
||||||
{
|
{
|
||||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autofree char *path = NULL;
|
g_autofree char *path = NULL;
|
||||||
|
|
||||||
if (!fprint_dbus_manager_call_get_default_device_sync (manager, &path,
|
if (!fprint_dbus_manager_call_get_default_device_sync (manager, &path,
|
||||||
NULL, &error)) {
|
NULL, &error))
|
||||||
g_print("Impossible to verify: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("Impossible to verify: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
g_print("Using device %s\n", path);
|
g_print ("Using device %s\n", path);
|
||||||
|
|
||||||
dev = fprint_dbus_device_proxy_new_sync (connection,
|
dev = fprint_dbus_device_proxy_new_sync (connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
path, NULL, &error);
|
path, NULL, &error);
|
||||||
|
|
||||||
if (error) {
|
if (error)
|
||||||
g_print ("failed to connect to device: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("failed to connect to device: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error)) {
|
if (!fprint_dbus_device_call_claim_sync (dev, username, NULL, &error))
|
||||||
g_print("failed to claim device: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("failed to claim device: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
return g_steal_pointer (&dev);
|
return g_steal_pointer (&dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void find_finger (FprintDBusDevice *dev, const char *username)
|
static void
|
||||||
|
find_finger (FprintDBusDevice *dev, const char *username)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_auto(GStrv) fingers = NULL;
|
g_auto(GStrv) fingers = NULL;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_list_enrolled_fingers_sync (dev, username,
|
if (!fprint_dbus_device_call_list_enrolled_fingers_sync (dev, username,
|
||||||
&fingers,
|
&fingers,
|
||||||
NULL, &error)) {
|
NULL, &error))
|
||||||
g_print("ListEnrolledFingers failed: %s\n", error->message);
|
{
|
||||||
exit (1);
|
g_print ("ListEnrolledFingers failed: %s\n", error->message);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (fingers == NULL || g_strv_length (fingers) == 0) {
|
if (fingers == NULL || g_strv_length (fingers) == 0)
|
||||||
g_print("No fingers enrolled for this device.\n");
|
{
|
||||||
exit(1);
|
g_print ("No fingers enrolled for this device.\n");
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
g_print("Listing enrolled fingers:\n");
|
g_print ("Listing enrolled fingers:\n");
|
||||||
for (i = 0; fingers[i] != NULL; i++) {
|
for (i = 0; fingers[i] != NULL; i++)
|
||||||
g_print(" - #%d: %s\n", i, fingers[i]);
|
g_print (" - #%d: %s\n", i, fingers[i]);
|
||||||
}
|
|
||||||
|
|
||||||
if (finger_name && !g_str_equal (finger_name, "any") &&
|
if (finger_name && !g_str_equal (finger_name, "any") &&
|
||||||
!g_strv_contains ((const char **) fingers, finger_name)) {
|
!g_strv_contains ((const char **) fingers, finger_name))
|
||||||
g_print("Finger '%s' not enrolled for user %s.\n", finger_name,
|
{
|
||||||
username);
|
g_print ("Finger '%s' not enrolled for user %s.\n", finger_name,
|
||||||
g_free (finger_name);
|
username);
|
||||||
exit(1);
|
g_free (finger_name);
|
||||||
}
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
if (finger_name == NULL) {
|
if (finger_name == NULL)
|
||||||
finger_name = g_strdup (fingers[0]);
|
finger_name = g_strdup (fingers[0]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_result(GObject *object, const char *result, gboolean done, void *user_data)
|
struct VerifyState
|
||||||
{
|
{
|
||||||
gboolean *verify_completed = user_data;
|
GError *error;
|
||||||
g_print("Verify result: %s (%s)\n", result, done ? "done" : "not done");
|
gboolean started;
|
||||||
if (done != FALSE)
|
gboolean completed;
|
||||||
*verify_completed = TRUE;
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
verify_result (GObject *object, const char *result, gboolean done, void *user_data)
|
||||||
|
{
|
||||||
|
struct VerifyState *verify_state = user_data;
|
||||||
|
|
||||||
|
g_print ("Verify result: %s (%s)\n", result, done ? "done" : "not done");
|
||||||
|
if (done != FALSE)
|
||||||
|
verify_state->completed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_finger_selected(GObject *object, const char *name, void *user_data)
|
static void
|
||||||
|
verify_finger_selected (GObject *object, const char *name, void *user_data)
|
||||||
{
|
{
|
||||||
g_print("Verifying: %s\n", name);
|
g_print ("Verifying: %s\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proxy_signal_cb (GDBusProxy *proxy,
|
static void
|
||||||
const gchar *sender_name,
|
verify_started_cb (GObject *obj,
|
||||||
const gchar *signal_name,
|
GAsyncResult *res,
|
||||||
GVariant *parameters,
|
gpointer user_data)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
if (g_str_equal (signal_name, "VerifyStatus")) {
|
struct VerifyState *verify_state = user_data;
|
||||||
const gchar *result;
|
|
||||||
gboolean done;
|
|
||||||
|
|
||||||
g_variant_get (parameters, "(&sb)", &result, &done);
|
if (fprint_dbus_device_call_verify_start_finish (FPRINT_DBUS_DEVICE (obj), res, &verify_state->error))
|
||||||
verify_result (G_OBJECT (proxy), result, done, user_data);
|
{
|
||||||
} else if (g_str_equal (signal_name, "VerifyFingerSelected")) {
|
g_print ("Verify started!\n");
|
||||||
const gchar *name;
|
verify_state->started = TRUE;
|
||||||
|
}
|
||||||
g_variant_get (parameters, "(&s)", &name);
|
|
||||||
verify_finger_selected (G_OBJECT (proxy), name, user_data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_verify (FprintDBusDevice *dev)
|
static void
|
||||||
|
proxy_signal_cb (GDBusProxy *proxy,
|
||||||
|
const gchar *sender_name,
|
||||||
|
const gchar *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
struct VerifyState *verify_state = user_data;
|
||||||
gboolean verify_completed = FALSE;
|
|
||||||
|
|
||||||
g_signal_connect (dev, "g-signal", G_CALLBACK (proxy_signal_cb),
|
if (!verify_state->started)
|
||||||
&verify_completed);
|
return;
|
||||||
|
|
||||||
if (!fprint_dbus_device_call_verify_start_sync (dev, finger_name, NULL,
|
if (g_str_equal (signal_name, "VerifyStatus"))
|
||||||
&error)) {
|
{
|
||||||
g_print("VerifyStart failed: %s\n", error->message);
|
const gchar *result;
|
||||||
exit (1);
|
gboolean done;
|
||||||
}
|
|
||||||
|
|
||||||
while (!verify_completed)
|
g_variant_get (parameters, "(&sb)", &result, &done);
|
||||||
g_main_context_iteration(NULL, TRUE);
|
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);
|
||||||
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb,
|
verify_finger_selected (G_OBJECT (proxy), name, user_data);
|
||||||
&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 (FprintDBusDevice *dev)
|
static void
|
||||||
|
do_verify (FprintDBusDevice *dev)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
if (!fprint_dbus_device_call_release_sync (dev, NULL, &error)) {
|
struct VerifyState verify_state = { 0 };
|
||||||
g_print("ReleaseDevice failed: %s\n", error->message);
|
|
||||||
exit (1);
|
/* This one is funny. We connect to the signal immediately to avoid
|
||||||
}
|
* race conditions. However, we must ignore any authentication results
|
||||||
|
* that happen before our start call returns.
|
||||||
|
* This is because the verify call itself may internally try to verify
|
||||||
|
* against fprintd (possibly using a separate account).
|
||||||
|
*
|
||||||
|
* To do so, we *must* use the async version of the verify call, as the
|
||||||
|
* sync version would cause the signals to be queued and only processed
|
||||||
|
* after it returns.
|
||||||
|
*/
|
||||||
|
|
||||||
|
g_signal_connect (dev, "g-signal", G_CALLBACK (proxy_signal_cb),
|
||||||
|
&verify_state);
|
||||||
|
|
||||||
|
fprint_dbus_device_call_verify_start (dev, finger_name, NULL,
|
||||||
|
verify_started_cb,
|
||||||
|
&verify_state);
|
||||||
|
|
||||||
|
/* Wait for verify start while discarding any VerifyStatus signals */
|
||||||
|
while (!verify_state.started && !verify_state.error)
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
|
||||||
|
if (verify_state.error)
|
||||||
|
{
|
||||||
|
g_print ("VerifyStart failed: %s\n", verify_state.error->message);
|
||||||
|
g_clear_error (&verify_state.error);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VerifyStatus signals are processing, wait for completion. */
|
||||||
|
while (!verify_state.completed)
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb,
|
||||||
|
&verify_state);
|
||||||
|
|
||||||
|
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 (FprintDBusDevice *dev)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GOptionEntry entries[] = {
|
static const GOptionEntry entries[] = {
|
||||||
{ "finger", 'f', 0, G_OPTION_ARG_STRING, &finger_name, "Finger selected to verify (default is automatic)", NULL },
|
{ "finger", 'f', 0, G_OPTION_ARG_STRING, &finger_name, "Finger selected to verify (default is automatic)", NULL },
|
||||||
{"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL},
|
{"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL},
|
||||||
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &usernames, NULL, "[username]" },
|
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &usernames, NULL, "[username]" },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
g_autoptr(FprintDBusDevice) dev = NULL;
|
g_autoptr(FprintDBusDevice) dev = NULL;
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
const char *username = NULL;
|
const char *username = NULL;
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
context = g_option_context_new ("Verify a fingerprint");
|
context = g_option_context_new ("Verify a fingerprint");
|
||||||
g_option_context_add_main_entries (context, entries, NULL);
|
g_option_context_add_main_entries (context, entries, NULL);
|
||||||
|
|
||||||
if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
|
if (g_option_context_parse (context, &argc, &argv, &err) == FALSE)
|
||||||
g_print ("couldn't parse command-line options: %s\n", err->message);
|
{
|
||||||
return 1;
|
g_print ("couldn't parse command-line options: %s\n", err->message);
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (usernames == NULL) {
|
if (usernames == NULL)
|
||||||
username = "";
|
username = "";
|
||||||
} else {
|
else
|
||||||
username = usernames[0];
|
username = usernames[0];
|
||||||
}
|
|
||||||
|
|
||||||
if (g_fatal_warnings) {
|
if (g_fatal_warnings)
|
||||||
GLogLevelFlags fatal_mask;
|
{
|
||||||
|
GLogLevelFlags fatal_mask;
|
||||||
|
|
||||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||||
g_log_set_always_fatal (fatal_mask);
|
g_log_set_always_fatal (fatal_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
create_manager();
|
create_manager ();
|
||||||
|
|
||||||
dev = open_device(username);
|
dev = open_device (username);
|
||||||
find_finger(dev, username);
|
find_finger (dev, username);
|
||||||
do_verify(dev);
|
do_verify (dev);
|
||||||
release_device(dev);
|
release_device (dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user