17 Commits

Author SHA1 Message Date
7d22a2b5b9 Release 1.90.8 2020-12-11 16:00:28 +01:00
de725a91e4 verify: Print message about verification start from callback
It seems that GLib may process multiple DBus signals in one mainloop
iteration. This could cause messages to be re-ordered, which in turn
caused a race condition in the CI that could trigger random failures.
2020-12-11 16:00:28 +01:00
18392cba54 manager: Export the object manager in /net/reactivated/Fprint
Given we're going to use an object manager it can just stay at the root
of the project, while it will be just used to manage the devices
2020-12-11 15:30:26 +01:00
783d82f359 device: Expose method name when logging authorization steps 2020-12-11 14:03:37 +00:00
c00a3375d1 device: Use standard names for local errors and remove unused one 2020-12-11 14:03:37 +00:00
5aa61adabc build: make systemd dependency optional
The systemd dependency is only used to install some systemd service
files. This can easily be made optional.
2020-12-11 15:01:24 +01:00
1fc10f15ee pam: Stop authorization if we couldn't parse signals
This really should never ever happen. If it does, don't continue but
stop instead.
2020-12-11 10:34:51 +01:00
c24badfd68 pam: Move NameOwnerChanged registration after initialization
We must ignore NameOwnerChanged that happen due to automatic startup.
The easy way to do so is to just register it only when we get to the
point that a name owner change has security implications.

While add it, change it to always log at a warning level.

Fixes: #94
2020-12-11 10:34:51 +01:00
4612c1f3ed Release 1.90.7 2020-12-09 13:16:12 +01:00
ca216a32af test_pam_fprintd: Add test verifying the case in which we've no devices 2020-12-08 21:14:24 +01:00
944493e472 pam_fprintd: Protect usage of strdup for NULL values
It's not smart as g_strdup, so need to ensure we don't use it for NULL
strings.

This is a regression caused by commit bf223662
2020-12-08 21:14:01 +01:00
34f24cbe19 ci: Move build jobs to build phase 2020-12-07 18:42:24 +01:00
9314069a88 ci: Add check-source stage where we check syntax 2020-12-07 18:42:24 +01:00
66e21eac8f .git-blame-ignore-revs: Ignore formatting commit and add hint how to use it 2020-12-07 18:42:22 +01:00
f73429f062 fprintd: Reindent the source code following uncrustify rules 2020-12-07 18:41:45 +01:00
c18ebaf9da scripts: Add uncrustify scripts for reformatting fprintd source code
We follow libfprint here, using GNOME format
2020-12-07 18:41:45 +01:00
4a80bfacec fingerprint-strings: Make the finger_str_to_msg loop clearer
Just continue earlier instead of using a long if check
2020-12-07 18:41:45 +01:00
23 changed files with 3823 additions and 3193 deletions

7
.git-blame-ignore-revs Normal file
View 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

View File

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

22
NEWS
View File

@ -1,6 +1,28 @@
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: Version 1.90.6:
The 1.90.5 release was unusable due to a number of inter-related issues The 1.90.5 release was unusable due to a number of inter-related issues

View File

@ -11,7 +11,8 @@ configure_file(
install_dir: dbus_service_dir, install_dir: dbus_service_dir,
) )
configure_file( if get_option('systemd')
configure_file(
configuration: configuration_data({ configuration: configuration_data({
'libexecdir': fprintd_installdir, 'libexecdir': fprintd_installdir,
}), }),
@ -19,7 +20,8 @@ configure_file(
output: 'fprintd.service', output: 'fprintd.service',
install: true, install: true,
install_dir: systemd_unit_dir, 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,

View File

@ -1,5 +1,5 @@
project('fprintd', 'c', project('fprintd', 'c',
version: '1.90.6', version: '1.90.8',
license: 'GPLv2+', license: 'GPLv2+',
default_options: [ default_options: [
'buildtype=debugoptimized', 'buildtype=debugoptimized',
@ -94,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 = ''

View File

@ -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')

View File

@ -28,16 +28,18 @@
#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 *dbus_name;
const char *place_str_generic; const char *place_str_generic;
const char *place_str_specific; const char *place_str_specific;
@ -105,33 +107,44 @@ struct {
#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;
if (is_swipe == false)
{
if (driver_name)
{
char *s; char *s;
int ret; int ret;
ret = asprintf (&s, TR (fingers[i].place_str_specific), driver_name); ret = asprintf (&s, TR (fingers[i].place_str_specific), driver_name);
return ret >= 0 ? s : NULL; return ret >= 0 ? s : NULL;
} else { }
else
{
return strdup (TR (fingers[i].place_str_generic)); return strdup (TR (fingers[i].place_str_generic));
} }
} else { }
if (driver_name) { else
{
if (driver_name)
{
char *s; char *s;
int ret; int ret;
ret = asprintf (&s, TR (fingers[i].swipe_str_specific), driver_name); ret = asprintf (&s, TR (fingers[i].swipe_str_specific), driver_name);
return ret >= 0 ? s : NULL; return ret >= 0 ? s : NULL;
} else {
return strdup (TR (fingers[i].swipe_str_generic));
} }
else
{
return strdup (TR (fingers[i].swipe_str_generic));
} }
} }
} }
@ -146,12 +159,14 @@ 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) if (is_swipe == false)
return TR (N_("Place your finger on the reader again")); return TR (N_("Place your finger on the reader again"));
else else
@ -172,12 +187,14 @@ 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) if (is_swipe == false)
return TR (N_("Place your finger on the reader again")); return TR (N_("Place your finger on the reader again"));
else else
@ -192,4 +209,3 @@ GNUC_UNUSED static const char *enroll_result_str_to_msg(const char *result, bool
return NULL; return NULL;
} }

View File

@ -39,7 +39,7 @@
#include <security/pam_ext.h> #include <security/pam_ext.h>
#define _(s) ((char *) dgettext (GETTEXT_PACKAGE, s)) #define _(s) ((char *) dgettext (GETTEXT_PACKAGE, s))
#define TR(s) dgettext(GETTEXT_PACKAGE, s) #define TR(s) dgettext (GETTEXT_PACKAGE, s)
#define N_(s) (s) #define N_(s) (s)
#include "fingerprint-strings.h" #include "fingerprint-strings.h"
@ -64,18 +64,21 @@ static uint64_t
now (void) now (void)
{ {
struct timespec ts; struct timespec ts;
clock_gettime (CLOCK_MONOTONIC, &ts); clock_gettime (CLOCK_MONOTONIC, &ts);
return (uint64_t) ts.tv_sec * USEC_PER_SEC + (uint64_t) ts.tv_nsec / NSEC_PER_USEC; return (uint64_t) ts.tv_sec * USEC_PER_SEC + (uint64_t) ts.tv_nsec / NSEC_PER_USEC;
} }
static bool str_has_prefix (const char *s, const char *prefix) static bool
str_has_prefix (const char *s, const char *prefix)
{ {
if (s == NULL || prefix == NULL) if (s == NULL || prefix == NULL)
return false; return false;
return (strncmp (s, prefix, strlen (prefix)) == 0); return strncmp (s, prefix, strlen (prefix)) == 0;
} }
static bool send_msg(pam_handle_t *pamh, const char *msg, int style) static bool
send_msg (pam_handle_t *pamh, const char *msg, int style)
{ {
const struct pam_message mymsg = { const struct pam_message mymsg = {
.msg_style = style, .msg_style = style,
@ -85,23 +88,25 @@ static bool send_msg(pam_handle_t *pamh, const char *msg, int style)
const struct pam_conv *pc; const struct pam_conv *pc;
struct pam_response *resp; struct pam_response *resp;
if (pam_get_item(pamh, PAM_CONV, (const void **) &pc) != PAM_SUCCESS) if (pam_get_item (pamh, PAM_CONV, (const void **) &pc) != PAM_SUCCESS)
return false; return false;
if (!pc || !pc->conv) if (!pc || !pc->conv)
return false; return false;
return (pc->conv(1, &msgp, &resp, pc->appdata_ptr) == PAM_SUCCESS); return pc->conv (1, &msgp, &resp, pc->appdata_ptr) == PAM_SUCCESS;
} }
static bool send_info_msg(pam_handle_t *pamh, const char *msg) static bool
send_info_msg (pam_handle_t *pamh, const char *msg)
{ {
return send_msg(pamh, msg, PAM_TEXT_INFO); return send_msg (pamh, msg, PAM_TEXT_INFO);
} }
static bool send_err_msg(pam_handle_t *pamh, const char *msg) static bool
send_err_msg (pam_handle_t *pamh, const char *msg)
{ {
return send_msg(pamh, msg, PAM_ERROR_MSG); return send_msg (pamh, msg, PAM_ERROR_MSG);
} }
static char * static char *
@ -109,8 +114,8 @@ open_device (pam_handle_t *pamh,
sd_bus *bus, sd_bus *bus,
bool *has_multiple_devices) bool *has_multiple_devices)
{ {
pf_auto(sd_bus_error) error = SD_BUS_ERROR_NULL; pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
pf_autoptr(sd_bus_message) m = NULL; pf_autoptr (sd_bus_message) m = NULL;
size_t num_devices; size_t num_devices;
const char *path = NULL; const char *path = NULL;
const char *s; const char *s;
@ -125,13 +130,15 @@ open_device (pam_handle_t *pamh,
"GetDevices", "GetDevices",
&error, &error,
&m, &m,
NULL) < 0) { NULL) < 0)
{
pam_syslog (pamh, LOG_ERR, "GetDevices failed: %s", error.message); pam_syslog (pamh, LOG_ERR, "GetDevices failed: %s", error.message);
return NULL; return NULL;
} }
r = sd_bus_message_enter_container (m, 'a', "o"); r = sd_bus_message_enter_container (m, 'a', "o");
if (r < 0) { if (r < 0)
{
pam_syslog (pamh, LOG_ERR, "Failed to parse answer from GetDevices(): %d", r); pam_syslog (pamh, LOG_ERR, "Failed to parse answer from GetDevices(): %d", r);
return NULL; return NULL;
} }
@ -140,18 +147,19 @@ open_device (pam_handle_t *pamh,
return NULL; return NULL;
num_devices = 1; num_devices = 1;
while ((r = sd_bus_message_read_basic(m, 'o', &s)) > 0) while ((r = sd_bus_message_read_basic (m, 'o', &s)) > 0)
num_devices++; num_devices++;
*has_multiple_devices = (num_devices > 1); *has_multiple_devices = (num_devices > 1);
if (debug) if (debug)
pam_syslog(pamh, LOG_DEBUG, "Using device %s (out of %ld devices)", path, num_devices); pam_syslog (pamh, LOG_DEBUG, "Using device %s (out of %ld devices)", path, num_devices);
sd_bus_message_exit_container (m); sd_bus_message_exit_container (m);
return strdup (path); return path ? strdup (path) : NULL;
} }
typedef struct { typedef struct
{
char *dev; char *dev;
bool has_multiple_devices; bool has_multiple_devices;
@ -189,38 +197,45 @@ verify_result (sd_bus_message *m,
uint64_t done = false; uint64_t done = false;
int r; int r;
if (!sd_bus_message_is_signal(m, "net.reactivated.Fprint.Device", "VerifyStatus")) { if (!sd_bus_message_is_signal (m, "net.reactivated.Fprint.Device", "VerifyStatus"))
{
pam_syslog (data->pamh, LOG_ERR, "Not the signal we expected (iface: %s, member: %s)", pam_syslog (data->pamh, LOG_ERR, "Not the signal we expected (iface: %s, member: %s)",
sd_bus_message_get_interface (m), sd_bus_message_get_interface (m),
sd_bus_message_get_member (m)); sd_bus_message_get_member (m));
return 0; return 0;
} }
if ((r = sd_bus_message_read (m, "sb", &result, &done)) < 0) { if ((r = sd_bus_message_read (m, "sb", &result, &done)) < 0)
{
pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyResult signal: %d", r); pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyResult signal: %d", r);
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
return 0; return 0;
} }
if (!data->verify_started) { if (!data->verify_started)
pam_syslog (data->pamh, LOG_ERR, "Unexpected VerifyResult '%s', %"PRIu64" signal", result, done); {
pam_syslog (data->pamh, LOG_ERR, "Unexpected VerifyResult '%s', %" PRIu64 " signal", result, done);
return 0; return 0;
} }
if (debug) if (debug)
pam_syslog (data->pamh, LOG_DEBUG, "Verify result: %s (done: %d)", result, done ? 1 : 0); pam_syslog (data->pamh, LOG_DEBUG, "Verify result: %s (done: %d)", result, done ? 1 : 0);
if (data->result) { if (data->result)
{
free (data->result); free (data->result);
data->result = NULL; data->result = NULL;
} }
if (done) { if (done && result)
{
data->result = strdup (result); data->result = strdup (result);
return 0; return 0;
} }
msg = verify_result_str_to_msg (result, data->is_swipe); msg = verify_result_str_to_msg (result, data->is_swipe);
if (!msg) { if (!msg)
{
data->result = strdup ("Protocol error with fprintd!"); data->result = strdup ("Protocol error with fprintd!");
return 0; return 0;
} }
@ -238,18 +253,22 @@ verify_finger_selected (sd_bus_message *m,
const char *finger_name = NULL; const char *finger_name = NULL;
pf_autofree char *msg = NULL; pf_autofree char *msg = NULL;
if (sd_bus_message_read_basic (m, 's', &finger_name) < 0) { if (sd_bus_message_read_basic (m, 's', &finger_name) < 0)
{
pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyFingerSelected signal: %d", errno); pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyFingerSelected signal: %d", errno);
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
return 0; return 0;
} }
if (!data->verify_started) { if (!data->verify_started)
{
pam_syslog (data->pamh, LOG_ERR, "Unexpected VerifyFingerSelected %s signal", finger_name); pam_syslog (data->pamh, LOG_ERR, "Unexpected VerifyFingerSelected %s signal", finger_name);
return 0; return 0;
} }
msg = finger_str_to_msg(finger_name, data->driver, data->is_swipe); msg = finger_str_to_msg (finger_name, data->driver, data->is_swipe);
if (!msg) { if (!msg)
{
data->result = strdup ("Protocol error with fprintd!"); data->result = strdup ("Protocol error with fprintd!");
return 0; return 0;
} }
@ -268,46 +287,52 @@ get_property_string (sd_bus *bus,
const char *interface, const char *interface,
const char *member, const char *member,
sd_bus_error *error, sd_bus_error *error,
char **ret) { char **ret)
{
pf_autoptr(sd_bus_message) reply = NULL; pf_autoptr (sd_bus_message) reply = NULL;
const char *s; const char *s;
char *n; char *n;
int r; int r;
r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", interface, member); r = sd_bus_call_method (bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", interface, member);
if (r < 0) if (r < 0)
return r; return r;
r = sd_bus_message_enter_container(reply, 'v', "s"); r = sd_bus_message_enter_container (reply, 'v', "s");
if (r < 0) if (r < 0)
return sd_bus_error_set_errno(error, r); return sd_bus_error_set_errno (error, r);
r = sd_bus_message_read_basic(reply, 's', &s); r = sd_bus_message_read_basic (reply, 's', &s);
if (r < 0) if (r < 0)
return sd_bus_error_set_errno(error, r); return sd_bus_error_set_errno (error, r);
n = strdup(s); n = strdup (s);
if (!n) { if (!n)
return sd_bus_error_set_errno(error, -ENOMEM); return sd_bus_error_set_errno (error, -ENOMEM);
}
*ret = n; *ret = n;
return 0; return 0;
} }
static int verify_started_cb (sd_bus_message *m, static int
verify_started_cb (sd_bus_message *m,
void *userdata, void *userdata,
sd_bus_error *ret_error) { sd_bus_error *ret_error)
{
const sd_bus_error *error = sd_bus_message_get_error (m); const sd_bus_error *error = sd_bus_message_get_error (m);
verify_data *data = userdata; verify_data *data = userdata;
if (error) { if (error)
if (sd_bus_error_has_name (error, "net.reactivated.Fprint.Error.NoEnrolledPrints")) { {
if (sd_bus_error_has_name (error, "net.reactivated.Fprint.Error.NoEnrolledPrints"))
{
pam_syslog (data->pamh, LOG_DEBUG, "No prints enrolled"); pam_syslog (data->pamh, LOG_DEBUG, "No prints enrolled");
data->verify_ret = PAM_USER_UNKNOWN; data->verify_ret = PAM_USER_UNKNOWN;
} else { }
else
{
data->verify_ret = PAM_AUTH_ERR; data->verify_ret = PAM_AUTH_ERR;
} }
@ -329,8 +354,8 @@ static int
do_verify (sd_bus *bus, do_verify (sd_bus *bus,
verify_data *data) verify_data *data)
{ {
pf_autoptr(sd_bus_slot) verify_status_slot = NULL; pf_autoptr (sd_bus_slot) verify_status_slot = NULL;
pf_autoptr(sd_bus_slot) verify_finger_selected_slot = NULL; pf_autoptr (sd_bus_slot) verify_finger_selected_slot = NULL;
pf_autofree char *scan_type = NULL; pf_autofree char *scan_type = NULL;
int r; int r;
@ -349,7 +374,8 @@ do_verify (sd_bus *bus,
if (str_equal (scan_type, "swipe")) if (str_equal (scan_type, "swipe"))
data->is_swipe = true; data->is_swipe = true;
if (data->has_multiple_devices) { if (data->has_multiple_devices)
{
get_property_string (bus, get_property_string (bus,
"net.reactivated.Fprint", "net.reactivated.Fprint",
data->dev, data->dev,
@ -381,7 +407,8 @@ do_verify (sd_bus *bus,
verify_finger_selected, verify_finger_selected,
data); data);
while (data->max_tries > 0) { while (data->max_tries > 0)
{
uint64_t verification_end = now () + (timeout * USEC_PER_SEC); uint64_t verification_end = now () + (timeout * USEC_PER_SEC);
data->timed_out = false; data->timed_out = false;
@ -405,16 +432,18 @@ do_verify (sd_bus *bus,
"s", "s",
"any"); "any");
if (r < 0) { if (r < 0)
{
if (debug) if (debug)
pam_syslog (data->pamh, LOG_DEBUG, "VerifyStart call failed: %d", r); pam_syslog (data->pamh, LOG_DEBUG, "VerifyStart call failed: %d", r);
break; break;
} }
for (;;) { for (;;)
{
int64_t wait_time; int64_t wait_time;
wait_time = verification_end - now(); wait_time = verification_end - now ();
if (wait_time <= 0) if (wait_time <= 0)
break; break;
@ -427,10 +456,12 @@ do_verify (sd_bus *bus,
continue; continue;
if (data->result != NULL) if (data->result != NULL)
break; break;
if (r == 0) { if (r == 0)
if (debug) { {
pam_syslog(data->pamh, LOG_DEBUG, if (debug)
"Waiting for %"PRId64" seconds (%"PRId64" usecs)", {
pam_syslog (data->pamh, LOG_DEBUG,
"Waiting for %" PRId64 " seconds (%" PRId64 " usecs)",
wait_time / USEC_PER_SEC, wait_time / USEC_PER_SEC,
wait_time); wait_time);
} }
@ -439,11 +470,11 @@ do_verify (sd_bus *bus,
} }
} }
if (data->verify_ret != PAM_INCOMPLETE) { if (data->verify_ret != PAM_INCOMPLETE)
return data->verify_ret; return data->verify_ret;
}
if (now () >= verification_end) { if (now () >= verification_end)
{
data->timed_out = true; data->timed_out = true;
send_info_msg (data->pamh, _("Verification timed out")); send_info_msg (data->pamh, _("Verification timed out"));
} }
@ -460,18 +491,30 @@ do_verify (sd_bus *bus,
NULL, NULL,
NULL); NULL);
if (data->timed_out) { if (data->timed_out)
{
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
} else { }
if (str_equal (data->result, "verify-no-match")) { else
{
if (str_equal (data->result, "verify-no-match"))
{
send_err_msg (data->pamh, "Failed to match fingerprint"); send_err_msg (data->pamh, "Failed to match fingerprint");
} else if (str_equal (data->result, "verify-match")) { }
else if (str_equal (data->result, "verify-match"))
{
return PAM_SUCCESS; return PAM_SUCCESS;
} else if (str_equal (data->result, "verify-unknown-error")) { }
else if (str_equal (data->result, "verify-unknown-error"))
{
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
} else if (str_equal (data->result, "verify-disconnected")) { }
else if (str_equal (data->result, "verify-disconnected"))
{
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
} else { }
else
{
send_err_msg (data->pamh, _("An unknown error occurred")); send_err_msg (data->pamh, _("An unknown error occurred"));
return PAM_AUTH_ERR; return PAM_AUTH_ERR;
} }
@ -491,8 +534,8 @@ user_has_prints (pam_handle_t *pamh,
const char *dev, const char *dev,
const char *username) const char *username)
{ {
pf_auto(sd_bus_error) error = SD_BUS_ERROR_NULL; pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
pf_autoptr(sd_bus_message) m = NULL; pf_autoptr (sd_bus_message) m = NULL;
size_t num_fingers = 0; size_t num_fingers = 0;
const char *s; const char *s;
int r; int r;
@ -506,28 +549,29 @@ user_has_prints (pam_handle_t *pamh,
&m, &m,
"s", "s",
username); username);
if (r < 0) { if (r < 0)
{
/* If ListEnrolledFingers fails then verification should /* If ListEnrolledFingers fails then verification should
* also fail (both use the same underlying call), so we * also fail (both use the same underlying call), so we
* report false here and bail out early. */ * report false here and bail out early. */
if (debug) { if (debug)
pam_syslog (pamh, LOG_DEBUG, "ListEnrolledFingers failed for %s: %s", pam_syslog (pamh, LOG_DEBUG, "ListEnrolledFingers failed for %s: %s",
username, error.message); username, error.message);
}
return false; return false;
} }
r = sd_bus_message_enter_container (m, 'a', "s"); r = sd_bus_message_enter_container (m, 'a', "s");
if (r < 0) { if (r < 0)
{
pam_syslog (pamh, LOG_ERR, "Failed to parse answer from ListEnrolledFingers(): %d", r); pam_syslog (pamh, LOG_ERR, "Failed to parse answer from ListEnrolledFingers(): %d", r);
return false; return false;
} }
while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) while ((r = sd_bus_message_read_basic (m, 's', &s)) > 0)
num_fingers++; num_fingers++;
sd_bus_message_exit_container (m); sd_bus_message_exit_container (m);
return (num_fingers > 0); return num_fingers > 0;
} }
static void static void
@ -535,7 +579,7 @@ release_device (pam_handle_t *pamh,
sd_bus *bus, sd_bus *bus,
const char *dev) const char *dev)
{ {
pf_auto(sd_bus_error) error = SD_BUS_ERROR_NULL; pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
if (sd_bus_call_method (bus, if (sd_bus_call_method (bus,
"net.reactivated.Fprint", "net.reactivated.Fprint",
@ -545,9 +589,8 @@ release_device (pam_handle_t *pamh,
&error, &error,
NULL, NULL,
NULL, NULL,
NULL) < 0) { NULL) < 0)
pam_syslog (pamh, LOG_ERR, "ReleaseDevice failed: %s", error.message); pam_syslog (pamh, LOG_ERR, "ReleaseDevice failed: %s", error.message);
}
} }
static bool static bool
@ -556,7 +599,7 @@ claim_device (pam_handle_t *pamh,
const char *dev, const char *dev,
const char *username) const char *username)
{ {
pf_auto(sd_bus_error) error = SD_BUS_ERROR_NULL; pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
if (sd_bus_call_method (bus, if (sd_bus_call_method (bus,
"net.reactivated.Fprint", "net.reactivated.Fprint",
@ -566,7 +609,8 @@ claim_device (pam_handle_t *pamh,
&error, &error,
NULL, NULL,
"s", "s",
username) < 0) { username) < 0)
{
if (debug) if (debug)
pam_syslog (pamh, LOG_DEBUG, "failed to claim device %s", error.message); pam_syslog (pamh, LOG_DEBUG, "failed to claim device %s", error.message);
return false; return false;
@ -585,8 +629,10 @@ name_owner_changed (sd_bus_message *m,
const char *old_owner = NULL; const char *old_owner = NULL;
const char *new_owner = NULL; const char *new_owner = NULL;
if (sd_bus_message_read (m, "sss", &name, &old_owner, &new_owner) < 0) { if (sd_bus_message_read (m, "sss", &name, &old_owner, &new_owner) < 0)
{
pam_syslog (data->pamh, LOG_ERR, "Failed to parse NameOwnerChanged signal: %d", errno); pam_syslog (data->pamh, LOG_ERR, "Failed to parse NameOwnerChanged signal: %d", errno);
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
return 0; return 0;
} }
@ -597,28 +643,44 @@ name_owner_changed (sd_bus_message *m,
* to events from a new name owner otherwise. */ * to events from a new name owner otherwise. */
data->verify_ret = PAM_AUTHINFO_UNAVAIL; data->verify_ret = PAM_AUTHINFO_UNAVAIL;
if (debug) pam_syslog (data->pamh, LOG_WARNING, "fprintd name owner changed during operation!");
pam_syslog (data->pamh, LOG_ERR, "fprintd name owner changed during operation!\n");
return 0; return 0;
} }
static int do_auth(pam_handle_t *pamh, const char *username) static int
do_auth (pam_handle_t *pamh, const char *username)
{ {
bool have_prints; bool have_prints;
pf_autoptr(verify_data) data = NULL;
pf_autoptr(sd_bus) bus = NULL;
pf_autoptr(sd_bus_slot) name_owner_changed_slot = NULL;
data = calloc (1, sizeof(verify_data)); pf_autoptr (verify_data) data = NULL;
pf_autoptr (sd_bus) bus = NULL;
pf_autoptr (sd_bus_slot) name_owner_changed_slot = NULL;
data = calloc (1, sizeof (verify_data));
data->max_tries = max_tries; data->max_tries = max_tries;
data->pamh = pamh; data->pamh = pamh;
if (sd_bus_open_system (&bus) < 0) { if (sd_bus_open_system (&bus) < 0)
{
pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %d", errno); pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %d", errno);
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
} }
data->dev = open_device (pamh, bus, &data->has_multiple_devices);
if (data->dev == NULL)
return PAM_AUTHINFO_UNAVAIL;
have_prints = user_has_prints (pamh, bus, data->dev, username);
if (debug)
pam_syslog (pamh, LOG_DEBUG, "prints registered: %s\n", have_prints ? "yes" : "no");
if (!have_prints)
return PAM_AUTHINFO_UNAVAIL;
/* Only connect to NameOwnerChanged when needed. In case of automatic startup
* we rely on the fact that we never see those signals.
*/
name_owner_changed_slot = NULL; name_owner_changed_slot = NULL;
sd_bus_match_signal (bus, sd_bus_match_signal (bus,
&name_owner_changed_slot, &name_owner_changed_slot,
@ -629,19 +691,8 @@ static int do_auth(pam_handle_t *pamh, const char *username)
name_owner_changed, name_owner_changed,
data); data);
data->dev = open_device (pamh, bus, &data->has_multiple_devices); if (claim_device (pamh, bus, data->dev, username))
if (data->dev == NULL) { {
return PAM_AUTHINFO_UNAVAIL;
}
have_prints = user_has_prints (pamh, bus, data->dev, username);
if (debug)
pam_syslog (pamh, LOG_DEBUG, "prints registered: %s\n", have_prints ? "yes" : "no");
if (!have_prints)
return PAM_AUTHINFO_UNAVAIL;
if (claim_device (pamh, bus, data->dev, username)) {
int ret = do_verify (bus, data); int ret = do_verify (bus, data);
release_device (pamh, bus, data->dev); release_device (pamh, bus, data->dev);
return ret; return ret;
@ -655,16 +706,15 @@ is_remote (pam_handle_t *pamh)
{ {
const char *rhost = NULL; const char *rhost = NULL;
pam_get_item(pamh, PAM_RHOST, (const void **)(const void*) &rhost); pam_get_item (pamh, PAM_RHOST, (const void **) (const void *) &rhost);
/* NULL or empty rhost if the host information is not available or set. /* NULL or empty rhost if the host information is not available or set.
* "localhost" if the host is local. * "localhost" if the host is local.
* We want to not run for known remote hosts */ * We want to not run for known remote hosts */
if (rhost != NULL && if (rhost != NULL &&
*rhost != '\0' && *rhost != '\0' &&
strcmp (rhost, "localhost") != 0) { strcmp (rhost, "localhost") != 0)
return true; return true;
}
if (sd_session_is_remote (NULL) > 0) if (sd_session_is_remote (NULL) > 0)
return true; return true;
@ -672,7 +722,8 @@ is_remote (pam_handle_t *pamh)
return false; return false;
} }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, PAM_EXTERN int
pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc,
const char **argv) const char **argv)
{ {
const char *username; const char *username;
@ -684,69 +735,86 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
if (is_remote (pamh)) if (is_remote (pamh))
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
if (pam_get_user(pamh, &username, NULL) != PAM_SUCCESS) if (pam_get_user (pamh, &username, NULL) != PAM_SUCCESS)
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++)
if (argv[i] != NULL) { {
if (str_equal (argv[i], "debug")) { if (argv[i] != NULL)
{
if (str_equal (argv[i], "debug"))
{
pam_syslog (pamh, LOG_DEBUG, "debug on"); pam_syslog (pamh, LOG_DEBUG, "debug on");
debug = true; debug = true;
} else if (str_has_prefix (argv[i], DEBUG_MATCH)) { }
else if (str_has_prefix (argv[i], DEBUG_MATCH))
{
pam_syslog (pamh, LOG_DEBUG, "debug on"); pam_syslog (pamh, LOG_DEBUG, "debug on");
const char *value; const char *value;
value = argv[i] + strlen (DEBUG_MATCH); value = argv[i] + strlen (DEBUG_MATCH);
if (str_equal (value, "on") || if (str_equal (value, "on") ||
str_equal (value, "true") || str_equal (value, "true") ||
str_equal (value, "1")) { str_equal (value, "1"))
{
pam_syslog (pamh, LOG_DEBUG, "debug on"); pam_syslog (pamh, LOG_DEBUG, "debug on");
debug = true; debug = true;
} else if (str_equal (value, "off") || }
else if (str_equal (value, "off") ||
str_equal (value, "false") || str_equal (value, "false") ||
str_equal (value, "0")) { str_equal (value, "0"))
{
debug = false; debug = false;
} else { }
else
{
pam_syslog (pamh, LOG_DEBUG, "invalid debug value '%s', disabling", value); pam_syslog (pamh, LOG_DEBUG, "invalid debug value '%s', disabling", value);
} }
} else if (str_has_prefix (argv[i], MAX_TRIES_MATCH) && strlen(argv[i]) == strlen (MAX_TRIES_MATCH) + 1) { }
else if (str_has_prefix (argv[i], MAX_TRIES_MATCH) && strlen (argv[i]) == strlen (MAX_TRIES_MATCH) + 1)
{
max_tries = atoi (argv[i] + strlen (MAX_TRIES_MATCH)); max_tries = atoi (argv[i] + strlen (MAX_TRIES_MATCH));
if (max_tries < 1) { if (max_tries < 1)
if (debug) { {
if (debug)
pam_syslog (pamh, LOG_DEBUG, "invalid max tries '%s', using %d", pam_syslog (pamh, LOG_DEBUG, "invalid max tries '%s', using %d",
argv[i] + strlen (MAX_TRIES_MATCH), DEFAULT_MAX_TRIES); argv[i] + strlen (MAX_TRIES_MATCH), DEFAULT_MAX_TRIES);
}
max_tries = DEFAULT_MAX_TRIES; max_tries = DEFAULT_MAX_TRIES;
} }
if (debug) if (debug)
pam_syslog (pamh, LOG_DEBUG, "max_tries specified as: %d", max_tries); pam_syslog (pamh, LOG_DEBUG, "max_tries specified as: %d", max_tries);
} else if (str_has_prefix (argv[i], TIMEOUT_MATCH) && strlen(argv[i]) <= strlen (TIMEOUT_MATCH) + 2) { }
else if (str_has_prefix (argv[i], TIMEOUT_MATCH) && strlen (argv[i]) <= strlen (TIMEOUT_MATCH) + 2)
{
timeout = atoi (argv[i] + strlen (TIMEOUT_MATCH)); timeout = atoi (argv[i] + strlen (TIMEOUT_MATCH));
if (timeout < MIN_TIMEOUT) { if (timeout < MIN_TIMEOUT)
if (debug) { {
if (debug)
pam_syslog (pamh, LOG_DEBUG, "timeout %d secs too low, using %d", pam_syslog (pamh, LOG_DEBUG, "timeout %d secs too low, using %d",
timeout, MIN_TIMEOUT); timeout, MIN_TIMEOUT);
}
timeout = MIN_TIMEOUT; timeout = MIN_TIMEOUT;
} else if (debug) { }
else if (debug)
{
pam_syslog (pamh, LOG_DEBUG, "timeout specified as: %d secs", timeout); pam_syslog (pamh, LOG_DEBUG, "timeout specified as: %d secs", timeout);
} }
} }
} }
} }
return do_auth(pamh, username); return do_auth (pamh, username);
} }
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, PAM_EXTERN int
pam_sm_setcred (pam_handle_t *pamh, int flags, int argc,
const char **argv) const char **argv)
{ {
return PAM_SUCCESS; return PAM_SUCCESS;
} }
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, PAM_EXTERN int
pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc,
const char **argv) const char **argv)
{ {
return PAM_SUCCESS; return PAM_SUCCESS;
} }

View File

@ -23,10 +23,10 @@
/* Define auto-pointers functions, based on GLib Macros */ /* Define auto-pointers functions, based on GLib Macros */
#define _CLEANUP_FUNC(func) __attribute__((cleanup(func))) #define _CLEANUP_FUNC(func) __attribute__((cleanup (func)))
#define _PF_AUTOPTR_FUNC_NAME(TypeName) pf_autoptr_cleanup_##TypeName #define _PF_AUTOPTR_FUNC_NAME(TypeName) pf_autoptr_cleanup_ ## TypeName
#define _PF_AUTOPTR_TYPENAME(TypeName) TypeName##_pf_autoptr #define _PF_AUTOPTR_TYPENAME(TypeName) TypeName ## _pf_autoptr
#define PF_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, cleanup) \ #define PF_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, cleanup) \
typedef TypeName *_PF_AUTOPTR_TYPENAME (TypeName); \ typedef TypeName *_PF_AUTOPTR_TYPENAME (TypeName); \
@ -42,7 +42,8 @@
static inline void static inline void
autoptr_cleanup_generic_free (void *p) autoptr_cleanup_generic_free (void *p)
{ {
void **pp = (void**)p; void **pp = (void **) p;
free (*pp); free (*pp);
} }

137
scripts/uncrustify.cfg Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,8 @@
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;
@ -55,10 +56,12 @@ static const char *get_storage_path(void)
* 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 /* If multiple directories are set, then in the environment variable
* the paths are concatenated with colon (":"). */ * the paths are concatenated with colon (":"). */
if (strchr (path, ':')) { if (strchr (path, ':'))
{
g_auto(GStrv) elems = NULL; g_auto(GStrv) elems = NULL;
elems = g_strsplit (path, ":", -1); elems = g_strsplit (path, ":", -1);
storage_path = g_strdup (elems[0]); storage_path = g_strdup (elems[0]);
@ -71,47 +74,53 @@ static const char *get_storage_path(void)
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 *
__get_path_to_print (const char *driver, const char * device_id,
FpFinger finger, char *base_store) 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;
@ -121,29 +130,32 @@ int file_storage_print_data_save(FpPrint *print)
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); g_warning ("Error serializing data: %s", err->message);
return -ENOMEM; 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",
dirpath, g_strerror (r));
return 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", {
g_debug ("file_storage_print_data_save(): could not save '%s': %s",
path, err->message); path, err->message);
/* FIXME interpret error codes */ /* FIXME interpret error codes */
return err->code; return err->code;
@ -152,7 +164,8 @@ int file_storage_print_data_save(FpPrint *print)
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;
@ -160,8 +173,9 @@ static int load_from_file(char *path, FpPrint **print)
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; int r = err->code;
/* FIXME interpret more error codes */ /* FIXME interpret more error codes */
if (r == G_FILE_ERROR_NOENT) if (r == G_FILE_ERROR_NOENT)
@ -171,7 +185,8 @@ static int load_from_file(char *path, FpPrint **print)
} }
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); g_print ("Error deserializing data: %s", err->message);
return -EIO; return -EIO;
} }
@ -180,134 +195,145 @@ static int load_from_file(char *path, FpPrint **print)
return 0; return 0;
} }
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)
{ {
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; g_autoptr(FpPrint) new = 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(dev, finger, base_store); path = get_path_to_print (dev, finger, base_store);
r = load_from_file(path, &new); r = load_from_file (path, &new);
g_debug ("file_storage_print_data_load(): loaded '%s' %s", g_debug ("file_storage_print_data_load(): loaded '%s' %s",
path, g_strerror(r)); path, g_strerror (r));
if (r) if (r)
return r; return r;
if (!fp_print_compatible (new, dev)) { if (!fp_print_compatible (new, dev))
return -EINVAL; return -EINVAL;
}
*print = g_steal_pointer (&new); *print = g_steal_pointer (&new);
return 0; 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 *
scan_dev_storedir (char *devpath,
GSList *list) 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); if (!dir)
{
g_debug ("scan_dev_storedir(): opendir(\"%s\") failed: %s", devpath, err->message);
return list; return list;
} }
while ((ent = g_dir_read_name(dir))) { while ((ent = g_dir_read_name (dir)))
{
/* ent is an 1 hex character fp_finger code */ /* ent is an 1 hex character fp_finger code */
guint64 val; guint64 val;
gchar *endptr; gchar *endptr;
if (*ent == 0 || strlen(ent) != 1) if (*ent == 0 || strlen (ent) != 1)
continue; continue;
val = g_ascii_strtoull(ent, &endptr, 16); val = g_ascii_strtoull (ent, &endptr, 16);
if (endptr == ent || !FP_FINGER_IS_VALID(val)) { if (endptr == ent || !FP_FINGER_IS_VALID (val))
g_debug("scan_dev_storedir(): skipping print file '%s'", ent); {
g_debug ("scan_dev_storedir(): skipping print file '%s'", ent);
continue; continue;
} }
list = g_slist_prepend (list, GUINT_TO_POINTER (val)); list = g_slist_prepend (list, GUINT_TO_POINTER (val));
} }
g_dir_close(dir); g_dir_close (dir);
return list; 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 */ /* ent is a username */
if (*ent == 0) if (*ent == 0)
continue; 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;

View File

@ -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);

View File

@ -31,9 +31,9 @@
#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 >*/
@ -57,7 +57,7 @@ typedef enum {
- The order controls the priority of a required permission when various are - The order controls the priority of a required permission when various are
accepted: the lowest the value, the more priorty it has. accepted: the lowest the value, the more priorty it has.
- Nick must match the relative polkit rule. - Nick must match the relative polkit rule.
*/ */
typedef enum { typedef enum {
FPRINT_DEVICE_PERMISSION_NONE = 0, FPRINT_DEVICE_PERMISSION_NONE = 0,
FPRINT_DEVICE_PERMISSION_VERIFY = (1 << 0), /*< nick=net.reactivated.fprint.device.verify >*/ FPRINT_DEVICE_PERMISSION_VERIFY = (1 << 0), /*< nick=net.reactivated.fprint.device.verify >*/
@ -66,25 +66,28 @@ typedef enum {
} 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 */

View File

@ -69,7 +69,8 @@ load_storage_module (const char *module_name)
!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); g_module_close (module);
return FALSE; return FALSE;
} }
@ -84,13 +85,15 @@ 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(GKeyFile) file = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
filename = g_build_filename (SYSCONFDIR, "fprintd.conf", NULL); filename = g_build_filename (SYSCONFDIR, "fprintd.conf", NULL);
file = g_key_file_new (); file = g_key_file_new ();
g_debug("About to load configuration file '%s'", filename); g_debug ("About to load configuration file '%s'", filename);
if (!g_key_file_load_from_file (file, filename, G_KEY_FILE_NONE, &error)) { 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); g_warning ("Could not open \"%s\": %s\n", filename, error->message);
return FALSE; return FALSE;
} }
@ -99,7 +102,8 @@ load_conf (void)
if (module_name == NULL) if (module_name == NULL)
return FALSE; return FALSE;
if (g_str_equal (module_name, "file")) { if (g_str_equal (module_name, "file"))
{
set_storage_file (); set_storage_file ();
return TRUE; return TRUE;
} }
@ -113,7 +117,8 @@ static const GOptionEntry entries[] = {
{ NULL } { NULL }
}; };
static gboolean sigterm_callback(gpointer data) static gboolean
sigterm_callback (gpointer data)
{ {
GMainLoop *loop = data; GMainLoop *loop = data;
@ -141,7 +146,8 @@ on_name_lost (GDBusConnection *connection,
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;
@ -159,12 +165,14 @@ int main(int argc, char **argv)
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); g_warning ("couldn't parse command-line options: %s\n", error->message);
return 1; 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);
@ -174,21 +182,22 @@ int main(int argc, char **argv)
/* 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); {
g_warning ("Failed to open connection to bus: %s", error->message);
return 1; 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 */
@ -204,11 +213,10 @@ int main(int argc, char **argv)
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;
} }

View File

@ -28,10 +28,12 @@
#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
{ {
@ -43,7 +45,7 @@ typedef struct
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,
@ -53,7 +55,8 @@ enum {
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));
@ -62,50 +65,58 @@ static void fprint_manager_finalize(GObject *object)
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
fprint_manager_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec) 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: case FPRINT_MANAGER_CONNECTION:
priv->connection = g_value_dup_object (value); priv->connection = g_value_dup_object (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; break;
} }
} }
static void fprint_manager_get_property (GObject *object, guint property_id, static void
fprint_manager_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec) 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: case FPRINT_MANAGER_CONNECTION:
g_value_set_object (value, priv->connection); g_value_set_object (value, priv->connection);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; 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);
@ -125,17 +136,18 @@ static void fprint_manager_class_init(FprintManagerClass *klass)
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;
} }
@ -144,11 +156,13 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
{ {
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;
g_autolist (GDBusObject) devices = NULL;
GList *l; GList *l;
gboolean in_use; gboolean in_use;
if (priv->timeout_id > 0) { if (priv->timeout_id > 0)
{
g_source_remove (priv->timeout_id); g_source_remove (priv->timeout_id);
priv->timeout_id = 0; priv->timeout_id = 0;
} }
@ -157,12 +171,13 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
devices = g_dbus_object_manager_get_objects (priv->object_manager); devices = g_dbus_object_manager_get_objects (priv->object_manager);
for (l = devices; l != NULL; l = l->next) { for (l = devices; l != NULL; l = l->next)
{
g_autoptr(FprintDevice) dev = NULL; g_autoptr(FprintDevice) dev = NULL;
FprintDBusObjectSkeleton *object = l->data; FprintDBusObjectSkeleton *object = l->data;
dev = fprint_dbus_object_skeleton_get_device (object); dev = fprint_dbus_object_skeleton_get_device (object);
g_object_get (G_OBJECT(dev), "in-use", &in_use, NULL); g_object_get (G_OBJECT (dev), "in-use", &in_use, NULL);
if (in_use != FALSE) if (in_use != FALSE)
num_devices_used++; num_devices_used++;
} }
@ -178,7 +193,8 @@ handle_get_devices (FprintManager *manager, GDBusMethodInvocation *invocation,
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); g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE; return TRUE;
} }
@ -196,9 +212,11 @@ handle_get_default_device (FprintManager *manager,
FprintDBusManager *skeleton) FprintDBusManager *skeleton)
{ {
const gchar *device; const gchar *device;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
if (!fprint_manager_get_default_device (manager, &device, &error)) { if (!fprint_manager_get_default_device (manager, &device, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error); g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE; return TRUE;
} }
@ -213,13 +231,14 @@ 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(FprintDBusObjectSkeleton) object = NULL;
g_autoptr(FprintDevice) rdev = NULL; g_autoptr(FprintDevice) rdev = NULL;
g_autofree gchar *path = NULL; g_autofree gchar *path = NULL;
rdev = fprint_device_new(device); rdev = fprint_device_new (device);
g_signal_connect (G_OBJECT(rdev), "notify::in-use", g_signal_connect (G_OBJECT (rdev), "notify::in-use",
G_CALLBACK (fprint_manager_in_use_notified), manager); G_CALLBACK (fprint_manager_in_use_notified), manager);
path = get_device_path (rdev); path = get_device_path (rdev);
@ -236,12 +255,14 @@ 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; g_autolist (FprintDBusObjectSkeleton) objects = NULL;
GList *item; GList *item;
objects = g_dbus_object_manager_get_objects (priv->object_manager); objects = g_dbus_object_manager_get_objects (priv->object_manager);
for (item = objects; item; item = item->next) { for (item = objects; item; item = item->next)
{
g_autoptr(FprintDevice) rdev = NULL; g_autoptr(FprintDevice) rdev = NULL;
g_autoptr(FpDevice) dev = NULL; g_autoptr(FpDevice) dev = NULL;
FprintDBusObjectSkeleton *object = item->data; FprintDBusObjectSkeleton *object = item->data;
@ -266,14 +287,15 @@ device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
fprint_manager_in_use_notified (NULL, NULL, manager); 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 ();
@ -323,7 +345,8 @@ 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;
@ -338,10 +361,12 @@ FprintManager *fprint_manager_new (GDBusConnection *connection, gboolean no_time
return FPRINT_MANAGER (object); return FPRINT_MANAGER (object);
} }
static gboolean fprint_manager_get_devices(FprintManager *manager, static gboolean
fprint_manager_get_devices (FprintManager *manager,
GPtrArray **devices, GError **error) 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; g_autolist (FprintDBusObjectSkeleton) objects = NULL;
GList *l; GList *l;
int num_open; int num_open;
@ -351,10 +376,12 @@ static gboolean fprint_manager_get_devices(FprintManager *manager,
objects = g_list_reverse (objects); objects = g_list_reverse (objects);
num_open = g_list_length (objects); num_open = g_list_length (objects);
devs = g_ptr_array_sized_new(num_open); devs = g_ptr_array_sized_new (num_open);
if (num_open > 0) { if (num_open > 0)
for (l = objects; l != NULL; l = l->next) { {
for (l = objects; l != NULL; l = l->next)
{
g_autoptr(FprintDevice) rdev = NULL; g_autoptr(FprintDevice) rdev = NULL;
FprintDBusObjectSkeleton *object = l->data; FprintDBusObjectSkeleton *object = l->data;
const char *path; const char *path;
@ -371,17 +398,20 @@ static gboolean fprint_manager_get_devices(FprintManager *manager,
return TRUE; return TRUE;
} }
static gboolean fprint_manager_get_default_device(FprintManager *manager, static gboolean
fprint_manager_get_default_device (FprintManager *manager,
const char **device, GError **error) 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; g_autolist (FprintDBusObjectSkeleton) objects = NULL;
int num_open; int num_open;
objects = g_dbus_object_manager_get_objects (priv->object_manager); objects = g_dbus_object_manager_get_objects (priv->object_manager);
num_open = g_list_length (objects); num_open = g_list_length (objects);
if (num_open > 0) { if (num_open > 0)
{
g_autoptr(FprintDevice) rdev = NULL; g_autoptr(FprintDevice) rdev = NULL;
FprintDBusObjectSkeleton *object = g_list_last (objects)->data; FprintDBusObjectSkeleton *object = g_list_last (objects)->data;
@ -389,7 +419,9 @@ static gboolean fprint_manager_get_default_device(FprintManager *manager,
*device = g_dbus_interface_skeleton_get_object_path ( *device = g_dbus_interface_skeleton_get_object_path (
G_DBUS_INTERFACE_SKELETON (rdev)); G_DBUS_INTERFACE_SKELETON (rdev));
return TRUE; return TRUE;
} else { }
else
{
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE,
"No devices available"); "No devices available");
*device = NULL; *device = NULL;
@ -397,10 +429,13 @@ static gboolean fprint_manager_get_default_device(FprintManager *manager,
} }
} }
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)) {
if (g_once_init_enter (&quark))
{
g_autoptr(GEnumClass) errors_enum = NULL; g_autoptr(GEnumClass) errors_enum = NULL;
GQuark domain; GQuark domain;
unsigned i; unsigned i;
@ -408,7 +443,8 @@ GQuark fprint_error_quark (void)
domain = g_quark_from_static_string ("fprintd-error-quark"); domain = g_quark_from_static_string ("fprintd-error-quark");
errors_enum = g_type_class_ref (FPRINT_TYPE_ERROR); errors_enum = g_type_class_ref (FPRINT_TYPE_ERROR);
for (i = 0; i < errors_enum->n_values; ++i) { for (i = 0; i < errors_enum->n_values; ++i)
{
GEnumValue *value = &errors_enum->values[i]; GEnumValue *value = &errors_enum->values[i];
g_dbus_error_register_error (domain, value->value, g_dbus_error_register_error (domain, value->value,

View File

@ -28,12 +28,14 @@ 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_init init;
storage_deinit deinit; storage_deinit deinit;
storage_print_data_save print_data_save; storage_print_data_save print_data_save;

View File

@ -86,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 = [

View File

@ -26,13 +26,15 @@
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); {
g_print ("Failed to connect to session bus: %s\n", error->message);
exit (1); exit (1);
} }
@ -41,55 +43,68 @@ static void create_manager(void)
"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); g_print ("Failed to get Fprintd manager: %s\n", error->message);
exit (1); 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); {
g_print ("failed to claim device: %s\n", error->message);
exit (1); 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; gboolean ignore_error = FALSE;
if (g_dbus_error_is_remote_error (error)) { if (g_dbus_error_is_remote_error (error))
{
g_autofree char *dbus_error = g_autofree char *dbus_error =
g_dbus_error_get_remote_error (error); g_dbus_error_get_remote_error (error);
if (g_str_equal (dbus_error, if (g_str_equal (dbus_error,
"net.reactivated.Fprint.Error.NoEnrolledPrints")) { "net.reactivated.Fprint.Error.NoEnrolledPrints"))
{
g_print ("No fingerprints to delete on %s\n", g_print ("No fingerprints to delete on %s\n",
fprint_dbus_device_get_name (dev)); fprint_dbus_device_get_name (dev));
ignore_error = TRUE; ignore_error = TRUE;
} }
} }
if (!ignore_error) { if (!ignore_error)
g_print("ListEnrolledFingers failed: %s\n", {
g_print ("ListEnrolledFingers failed: %s\n",
error->message); error->message);
exit (1); exit (1);
} else { }
else
{
g_print ("No fingerprints to delete on %s\n", g_print ("No fingerprints to delete on %s\n",
fprint_dbus_device_get_name (dev)); fprint_dbus_device_get_name (dev));
} }
} else { }
else
{
g_print ("Fingerprints deleted on %s\n", g_print ("Fingerprints deleted on %s\n",
fprint_dbus_device_get_name (dev)); fprint_dbus_device_get_name (dev));
} }
g_clear_error (&error); 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); {
g_print ("ReleaseDevice failed: %s\n", error->message);
exit (1); 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;
@ -98,29 +113,33 @@ static void process_devices(char **argv)
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); {
g_print ("Impossible to get devices: %s\n", error->message);
exit (1); 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]; path = devices[i];
g_print("Device at %s\n", path); 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; g_autoptr(FprintDBusDevice) dev = NULL;
guint j; 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,
@ -133,13 +152,15 @@ static void process_devices(char **argv)
} }
} }
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]); g_print ("Usage: %s <username> [usernames...]\n", argv[0]);
return 1; return 1;
} }
@ -148,4 +169,3 @@ int main(int argc, char **argv)
return 0; return 0;
} }

View File

@ -33,13 +33,15 @@ 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); {
g_print ("Failed to connect to session bus: %s\n", error->message);
exit (1); exit (1);
} }
@ -48,58 +50,67 @@ static void create_manager(void)
"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); g_print ("Failed to get Fprintd manager: %s\n", error->message);
exit (1); 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); {
g_print ("Impossible to enroll: %s\n", error->message);
exit (1); 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); g_print ("failed to connect to device: %s\n", error->message);
exit (1); 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); {
g_print ("failed to claim device: %s\n", error->message);
exit (1); 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);
g_print ("Enroll result: %s\n", result);
if (done != FALSE) if (done != FALSE)
*enroll_completed = TRUE; *enroll_completed = TRUE;
} }
static void proxy_signal_cb (GDBusProxy *proxy, static void
proxy_signal_cb (GDBusProxy *proxy,
const gchar *sender_name, const gchar *sender_name,
const gchar *signal_name, const gchar *signal_name,
GVariant *parameters, GVariant *parameters,
gpointer user_data) gpointer user_data)
{ {
if (g_str_equal (signal_name, "EnrollStatus")) { if (g_str_equal (signal_name, "EnrollStatus"))
{
const gchar *result; const gchar *result;
gboolean done; gboolean done;
@ -108,7 +119,8 @@ static void proxy_signal_cb (GDBusProxy *proxy,
} }
} }
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;
@ -119,18 +131,22 @@ static void do_enroll (FprintDBusDevice *dev)
&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) { {
if (g_strcmp0 (fingers[i].dbus_name, finger_name) == 0)
{
found = TRUE; found = TRUE;
break; break;
} }
} }
if (!found) { if (!found)
{
g_autoptr(GString) s = NULL; 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); g_string_append_printf (s, "%s", fingers[i].dbus_name);
if (fingers[i + 1].dbus_name != NULL) if (fingers[i + 1].dbus_name != NULL)
g_string_append (s, ", "); g_string_append (s, ", ");
@ -139,29 +155,33 @@ static void do_enroll (FprintDBusDevice *dev)
exit (1); 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); {
g_print ("EnrollStart failed: %s\n", error->message);
exit (1); 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); {
g_print ("ReleaseDevice failed: %s\n", error->message);
exit (1); exit (1);
} }
} }
@ -172,10 +192,12 @@ static const GOptionEntry entries[] = {
{ 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; g_autoptr(GError) err = NULL;
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
@ -183,21 +205,21 @@ int main(int argc, char **argv)
context = g_option_context_new ("Enroll a fingerprint"); context = g_option_context_new ("Enroll 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); g_print ("couldn't parse command-line options: %s\n", err->message);
return 1; return 1;
} }
if (finger_name == NULL) if (finger_name == NULL)
finger_name = g_strdup("right-index-finger"); finger_name = g_strdup ("right-index-finger");
create_manager(); create_manager ();
dev = open_device (usernames ? usernames[0] : ""); dev = open_device (usernames ? usernames[0] : "");
do_enroll(dev); do_enroll (dev);
release_device(dev); release_device (dev);
g_free(finger_name); g_free (finger_name);
g_strfreev(usernames); g_strfreev (usernames);
return 0; return 0;
} }

View File

@ -26,13 +26,15 @@
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); {
g_print ("Failed to connect to session bus: %s\n", error->message);
exit (1); exit (1);
} }
@ -41,13 +43,15 @@ static void create_manager(void)
"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); g_print ("Failed to get Fprintd manager: %s\n", error->message);
exit (1); 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;
@ -55,40 +59,43 @@ static void list_fingerprints (FprintDBusDevice *dev, const char *username)
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; gboolean ignore_error = FALSE;
if (g_dbus_error_is_remote_error (error)) { if (g_dbus_error_is_remote_error (error))
{
g_autofree char *dbus_error = g_autofree char *dbus_error =
g_dbus_error_get_remote_error (error); g_dbus_error_get_remote_error (error);
if (g_str_equal (dbus_error, if (g_str_equal (dbus_error,
"net.reactivated.Fprint.Error.NoEnrolledPrints")) { "net.reactivated.Fprint.Error.NoEnrolledPrints"))
ignore_error = TRUE; ignore_error = TRUE;
} }
}
if (!ignore_error) { if (!ignore_error)
g_print("ListEnrolledFingers failed: %s\n", error->message); {
g_print ("ListEnrolledFingers failed: %s\n", error->message);
exit (1); 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, g_print ("User %s has no fingers enrolled for %s.\n", username,
fprint_dbus_device_get_name (dev)); fprint_dbus_device_get_name (dev));
return; 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;
@ -97,29 +104,33 @@ static void process_devices(char **argv)
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); {
g_print ("Impossible to get devices: %s\n", error->message);
exit (1); 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]; path = devices[i];
g_print("Device at %s\n", path); 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; g_autoptr(FprintDBusDevice) dev = NULL;
guint j; 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,
@ -132,13 +143,15 @@ static void process_devices(char **argv)
} }
} }
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]); g_print ("Usage: %s <username> [usernames...]\n", argv[0]);
return 1; return 1;
} }
@ -147,4 +160,3 @@ int main(int argc, char **argv)
return 0; return 0;
} }

View File

@ -31,13 +31,15 @@ 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); {
g_print ("Failed to connect to session bus: %s\n", error->message);
exit (1); exit (1);
} }
@ -46,45 +48,51 @@ static void create_manager(void)
"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); g_print ("Failed to get Fprintd manager: %s\n", error->message);
exit (1); 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); {
g_print ("Impossible to verify: %s\n", error->message);
exit (1); 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); g_print ("failed to connect to device: %s\n", error->message);
exit (1); 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); {
g_print ("failed to claim device: %s\n", error->message);
exit (1); 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;
@ -92,64 +100,74 @@ static void find_finger (FprintDBusDevice *dev, const char *username)
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); {
g_print ("ListEnrolledFingers failed: %s\n", error->message);
exit (1); 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, {
g_print ("Finger '%s' not enrolled for user %s.\n", finger_name,
username); username);
g_free (finger_name); g_free (finger_name);
exit(1); exit (1);
} }
if (finger_name == NULL) { if (finger_name == NULL)
finger_name = g_strdup (fingers[0]); finger_name = g_strdup (fingers[0]);
}
} }
struct VerifyState { struct VerifyState
{
GError *error; GError *error;
gboolean started; gboolean started;
gboolean completed; gboolean completed;
}; };
static void verify_result(GObject *object, const char *result, gboolean done, void *user_data) static void
verify_result (GObject *object, const char *result, gboolean done, void *user_data)
{ {
struct VerifyState *verify_state = user_data; struct VerifyState *verify_state = user_data;
g_print("Verify result: %s (%s)\n", result, done ? "done" : "not done");
g_print ("Verify result: %s (%s)\n", result, done ? "done" : "not done");
if (done != FALSE) if (done != FALSE)
verify_state->completed = TRUE; 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 verify_started_cb (GObject *obj, static void
verify_started_cb (GObject *obj,
GAsyncResult *res, GAsyncResult *res,
gpointer user_data) gpointer user_data)
{ {
struct VerifyState *verify_state = user_data; struct VerifyState *verify_state = user_data;
if (fprint_dbus_device_call_verify_start_finish (FPRINT_DBUS_DEVICE (obj), res, &verify_state->error)) if (fprint_dbus_device_call_verify_start_finish (FPRINT_DBUS_DEVICE (obj), res, &verify_state->error))
{
g_print ("Verify started!\n");
verify_state->started = TRUE; verify_state->started = TRUE;
}
} }
static void proxy_signal_cb (GDBusProxy *proxy, static void
proxy_signal_cb (GDBusProxy *proxy,
const gchar *sender_name, const gchar *sender_name,
const gchar *signal_name, const gchar *signal_name,
GVariant *parameters, GVariant *parameters,
@ -160,13 +178,16 @@ static void proxy_signal_cb (GDBusProxy *proxy,
if (!verify_state->started) if (!verify_state->started)
return; return;
if (g_str_equal (signal_name, "VerifyStatus")) { if (g_str_equal (signal_name, "VerifyStatus"))
{
const gchar *result; const gchar *result;
gboolean done; gboolean done;
g_variant_get (parameters, "(&sb)", &result, &done); g_variant_get (parameters, "(&sb)", &result, &done);
verify_result (G_OBJECT (proxy), result, done, user_data); verify_result (G_OBJECT (proxy), result, done, user_data);
} else if (g_str_equal (signal_name, "VerifyFingerSelected")) { }
else if (g_str_equal (signal_name, "VerifyFingerSelected"))
{
const gchar *name; const gchar *name;
g_variant_get (parameters, "(&s)", &name); g_variant_get (parameters, "(&s)", &name);
@ -174,7 +195,8 @@ static void proxy_signal_cb (GDBusProxy *proxy,
} }
} }
static void do_verify (FprintDBusDevice *dev) static void
do_verify (FprintDBusDevice *dev)
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
struct VerifyState verify_state = { 0 }; struct VerifyState verify_state = { 0 };
@ -199,34 +221,37 @@ static void do_verify (FprintDBusDevice *dev)
/* Wait for verify start while discarding any VerifyStatus signals */ /* Wait for verify start while discarding any VerifyStatus signals */
while (!verify_state.started && !verify_state.error) while (!verify_state.started && !verify_state.error)
g_main_context_iteration(NULL, TRUE); g_main_context_iteration (NULL, TRUE);
if (verify_state.error) { if (verify_state.error)
g_print("VerifyStart failed: %s\n", verify_state.error->message); {
g_print ("VerifyStart failed: %s\n", verify_state.error->message);
g_clear_error (&verify_state.error); g_clear_error (&verify_state.error);
exit (1); exit (1);
} }
g_print("Verify started!\n");
/* VerifyStatus signals are processing, wait for completion. */ /* VerifyStatus signals are processing, wait for completion. */
while (!verify_state.completed) while (!verify_state.completed)
g_main_context_iteration(NULL, TRUE); g_main_context_iteration (NULL, TRUE);
g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb, g_signal_handlers_disconnect_by_func (dev, proxy_signal_cb,
&verify_state); &verify_state);
if (!fprint_dbus_device_call_verify_stop_sync (dev, NULL, &error)) { if (!fprint_dbus_device_call_verify_stop_sync (dev, NULL, &error))
g_print("VerifyStop failed: %s\n", error->message); {
g_print ("VerifyStop failed: %s\n", error->message);
exit (1); 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); {
g_print ("ReleaseDevice failed: %s\n", error->message);
exit (1); exit (1);
} }
} }
@ -238,7 +263,8 @@ static const GOptionEntry entries[] = {
{ 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;
@ -250,18 +276,19 @@ int main(int argc, char **argv)
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); g_print ("couldn't parse command-line options: %s\n", err->message);
return 1; 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);
@ -269,12 +296,11 @@ int main(int argc, char **argv)
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;
} }