device.c 41.6 KB
Newer Older
Daniel Drake's avatar
Daniel Drake committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * /net/reactivated/Fprint/Device/foo object implementation
 * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

20
21
#include "config.h"

Daniel Drake's avatar
Daniel Drake committed
22
#include <dbus/dbus-glib-bindings.h>
23
24
#include <dbus/dbus-glib-lowlevel.h>
#include <glib/gi18n.h>
25
#include <gio/gio.h>
Bastien Nocera's avatar
Bastien Nocera committed
26
#include <polkit/polkit.h>
Benjamin Berg's avatar
Benjamin Berg committed
27
#include <fprint.h>
Daniel Drake's avatar
Daniel Drake committed
28

29
30
#include <sys/types.h>
#include <pwd.h>
31
#include <errno.h>
32

33
#include "fprintd-marshal.h"
Daniel Drake's avatar
Daniel Drake committed
34
#include "fprintd.h"
35
#include "storage.h"
Daniel Drake's avatar
Daniel Drake committed
36

37
static const char *FINGERS_NAMES[] = {
Benjamin Berg's avatar
Benjamin Berg committed
38
	[FP_FINGER_UNKNOWN] = "unknown",
39
40
41
42
43
44
45
46
47
48
49
50
	"left-thumb",
	"left-index-finger",
	"left-middle-finger",
	"left-ring-finger",
	"left-little-finger",
	"right-thumb",
	"right-index-finger",
	"right-middle-finger",
	"right-ring-finger",
	"right-little-finger"
};

51
52
extern DBusGConnection *fprintd_dbus_conn;

Bastien Nocera's avatar
Bastien Nocera committed
53
static void fprint_device_claim(FprintDevice *rdev,
54
55
				const char *username,
				DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
56
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
57
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
58
static void fprint_device_verify_start(FprintDevice *rdev,
59
	const char *finger_name, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
60
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
61
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
62
static void fprint_device_enroll_start(FprintDevice *rdev,
63
	const char *finger_name, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
64
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
65
	DBusGMethodInvocation *context);
66
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev, 
67
68
						const char *username,
						DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
69
static void fprint_device_delete_enrolled_fingers(FprintDevice *rdev,
70
71
						  const char *username,
						  DBusGMethodInvocation *context);
72
73
static void fprint_device_delete_enrolled_fingers2(FprintDevice *rdev,
						    DBusGMethodInvocation *context);
Daniel Drake's avatar
Daniel Drake committed
74
75
76

#include "device-dbus-glue.h"

Bastien Nocera's avatar
Bastien Nocera committed
77
78
79
typedef enum {
	ACTION_NONE = 0,
	ACTION_IDENTIFY,
Bastien Nocera's avatar
Bastien Nocera committed
80
81
	ACTION_VERIFY,
	ACTION_ENROLL
Bastien Nocera's avatar
Bastien Nocera committed
82
83
} FprintDeviceAction;

84
typedef struct {
85
86
	/* current method invocation */
	DBusGMethodInvocation *context;
Daniel Drake's avatar
Daniel Drake committed
87

88
89
90
91
92
93
	/* The current user of the device, if claimed */
	char *sender;

	/* The current user of the device, or if allowed,
	 * what was passed as a username argument */
	char *username;
94
} SessionData;
Daniel Drake's avatar
Daniel Drake committed
95

96
typedef struct {
Daniel Drake's avatar
Daniel Drake committed
97
	guint32 id;
Benjamin Berg's avatar
Benjamin Berg committed
98
	FpDevice *dev;
99
	SessionData *session;
100

Matthias Clasen's avatar
Matthias Clasen committed
101
	PolkitAuthority *auth;
Bastien Nocera's avatar
Bastien Nocera committed
102

103
104
105
	/* Hashtable of connected clients */
	GHashTable *clients;

Benjamin Berg's avatar
Benjamin Berg committed
106
107
108
	/* Required to restart the operation on a retry failure. */
	FpPrint   *verify_data;
	GPtrArray *identify_data;
109
	int enroll_data;
Bastien Nocera's avatar
Bastien Nocera committed
110

Bastien Nocera's avatar
Bastien Nocera committed
111
	/* whether we're running an identify, or a verify */
Bastien Nocera's avatar
Bastien Nocera committed
112
	FprintDeviceAction current_action;
Benjamin Berg's avatar
Benjamin Berg committed
113
114
	GCancellable *current_cancellable;
	DBusGMethodInvocation *current_cancel_context;
115
116
	/* Whether the device was disconnected */
	gboolean disconnected;
117
} FprintDevicePrivate;
Daniel Drake's avatar
Daniel Drake committed
118

119
G_DEFINE_TYPE_WITH_CODE(FprintDevice, fprint_device, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintDevice));
Daniel Drake's avatar
Daniel Drake committed
120
121

enum fprint_device_properties {
Benjamin Berg's avatar
Benjamin Berg committed
122
	FPRINT_DEVICE_CONSTRUCT_DEV = 1,
123
	FPRINT_DEVICE_IN_USE,
124
125
126
	FPRINT_DEVICE_NAME,
	FPRINT_DEVICE_NUM_ENROLL,
	FPRINT_DEVICE_SCAN_TYPE
Daniel Drake's avatar
Daniel Drake committed
127
128
};

129
enum fprint_device_signals {
Daniel Drake's avatar
Daniel Drake committed
130
	SIGNAL_VERIFY_STATUS,
Bastien Nocera's avatar
Bastien Nocera committed
131
	SIGNAL_VERIFY_FINGER_SELECTED,
Daniel Drake's avatar
Daniel Drake committed
132
	SIGNAL_ENROLL_STATUS,
133
134
135
	NUM_SIGNALS,
};

Daniel Drake's avatar
Daniel Drake committed
136
static guint32 last_id = ~0;
137
static guint signals[NUM_SIGNALS] = { 0, };
Daniel Drake's avatar
Daniel Drake committed
138

139
140
141
142
143
144
145
146
147
static void session_data_free(SessionData *session)
{
	g_clear_pointer(&session->sender, g_free);
	g_clear_pointer(&session->username, g_free);
	g_nullify_pointer((gpointer *) &session->context);
	g_free(session);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC(SessionData, session_data_free);

148
static void fprint_device_finalize(GObject *object)
Daniel Drake's avatar
Daniel Drake committed
149
{
150
	FprintDevice *self = (FprintDevice *) object;
151
	FprintDevicePrivate *priv = fprint_device_get_instance_private(self);
152
153

	g_hash_table_destroy (priv->clients);
154
	g_clear_pointer(&priv->session, session_data_free);
Daniel Drake's avatar
Daniel Drake committed
155
	/* FIXME close and stuff */
156
157

	G_OBJECT_CLASS(fprint_device_parent_class)->finalize(object);
Daniel Drake's avatar
Daniel Drake committed
158
159
}

160
static void fprint_device_set_property(GObject *object, guint property_id,
Daniel Drake's avatar
Daniel Drake committed
161
162
163
	const GValue *value, GParamSpec *pspec)
{
	FprintDevice *self = (FprintDevice *) object;
164
	FprintDevicePrivate *priv = fprint_device_get_instance_private(self);
Daniel Drake's avatar
Daniel Drake committed
165
166

	switch (property_id) {
Benjamin Berg's avatar
Benjamin Berg committed
167
168
	case FPRINT_DEVICE_CONSTRUCT_DEV:
		priv->dev = g_value_dup_object(value);
Daniel Drake's avatar
Daniel Drake committed
169
170
171
172
173
174
175
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
		break;
	}
}

Bastien Nocera's avatar
Bastien Nocera committed
176
177
178
179
static void fprint_device_get_property(GObject *object, guint property_id,
				       GValue *value, GParamSpec *pspec)
{
	FprintDevice *self = (FprintDevice *) object;
180
	FprintDevicePrivate *priv = fprint_device_get_instance_private(self);
Bastien Nocera's avatar
Bastien Nocera committed
181
182

	switch (property_id) {
Benjamin Berg's avatar
Benjamin Berg committed
183
184
185
	case FPRINT_DEVICE_CONSTRUCT_DEV:
		g_value_set_object(value, priv->dev);
		break;
186
187
	case FPRINT_DEVICE_IN_USE:
		g_value_set_boolean(value, g_hash_table_size (priv->clients) != 0);
Bastien Nocera's avatar
Bastien Nocera committed
188
		break;
189
	case FPRINT_DEVICE_NAME:
Benjamin Berg's avatar
Benjamin Berg committed
190
		g_value_set_static_string (value, fp_device_get_name (priv->dev));
191
192
193
		break;
	case FPRINT_DEVICE_NUM_ENROLL:
		if (priv->dev)
Benjamin Berg's avatar
Benjamin Berg committed
194
			g_value_set_int (value, fp_device_get_nr_enroll_stages (priv->dev));
195
196
197
198
199
200
		else
			g_value_set_int (value, -1);
		break;
	case FPRINT_DEVICE_SCAN_TYPE: {
		const char *type;

Benjamin Berg's avatar
Benjamin Berg committed
201
		if (fp_device_get_scan_type (priv->dev) == FP_SCAN_TYPE_PRESS)
202
203
204
205
206
207
208
			type = "press";
		else
			type = "swipe";

		g_value_set_static_string (value, type);
		break;
	}
Bastien Nocera's avatar
Bastien Nocera committed
209
210
211
212
213
214
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
		break;
	}
}

215
static void fprint_device_class_init(FprintDeviceClass *klass)
Daniel Drake's avatar
Daniel Drake committed
216
217
218
219
220
221
222
{
	GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
	GParamSpec *pspec;

	dbus_g_object_type_install_info(FPRINT_TYPE_DEVICE,
		&dbus_glib_fprint_device_object_info);

223
224
	gobject_class->finalize = fprint_device_finalize;
	gobject_class->set_property = fprint_device_set_property;
Bastien Nocera's avatar
Bastien Nocera committed
225
	gobject_class->get_property = fprint_device_get_property;
Daniel Drake's avatar
Daniel Drake committed
226

Benjamin Berg's avatar
Benjamin Berg committed
227
228
229
230
	pspec = g_param_spec_object("dev", "Device",
				     "Set device construction property",
				     FP_TYPE_DEVICE,
				     G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_READABLE);
Daniel Drake's avatar
Daniel Drake committed
231
	g_object_class_install_property(gobject_class,
Benjamin Berg's avatar
Benjamin Berg committed
232
					FPRINT_DEVICE_CONSTRUCT_DEV, pspec);
233

234
	pspec = g_param_spec_boolean("in-use", "In use",
235
236
				     "Whether the device is currently in use", FALSE,
				     G_PARAM_READABLE);
Bastien Nocera's avatar
Bastien Nocera committed
237
	g_object_class_install_property(gobject_class,
238
					FPRINT_DEVICE_IN_USE, pspec);
Daniel Drake's avatar
Daniel Drake committed
239

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
	pspec = g_param_spec_string("name", "Name",
				    "The product name of the device", NULL,
				    G_PARAM_READABLE);
	g_object_class_install_property(gobject_class,
					FPRINT_DEVICE_NAME, pspec);

	pspec = g_param_spec_string("scan-type", "Scan Type",
				    "The scan type of the device", "press",
				    G_PARAM_READABLE);
	g_object_class_install_property(gobject_class,
					FPRINT_DEVICE_SCAN_TYPE, pspec);

	pspec = g_param_spec_int("num-enroll-stages", "Number of enrollments stages",
				  "Number of enrollment stages for the device.",
				  -1, G_MAXINT, -1, G_PARAM_READABLE);
	g_object_class_install_property(gobject_class,
					FPRINT_DEVICE_NUM_ENROLL, pspec);

Daniel Drake's avatar
Daniel Drake committed
258
259
	signals[SIGNAL_VERIFY_STATUS] = g_signal_new("verify-status",
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
260
		fprintd_marshal_VOID__STRING_BOOLEAN, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
Daniel Drake's avatar
Daniel Drake committed
261
	signals[SIGNAL_ENROLL_STATUS] = g_signal_new("enroll-status",
262
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
263
		fprintd_marshal_VOID__STRING_BOOLEAN, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
Bastien Nocera's avatar
Bastien Nocera committed
264
265
	signals[SIGNAL_VERIFY_FINGER_SELECTED] = g_signal_new("verify-finger-selected",
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
266
		g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
Daniel Drake's avatar
Daniel Drake committed
267
268
}

269
static void fprint_device_init(FprintDevice *device)
Daniel Drake's avatar
Daniel Drake committed
270
{
271
	FprintDevicePrivate *priv = fprint_device_get_instance_private(device);
Daniel Drake's avatar
Daniel Drake committed
272
	priv->id = ++last_id;
Bastien Nocera's avatar
Bastien Nocera committed
273
274

	/* Setup PolicyKit */
275
	priv->auth = polkit_authority_get_sync (NULL, NULL);
276
277
278
	priv->clients = g_hash_table_new_full (g_str_hash,
					       g_str_equal,
					       g_free,
279
					       NULL);
Daniel Drake's avatar
Daniel Drake committed
280
281
}

Benjamin Berg's avatar
Benjamin Berg committed
282
FprintDevice *fprint_device_new(FpDevice *dev)
Daniel Drake's avatar
Daniel Drake committed
283
{
Benjamin Berg's avatar
Benjamin Berg committed
284
	return g_object_new(FPRINT_TYPE_DEVICE, "dev", dev, NULL);
Daniel Drake's avatar
Daniel Drake committed
285
286
287
288
}

guint32 _fprint_device_get_id(FprintDevice *rdev)
{
289
290
291
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);

	return priv->id;
Daniel Drake's avatar
Daniel Drake committed
292
293
}

294
295
296
297
298
static const char *
finger_num_to_name (int finger_num)
{
	if (finger_num == -1)
		return "any";
299
	if (!FP_FINGER_IS_VALID (finger_num))
300
		return NULL;
301
	return FINGERS_NAMES[finger_num];
302
303
304
305
306
307
308
309
310
311
}

static int
finger_name_to_num (const char *finger_name)
{
	guint i;

	if (finger_name == NULL || *finger_name == '\0' || g_str_equal (finger_name, "any"))
		return -1;

312
	for (i = FP_FINGER_FIRST; i <= FP_FINGER_LAST; i++) {
313
		if (g_str_equal (finger_name, FINGERS_NAMES[i]))
Benjamin Berg's avatar
Benjamin Berg committed
314
			return i;
315
316
317
318
319
320
	}

	/* Invalid, let's try that */
	return -1;
}

321
static const char *
Benjamin Berg's avatar
Benjamin Berg committed
322
verify_result_to_name (gboolean match, GError *error)
323
{
Benjamin Berg's avatar
Benjamin Berg committed
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
	if (!error) {
		if (match)
			return "verify-match";
		else
			return "verify-no-match";
	}

	if (error->domain == FP_DEVICE_RETRY) {
		switch (error->code) {
			case FP_DEVICE_RETRY_TOO_SHORT:
				return "verify-swipe-too-short";
			case FP_DEVICE_RETRY_CENTER_FINGER:
				return "verify-finger-not-centered";
			case FP_DEVICE_RETRY_REMOVE_FINGER:
				return "verify-remove-and-retry";
			default:
				return "verify-retry-scan";
		}
	} else {
		/* Which errors should be mapped to disconnection?
		 * Are drivers/libfprint/fprintd really in agreement here?
		 */
		if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO))
			return "verify-disconnect";
348
349
		else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			return "verify-no-match";
Benjamin Berg's avatar
Benjamin Berg committed
350

351
352
353
354
355
		return "verify-unknown-error";
	}
}

static const char *
Benjamin Berg's avatar
Benjamin Berg committed
356
enroll_result_to_name (gboolean completed, gboolean enrolled, GError *error)
357
{
Benjamin Berg's avatar
Benjamin Berg committed
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
	if (!error) {
		if (!completed)
			return "enroll-stage-passed";
		else if (enrolled)
			return "enroll-completed";
		else
			return "enroll-failed";
	}

	if (error->domain == FP_DEVICE_RETRY) {
		switch (error->code) {
			case FP_DEVICE_RETRY_TOO_SHORT:
				return "enroll-swipe-too-short";
			case FP_DEVICE_RETRY_CENTER_FINGER:
				return "enroll-finger-not-centered";
			case FP_DEVICE_RETRY_REMOVE_FINGER:
				return "verify-remove-and-retry";
			default:
				return "enroll-remove-and-retry";
		}
	} else {
		/* Which errors should be mapped to disconnection?
		 * Are drivers/libfprint/fprintd really in agreement here?
		 */
		if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO))
			return "enroll-disconnected";
384
385
		else if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_FULL))
			return "enroll-data-full";
386
387
		else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			return "enroll-failed";
Benjamin Berg's avatar
Benjamin Berg committed
388

389
390
391
392
		return "enroll-unknown-error";
	}
}

393
394
395
396
397
398
399
400
static void
set_disconnected (FprintDevicePrivate *priv, const char *res)
{
	if (g_str_equal (res, "enroll-disconnected") ||
	    g_str_equal (res, "verify-disconnected"))
		priv->disconnected = TRUE;
}

401
402
403
404
405
static gboolean
_fprint_device_check_claimed (FprintDevice *rdev,
			      DBusGMethodInvocation *context,
			      GError **error)
{
406
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
407
408
409
410
	char *sender;
	gboolean retval;

	/* The device wasn't claimed, exit */
411
	if (priv->session == NULL) {
412
413
414
415
416
417
		g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			     _("Device was not claimed before use"));
		return FALSE;
	}

	sender = dbus_g_method_get_sender (context);
418
	retval = g_str_equal (sender, priv->session->sender);
419
420
	g_free (sender);

421
422
	if (retval == FALSE ||
	    priv->session->context != NULL) {
423
424
425
426
427
428
429
		g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
			     _("Device already in use by another user"));
	}

	return retval;
}

Bastien Nocera's avatar
Bastien Nocera committed
430
static gboolean
Bastien Nocera's avatar
Bastien Nocera committed
431
_fprint_device_check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, const char *action, GError **error)
Bastien Nocera's avatar
Bastien Nocera committed
432
{
433
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
434
	char *sender;
Matthias Clasen's avatar
Matthias Clasen committed
435
436
437
	PolkitSubject *subject;
	PolkitAuthorizationResult *result;
	GError *_error = NULL;
Bastien Nocera's avatar
Bastien Nocera committed
438
439
440

	/* Check that caller is privileged */
	sender = dbus_g_method_get_sender (context);
Matthias Clasen's avatar
Matthias Clasen committed
441
	subject = polkit_system_bus_name_new (sender);
442
	g_free (sender);
Matthias Clasen's avatar
Matthias Clasen committed
443
444
445
446
447
448
449
450
451
452

	result = polkit_authority_check_authorization_sync (priv->auth,
                                                            subject,
                                                            action,
							    NULL,
                                                            POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
					                    NULL, &_error);
	g_object_unref (subject);

	if (result == NULL) {
Bastien Nocera's avatar
Bastien Nocera committed
453
		g_set_error (error, FPRINT_ERROR,
Matthias Clasen's avatar
Matthias Clasen committed
454
455
456
			     FPRINT_ERROR_PERMISSION_DENIED,
			     "Not Authorized: %s", _error->message);
		g_error_free (_error);
Bastien Nocera's avatar
Bastien Nocera committed
457
458
459
		return FALSE;
	}

Matthias Clasen's avatar
Matthias Clasen committed
460
	if (!polkit_authorization_result_get_is_authorized (result)) {
Bastien Nocera's avatar
Bastien Nocera committed
461
		g_set_error (error, FPRINT_ERROR,
462
			     FPRINT_ERROR_PERMISSION_DENIED,
Matthias Clasen's avatar
Matthias Clasen committed
463
464
			     "Not Authorized: %s", action);
		g_object_unref (result);
Bastien Nocera's avatar
Bastien Nocera committed
465
466
467
		return FALSE;
	}

Matthias Clasen's avatar
Matthias Clasen committed
468
469
	g_object_unref (result);

Bastien Nocera's avatar
Bastien Nocera committed
470
471
472
	return TRUE;
}

Bastien Nocera's avatar
Bastien Nocera committed
473
474
475
476
477
478
479
480
481
482
static gboolean
_fprint_device_check_polkit_for_actions (FprintDevice *rdev,
					 DBusGMethodInvocation *context,
					 const char *action1,
					 const char *action2,
					 GError **error)
{
	if (_fprint_device_check_polkit_for_action (rdev, context, action1, error) != FALSE)
		return TRUE;

483
	g_clear_error (error);
Bastien Nocera's avatar
Bastien Nocera committed
484
485
486
487

	return _fprint_device_check_polkit_for_action (rdev, context, action2, error);
}

488
489
490
491
492
493
static char *
_fprint_device_check_for_username (FprintDevice *rdev,
				   DBusGMethodInvocation *context,
				   const char *username,
				   char **ret_sender,
				   GError **error)
Bastien Nocera's avatar
Bastien Nocera committed
494
{
495
496
497
498
499
	DBusConnection *conn;
	DBusError dbus_error;
	char *sender;
	unsigned long uid;
	struct passwd *user;
Bastien Nocera's avatar
Bastien Nocera committed
500

501
502
503
504
505
	/* Get details about the current sender, and username/uid */
	conn = dbus_g_connection_get_connection (fprintd_dbus_conn);
	sender = dbus_g_method_get_sender (context);
	dbus_error_init (&dbus_error);
	uid = dbus_bus_get_unix_user (conn, sender, &dbus_error);
Bastien Nocera's avatar
Bastien Nocera committed
506

507
508
509
510
	if (dbus_error_is_set(&dbus_error)) {
		g_free (sender);
		dbus_set_g_error (error, &dbus_error);
		return NULL;
Bastien Nocera's avatar
Bastien Nocera committed
511
512
	}

513
514
515
	user = getpwuid (uid);
	if (user == NULL) {
		g_free (sender);
516
		g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL,
517
518
519
520
521
522
523
			    "Failed to get information about user UID %lu", uid);
		return NULL;
	}

	/* The current user is usually allowed to access their
	 * own data, this should be followed by PolicyKit checks
	 * anyway */
524
	if (username == NULL || *username == '\0' || g_str_equal (username, user->pw_name)) {
525
526
527
528
		if (ret_sender != NULL)
			*ret_sender = sender;
		else
			g_free (sender);
529
		return g_strdup (user->pw_name);
530
531
532
533
534
535
536
	}

	/* If we're not allowed to set a different username,
	 * then fail */
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.setusername", error) == FALSE) {
		g_free (sender);
		return NULL;
Bastien Nocera's avatar
Bastien Nocera committed
537
538
	}

539
540
541
542
	if (ret_sender != NULL)
		*ret_sender = sender;
	else
		g_free (sender);
Bastien Nocera's avatar
Bastien Nocera committed
543

544
	return g_strdup (username);
Bastien Nocera's avatar
Bastien Nocera committed
545
546
}

547
static void
548
549
550
_fprint_device_client_vanished (GDBusConnection *connection,
				const char *name,
				FprintDevice *rdev)
551
{
Benjamin Berg's avatar
Benjamin Berg committed
552
	g_autoptr(GError) error = NULL;
553
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
554

555
	/* Was that the client that claimed the device? */
556
557
	if (priv->session != NULL &&
	    g_strcmp0 (priv->session->sender, name) == 0) {
Benjamin Berg's avatar
Benjamin Berg committed
558
559
		while (priv->current_action != ACTION_NONE) {
			g_cancellable_cancel (priv->current_cancellable);
Bastien Nocera's avatar
Bastien Nocera committed
560

Benjamin Berg's avatar
Benjamin Berg committed
561
			g_main_context_iteration (NULL, TRUE);
562
		}
563

Benjamin Berg's avatar
Benjamin Berg committed
564
		if (!fp_device_close_sync (priv->dev, NULL, &error))
565
			g_debug ("Error closing device after disconnect: %s", error->message);
Benjamin Berg's avatar
Benjamin Berg committed
566

567
		g_clear_pointer(&priv->session, session_data_free);
568
	}
569
	g_hash_table_remove (priv->clients, name);
570
571
572
573
574
575
576
577
578

	if (g_hash_table_size (priv->clients) == 0) {
		g_object_notify (G_OBJECT (rdev), "in-use");
	}
}

static void
_fprint_device_add_client (FprintDevice *rdev, const char *sender)
{
579
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
580
581
582
583
584
585
586
587
588
589
590
591
	guint id;

	id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->clients, sender));
	if (id == 0) {
		id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
				       sender,
				       G_BUS_NAME_WATCHER_FLAGS_NONE,
				       NULL,
				       (GBusNameVanishedCallback) _fprint_device_client_vanished,
				       rdev,
				       NULL);
		g_hash_table_insert (priv->clients, g_strdup (sender), GUINT_TO_POINTER(id));
592
593
594
595
		g_object_notify (G_OBJECT (rdev), "in-use");
	}
}

Benjamin Berg's avatar
Benjamin Berg committed
596
static void dev_open_cb(FpDevice *dev, GAsyncResult *res, void *user_data)
Daniel Drake's avatar
Daniel Drake committed
597
{
Benjamin Berg's avatar
Benjamin Berg committed
598
	g_autoptr(GError) error = NULL;
Daniel Drake's avatar
Daniel Drake committed
599
	FprintDevice *rdev = user_data;
600
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
601
	DBusGMethodInvocation *context = g_steal_pointer(&priv->session->context);
Daniel Drake's avatar
Daniel Drake committed
602

Benjamin Berg's avatar
Benjamin Berg committed
603
604
	if (!fp_device_open_finish (dev, res, &error)) {
		g_autoptr(GError) dbus_error = NULL;
605

Benjamin Berg's avatar
Benjamin Berg committed
606
607
608
		dbus_error = g_error_new (FPRINT_ERROR,
		                          FPRINT_ERROR_INTERNAL,
		                          "Open failed with error: %s", error->message);
609
610
		dbus_g_method_return_error(context, dbus_error);
		g_clear_pointer(&priv->session, session_data_free);
Daniel Drake's avatar
Daniel Drake committed
611
612
613
		return;
	}

Benjamin Berg's avatar
Benjamin Berg committed
614
615
	g_debug("claimed device %d", priv->id);

616
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
617
618
}

Bastien Nocera's avatar
Bastien Nocera committed
619
static void fprint_device_claim(FprintDevice *rdev,
620
621
				const char *username,
				DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
622
{
623
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
Daniel Drake's avatar
Daniel Drake committed
624
	GError *error = NULL;
625
	char *sender, *user;
Daniel Drake's avatar
Daniel Drake committed
626

627
	/* Is it already claimed? */
628
	if (priv->session) {
629
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
630
631
			    "Device was already claimed");
		dbus_g_method_return_error(context, error);
632
		g_error_free(error);
Bastien Nocera's avatar
Bastien Nocera committed
633
		return;
634
635
	}

636
	g_assert_null(priv->session);
Bastien Nocera's avatar
Bastien Nocera committed
637

638
639
640
641
642
643
644
	sender = NULL;
	user = _fprint_device_check_for_username (rdev,
						  context,
						  username,
						  &sender,
						  &error);
	if (user == NULL) {
645
		g_free (sender);
646
		dbus_g_method_return_error (context, error);
647
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
648
		return;
649
650
	}

651
652
653
654
	if (_fprint_device_check_polkit_for_actions (rdev, context,
						     "net.reactivated.fprint.device.verify",
						     "net.reactivated.fprint.device.enroll",
						     &error) == FALSE) {
655
		g_free (sender);
656
657
		g_free (user);
		dbus_g_method_return_error (context, error);
658
		g_error_free (error);
659
660
661
		return;
	}

662
663
	_fprint_device_add_client (rdev, sender);

664
	priv->session = g_new0(SessionData, 1);
665
666
667
668
669
	priv->session->context = context;
	priv->session->username = user;
	priv->session->sender = sender;

	g_debug ("user '%s' claiming the device: %d", priv->session->username, priv->id);
Daniel Drake's avatar
Daniel Drake committed
670

Benjamin Berg's avatar
Benjamin Berg committed
671
	fp_device_open (priv->dev, NULL, (GAsyncReadyCallback) dev_open_cb, rdev);
Daniel Drake's avatar
Daniel Drake committed
672
673
}

Benjamin Berg's avatar
Benjamin Berg committed
674
static void dev_close_cb(FpDevice *dev, GAsyncResult *res, void *user_data)
Daniel Drake's avatar
Daniel Drake committed
675
{
Benjamin Berg's avatar
Benjamin Berg committed
676
	g_autoptr(GError) error = NULL;
Daniel Drake's avatar
Daniel Drake committed
677
	FprintDevice *rdev = user_data;
678
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
679
680
	g_autoptr(SessionData) session = g_steal_pointer(&priv->session);
	DBusGMethodInvocation *context = g_steal_pointer(&session->context);
Daniel Drake's avatar
Daniel Drake committed
681

Benjamin Berg's avatar
Benjamin Berg committed
682
683
	if (!fp_device_close_finish (dev, res, &error)) {
		g_autoptr(GError) dbus_error = NULL;
Daniel Drake's avatar
Daniel Drake committed
684

Benjamin Berg's avatar
Benjamin Berg committed
685
686
687
		dbus_error = g_error_new (FPRINT_ERROR,
		                          FPRINT_ERROR_INTERNAL,
		                          "Release failed with error: %s", error->message);
688
		dbus_g_method_return_error(context, dbus_error);
Benjamin Berg's avatar
Benjamin Berg committed
689
690
		return;
	}
691

692
	g_debug("released device %d", priv->id);
Benjamin Berg's avatar
Benjamin Berg committed
693

694
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
695
696
}

Bastien Nocera's avatar
Bastien Nocera committed
697
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
698
699
	DBusGMethodInvocation *context)
{
700
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
701
702
703
704
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
705
		g_error_free(error);
Bastien Nocera's avatar
Bastien Nocera committed
706
		return;
707
	}
Daniel Drake's avatar
Daniel Drake committed
708

Bastien Nocera's avatar
Bastien Nocera committed
709
710
711
712
713
714
	/* People that can claim can also release */
	if (_fprint_device_check_polkit_for_actions (rdev, context,
						     "net.reactivated.fprint.device.verify",
						     "net.reactivated.fprint.device.enroll",
						     &error) == FALSE) {
		dbus_g_method_return_error (context, error);
715
		g_error_free(error);
Bastien Nocera's avatar
Bastien Nocera committed
716
717
718
		return;
	}

719
720
721
722
723
724
725
726
727
728
729
730
731
	if (priv->current_cancellable) {
		if (priv->current_action == ACTION_ENROLL) {
			g_warning("Enrollment was in progress, stopping it");
		} else if (priv->current_action == ACTION_IDENTIFY ||
			   priv->current_action == ACTION_VERIFY) {
			g_warning("Verification was in progress, stopping it");
		}

		g_cancellable_cancel (priv->current_cancellable);
		while (priv->current_action != ACTION_NONE)
			g_main_context_iteration (NULL, TRUE);
	}

732
	priv->session->context = context;
Benjamin Berg's avatar
Benjamin Berg committed
733
	fp_device_close (priv->dev, NULL, (GAsyncReadyCallback) dev_close_cb, rdev);
Daniel Drake's avatar
Daniel Drake committed
734
735
}

Benjamin Berg's avatar
Benjamin Berg committed
736
static void verify_cb(FpDevice *dev, GAsyncResult *res, void *user_data)
737
{
Benjamin Berg's avatar
Benjamin Berg committed
738
	g_autoptr(GError) error = NULL;
739
	FprintDevice *rdev = user_data;
740
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
741
	gboolean success;
Benjamin Berg's avatar
Benjamin Berg committed
742
743
	const char *name;
	gboolean match;
744

745
746
	success = fp_device_verify_finish (dev, res, &match, NULL, &error);
	g_assert (!!success == !error);
Benjamin Berg's avatar
Benjamin Berg committed
747
	name = verify_result_to_name (match, error);
748

Benjamin Berg's avatar
Benjamin Berg committed
749
	g_debug("verify_cb: result %s", name);
750

Benjamin Berg's avatar
Benjamin Berg committed
751
	set_disconnected (priv, name);
752

Benjamin Berg's avatar
Benjamin Berg committed
753
754
755
	/* Automatically restart the operation for retry failures */
	if (error && error->domain == FP_DEVICE_RETRY) {
		g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, FALSE);
Bastien Nocera's avatar
Bastien Nocera committed
756

757
		/* TODO: Support early match result callback from libfprint */
Benjamin Berg's avatar
Benjamin Berg committed
758
759
760
		fp_device_verify (priv->dev,
				  priv->verify_data,
				  priv->current_cancellable,
761
				  NULL, NULL, NULL,
Benjamin Berg's avatar
Benjamin Berg committed
762
763
764
765
766
767
				  (GAsyncReadyCallback) verify_cb,
				  rdev);
	} else {
		g_clear_object (&priv->verify_data);
		g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, TRUE);

768
769
770
		if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			g_warning ("Device reported an error during verify: %s", error->message);

Benjamin Berg's avatar
Benjamin Berg committed
771
772
773
774
775
776
777
		/* Return the cancellation or reset action right away if vanished. */
		if (priv->current_cancel_context) {
			dbus_g_method_return(priv->current_cancel_context);
			priv->current_cancel_context = NULL;
			priv->current_action = ACTION_NONE;
		} else if (g_cancellable_is_cancelled (priv->current_cancellable)) {
			priv->current_action = ACTION_NONE;
778
		}
Bastien Nocera's avatar
Bastien Nocera committed
779

Benjamin Berg's avatar
Benjamin Berg committed
780
		g_clear_object (&priv->current_cancellable);
Bastien Nocera's avatar
Bastien Nocera committed
781
	}
Bastien Nocera's avatar
Bastien Nocera committed
782
783
}

Benjamin Berg's avatar
Benjamin Berg committed
784
static void identify_cb(FpDevice *dev, GAsyncResult *res, void *user_data)
785
{
Benjamin Berg's avatar
Benjamin Berg committed
786
	g_autoptr(GError) error = NULL;
787
	g_autoptr(FpPrint) match = NULL;
788
	FprintDevice *rdev = user_data;
789
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
Benjamin Berg's avatar
Benjamin Berg committed
790
	const char *name;
791
	gboolean success;
792

793
794
	success = fp_device_identify_finish (dev, res, &match, NULL, &error);
	g_assert (!!success == !error);
Benjamin Berg's avatar
Benjamin Berg committed
795
	name = verify_result_to_name (match != NULL, error);
796

Benjamin Berg's avatar
Benjamin Berg committed
797
	g_debug("verify_cb: result %s", name);
798

Benjamin Berg's avatar
Benjamin Berg committed
799
	set_disconnected (priv, name);
800

Benjamin Berg's avatar
Benjamin Berg committed
801
802
803
	/* Automatically restart the operation for retry failures */
	if (error && error->domain == FP_DEVICE_RETRY) {
		g_signal_emit (rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, FALSE);
Daniel Drake's avatar
Daniel Drake committed
804

805
		/* TODO: Support early match result callback from libfprint */
Benjamin Berg's avatar
Benjamin Berg committed
806
807
808
		fp_device_identify (priv->dev,
				    priv->identify_data,
				    priv->current_cancellable,
809
				    NULL, NULL, NULL,
Benjamin Berg's avatar
Benjamin Berg committed
810
811
812
813
814
815
				    (GAsyncReadyCallback) identify_cb,
				    rdev);
	} else {
		g_clear_pointer (&priv->identify_data, g_ptr_array_unref);
		g_signal_emit (rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, TRUE);

816
817
818
		if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			g_warning ("Device reported an error during identify: %s", error->message);

Benjamin Berg's avatar
Benjamin Berg committed
819
820
821
822
823
824
825
		/* Return the cancellation or reset action right away if vanished. */
		if (priv->current_cancel_context) {
			dbus_g_method_return(priv->current_cancel_context);
			priv->current_cancel_context = NULL;
			priv->current_action = ACTION_NONE;
		} else if (g_cancellable_is_cancelled (priv->current_cancellable)) {
			priv->current_action = ACTION_NONE;
826
827
		}

Benjamin Berg's avatar
Benjamin Berg committed
828
		g_clear_object (&priv->current_cancellable);
Bastien Nocera's avatar
Bastien Nocera committed
829
	}
Daniel Drake's avatar
Daniel Drake committed
830
831
}

Bastien Nocera's avatar
Bastien Nocera committed
832
static void fprint_device_verify_start(FprintDevice *rdev,
833
	const char *finger_name, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
834
{
835
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
Benjamin Berg's avatar
Benjamin Berg committed
836
837
838
	g_autoptr(GPtrArray) gallery = NULL;
	g_autoptr(FpPrint) print = NULL;
	g_autoptr(GError) error = NULL;
839
	guint finger_num = finger_name_to_num (finger_name);
Daniel Drake's avatar
Daniel Drake committed
840

841
842
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
843
		return;
844
845
	}

Bastien Nocera's avatar
Bastien Nocera committed
846
847
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
848
849
850
851
		return;
	}

	if (priv->current_action != ACTION_NONE) {
Bastien Nocera's avatar
Bastien Nocera committed
852
853
854
855
856
857
858
		if (priv->current_action == ACTION_ENROLL) {
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
				    "Enrollment in progress");
		} else {
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
				    "Verification already in progress");
		}
Bastien Nocera's avatar
Bastien Nocera committed
859
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
860
861
862
		return;
	}

Bastien Nocera's avatar
Bastien Nocera committed
863
864
865
	if (finger_num == -1) {
		GSList *prints;

866
		prints = store.discover_prints(priv->dev, priv->session->username);
Bastien Nocera's avatar
Bastien Nocera committed
867
		if (prints == NULL) {
868
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_ENROLLED_PRINTS,
Bastien Nocera's avatar
Bastien Nocera committed
869
870
				    "No fingerprints enrolled");
			dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
871
872
			return;
		}
Benjamin Berg's avatar
Benjamin Berg committed
873
		if (fp_device_supports_identify (priv->dev)) {
Bastien Nocera's avatar
Bastien Nocera committed
874
875
			GSList *l;

Benjamin Berg's avatar
Benjamin Berg committed
876
			gallery = g_ptr_array_new_with_free_func (g_object_unref);
Bastien Nocera's avatar
Bastien Nocera committed
877
878

			for (l = prints; l != NULL; l = l->next) {
879
				g_debug ("adding finger %d to the gallery", GPOINTER_TO_INT (l->data));
Benjamin Berg's avatar
Benjamin Berg committed
880
				store.print_data_load(priv->dev, GPOINTER_TO_INT (l->data),
881
						      priv->session->username, &print);
Bastien Nocera's avatar
Bastien Nocera committed
882

Benjamin Berg's avatar
Benjamin Berg committed
883
884
				if (print)
					g_ptr_array_add (gallery, g_steal_pointer (&print));
Bastien Nocera's avatar
Bastien Nocera committed
885
			}
Bastien Nocera's avatar
Bastien Nocera committed
886
		} else {
Bastien Nocera's avatar
Bastien Nocera committed
887
			finger_num = GPOINTER_TO_INT (prints->data);
Bastien Nocera's avatar
Bastien Nocera committed
888
889
		}
		g_slist_free(prints);
Daniel Drake's avatar
Daniel Drake committed
890
	}
Bastien Nocera's avatar
Bastien Nocera committed
891

Benjamin Berg's avatar
Benjamin Berg committed
892
893
	if (fp_device_supports_identify (priv->dev) && finger_num == -1) {
		if (gallery->len == 0) {
894
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_ENROLLED_PRINTS,
895
896
				    "No fingerprints on that device");
			dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
897
898
			return;
		}
899
		priv->current_action = ACTION_IDENTIFY;
Bastien Nocera's avatar
Bastien Nocera committed
900

901
		g_debug ("start identification device %d", priv->id);
Benjamin Berg's avatar
Benjamin Berg committed
902
903
		priv->current_cancellable = g_cancellable_new ();
		priv->identify_data = g_ptr_array_ref (gallery);
904
905
906
907
		/* TODO: Support early match result callback from libfprint */
		fp_device_identify (priv->dev, gallery, priv->current_cancellable,
		                    NULL, NULL, NULL,
		                    (GAsyncReadyCallback) identify_cb, rdev);
Bastien Nocera's avatar
Bastien Nocera committed
908
	} else {
909
		priv->current_action = ACTION_VERIFY;
Bastien Nocera's avatar
Bastien Nocera committed
910

911
		g_debug("start verification device %d finger %d", priv->id, finger_num);
Bastien Nocera's avatar
Bastien Nocera committed
912

Benjamin Berg's avatar
Benjamin Berg committed
913
		store.print_data_load(priv->dev, finger_num,
914
				      priv->session->username, &print);
Bastien Nocera's avatar
Bastien Nocera committed
915

Benjamin Berg's avatar
Benjamin Berg committed
916
		if (!print) {
917
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL,
Bastien Nocera's avatar
Bastien Nocera committed
918
919
920
921
				    "No such print %d", finger_num);
			dbus_g_method_return_error(context, error);
			return;
		}
Bastien Nocera's avatar
Bastien Nocera committed
922

Benjamin Berg's avatar
Benjamin Berg committed
923
924
		priv->current_cancellable = g_cancellable_new ();
		priv->verify_data = g_object_ref (print);
925
926
927
928
		/* TODO: Support early match result callback from libfprint */
		fp_device_verify (priv->dev, print, priv->current_cancellable,
		                  NULL, NULL, NULL,
		                  (GAsyncReadyCallback) verify_cb, rdev);
Bastien Nocera's avatar
Bastien Nocera committed
929
930
	}

931
932
	/* Emit VerifyFingerSelected telling the front-end which finger
	 * we selected for auth */
933
934
	g_signal_emit(rdev, signals[SIGNAL_VERIFY_FINGER_SELECTED],
		      0, finger_num_to_name (finger_num));
935

936
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
937
938
}

Bastien Nocera's avatar
Bastien Nocera committed
939
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
940
941
	DBusGMethodInvocation *context)
{
942
	FprintDevicePrivate *priv = fprint_device_get_instance_private(rdev);
943
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
944

945
946
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
947
		g_error_free(error);
Bastien Nocera's avatar
Bastien Nocera committed
948
		return;
949
950
	}

Bastien Nocera's avatar
Bastien Nocera committed
951
952
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) {
		dbus_g_method_return_error (context, error);
953
		g_error_free(error);
Bastien Nocera's avatar
Bastien Nocera committed
954
955
956
		return;
	}

Benjamin Berg's avatar
Benjamin Berg committed
957
	if (priv->current_action == ACTION_NONE) {
958
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_ACTION_IN_PROGRESS,
Bastien Nocera's avatar
Bastien Nocera committed
959
960
961
962
			    "No verification in progress");
		dbus_g_method_return_error(context, error);
		g_error_free (error);
		return;
Bastien Nocera's avatar
Bastien Nocera committed
963
	}
Bastien Nocera's avatar
Bastien Nocera committed
964

Benjamin Berg's avatar
Benjamin Berg committed
965
966
967
968
969
970
971
	if (priv->current_cancellable) {
		/* We return only when the action was cancelled */
		g_cancellable_cancel (priv->current_cancellable);
		priv->current_cancel_context = context;
	} else {
		dbus_g_method_return (context);
		priv->current_action = ACTION_NONE;
972
	}
Benjamin Berg's avatar
Benjamin Berg committed
973
}
974

Benjamin Berg's avatar
Benjamin Berg committed
975
976
977
978
979
980
static void enroll_progress_cb(FpDevice *dev,
                               gint      completed_stages,
                               FpPrint  *print,
                               gpointer  user_data,
                               GError   *error)
{
981
	FprintDevice *rdev = user_data;
Benjamin Berg's avatar
Benjamin Berg committed
982
	const char *name = enroll_result_to_name (FALSE, FALSE, error);
Bastien Nocera's avatar
Bastien Nocera committed
983

Benjamin Berg's avatar
Benjamin Berg committed
984
985
986
987
988
989
	g_debug("enroll_stage_cb: result %s", name);

	if (completed_stages < fp_device_get_nr_enroll_stages (dev))
		g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, name, FALSE);
}

Benjamin Berg's avatar