device.c 29.2 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>
Bastien Nocera's avatar
Bastien Nocera committed
25 26
#include <polkit/polkit.h>
#include <polkit-dbus/polkit-dbus.h>
Daniel Drake's avatar
Daniel Drake committed
27 28
#include <libfprint/fprint.h>

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

Daniel Drake's avatar
Daniel Drake committed
32
#include "fprintd.h"
33
#include "storage.h"
34
#include "egg-dbus-monitor.h"
Daniel Drake's avatar
Daniel Drake committed
35

36 37
extern DBusGConnection *fprintd_dbus_conn;

Bastien Nocera's avatar
Bastien Nocera committed
38
static void fprint_device_claim(FprintDevice *rdev,
39 40
				const char *username,
				DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
41
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
42
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
43
static void fprint_device_verify_start(FprintDevice *rdev,
44
	guint32 print_id, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
45
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
46
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
47
static void fprint_device_enroll_start(FprintDevice *rdev,
48
	guint32 finger_num, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
49
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
50
	DBusGMethodInvocation *context);
51
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev, 
52 53
						const char *username,
						DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
54
static void fprint_device_delete_enrolled_fingers(FprintDevice *rdev,
55 56
						  const char *username,
						  DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
57 58
static void fprint_device_get_properties (FprintDevice *rdev,
					  DBusGMethodInvocation *context);
Daniel Drake's avatar
Daniel Drake committed
59 60 61

#include "device-dbus-glue.h"

Bastien Nocera's avatar
Bastien Nocera committed
62 63 64
typedef enum {
	ACTION_NONE = 0,
	ACTION_IDENTIFY,
Bastien Nocera's avatar
Bastien Nocera committed
65 66
	ACTION_VERIFY,
	ACTION_ENROLL
Bastien Nocera's avatar
Bastien Nocera committed
67 68
} FprintDeviceAction;

Daniel Drake's avatar
Daniel Drake committed
69
struct session_data {
Daniel Drake's avatar
Daniel Drake committed
70 71 72
	/* finger being enrolled */
	int enroll_finger;

Daniel Drake's avatar
Daniel Drake committed
73 74 75 76 77 78 79 80 81 82 83 84
	/* method invocation for async ClaimDevice() */
	DBusGMethodInvocation *context_claim_device;

	/* method invocation for async ReleaseDevice() */
	DBusGMethodInvocation *context_release_device;
};

struct FprintDevicePrivate {
	guint32 id;
	struct fp_dscv_dev *ddev;
	struct fp_dev *dev;
	struct session_data *session;
85

Bastien Nocera's avatar
Bastien Nocera committed
86 87
	PolKitContext *pol_ctx;

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

Bastien Nocera's avatar
Bastien Nocera committed
91 92
	/* The current user of the device, or if allowed,
	 * what was passed as a username argument */
93 94
	char *username;

95 96
	/* type of storage */
	int storage_type;
Bastien Nocera's avatar
Bastien Nocera committed
97

98 99 100
	/* Hashtable of connected clients */
	GHashTable *clients;

Bastien Nocera's avatar
Bastien Nocera committed
101
	/* whether we're running an identify, or a verify */
Bastien Nocera's avatar
Bastien Nocera committed
102
	FprintDeviceAction current_action;
Daniel Drake's avatar
Daniel Drake committed
103 104 105 106 107 108 109 110
};

typedef struct FprintDevicePrivate FprintDevicePrivate;

#define DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), FPRINT_TYPE_DEVICE, FprintDevicePrivate))

enum fprint_device_properties {
	FPRINT_DEVICE_CONSTRUCT_DDEV = 1,
111
	FPRINT_DEVICE_IN_USE,
Daniel Drake's avatar
Daniel Drake committed
112 113
};

114
enum fprint_device_signals {
Daniel Drake's avatar
Daniel Drake committed
115
	SIGNAL_VERIFY_STATUS,
Bastien Nocera's avatar
Bastien Nocera committed
116
	SIGNAL_VERIFY_FINGER_SELECTED,
Daniel Drake's avatar
Daniel Drake committed
117
	SIGNAL_ENROLL_STATUS,
118 119 120
	NUM_SIGNALS,
};

Daniel Drake's avatar
Daniel Drake committed
121 122
static GObjectClass *parent_class = NULL;
static guint32 last_id = ~0;
123
static guint signals[NUM_SIGNALS] = { 0, };
Daniel Drake's avatar
Daniel Drake committed
124

125
static void fprint_device_finalize(GObject *object)
Daniel Drake's avatar
Daniel Drake committed
126
{
127 128 129 130
	FprintDevice *self = (FprintDevice *) object;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self);

	g_hash_table_destroy (priv->clients);
Daniel Drake's avatar
Daniel Drake committed
131 132 133
	/* FIXME close and stuff */
}

134
static void fprint_device_set_property(GObject *object, guint property_id,
Daniel Drake's avatar
Daniel Drake committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	const GValue *value, GParamSpec *pspec)
{
	FprintDevice *self = (FprintDevice *) object;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self);

	switch (property_id) {
	case FPRINT_DEVICE_CONSTRUCT_DDEV:
		priv->ddev = g_value_get_pointer(value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
		break;
	}
}

Bastien Nocera's avatar
Bastien Nocera committed
150 151 152 153 154 155 156
static void fprint_device_get_property(GObject *object, guint property_id,
				       GValue *value, GParamSpec *pspec)
{
	FprintDevice *self = (FprintDevice *) object;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self);

	switch (property_id) {
157 158
	case FPRINT_DEVICE_IN_USE:
		g_value_set_boolean(value, g_hash_table_size (priv->clients) != 0);
Bastien Nocera's avatar
Bastien Nocera committed
159 160 161 162 163 164 165
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
		break;
	}
}

166
static void fprint_device_class_init(FprintDeviceClass *klass)
Daniel Drake's avatar
Daniel Drake committed
167 168 169 170 171 172 173 174
{
	GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
	GParamSpec *pspec;

	dbus_g_object_type_install_info(FPRINT_TYPE_DEVICE,
		&dbus_glib_fprint_device_object_info);
	parent_class = g_type_class_peek_parent(klass);

175 176
	gobject_class->finalize = fprint_device_finalize;
	gobject_class->set_property = fprint_device_set_property;
Bastien Nocera's avatar
Bastien Nocera committed
177
	gobject_class->get_property = fprint_device_get_property;
178
	g_type_class_add_private(klass, sizeof(FprintDevicePrivate));
Daniel Drake's avatar
Daniel Drake committed
179 180 181 182 183 184

	pspec = g_param_spec_pointer("discovered-dev", "Discovered device",
		"Set discovered device construction property",
		G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
	g_object_class_install_property(gobject_class,
		FPRINT_DEVICE_CONSTRUCT_DDEV, pspec);
185 186 187
	pspec = g_param_spec_boolean("in-use", "In use",
				 "Whether the device is currently in use", FALSE,
				 G_PARAM_READABLE);
Bastien Nocera's avatar
Bastien Nocera committed
188
	g_object_class_install_property(gobject_class,
189
					FPRINT_DEVICE_IN_USE, pspec);
Daniel Drake's avatar
Daniel Drake committed
190

Daniel Drake's avatar
Daniel Drake committed
191 192 193 194
	signals[SIGNAL_VERIFY_STATUS] = g_signal_new("verify-status",
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
		g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
	signals[SIGNAL_ENROLL_STATUS] = g_signal_new("enroll-status",
195 196
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
		g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
Bastien Nocera's avatar
Bastien Nocera committed
197 198 199
	signals[SIGNAL_VERIFY_FINGER_SELECTED] = g_signal_new("verify-finger-selected",
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
		g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
Daniel Drake's avatar
Daniel Drake committed
200 201
}

Bastien Nocera's avatar
Bastien Nocera committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
static gboolean
pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
{
	int fd;
	PolKitContext *pk_context = user_data;
	fd = g_io_channel_unix_get_fd (channel);
	polkit_context_io_func (pk_context, fd);
	return TRUE;
}

static int 
pk_io_add_watch (PolKitContext *pk_context, int fd)
{
	guint id = 0;
	GIOChannel *channel;
	channel = g_io_channel_unix_new (fd);
	if (channel == NULL)
		goto out;
	id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
	if (id == 0) {
		g_io_channel_unref (channel);
		goto out;
	}
	g_io_channel_unref (channel);
out:
	return id;
}

static void 
pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
{
	g_source_remove (watch_id);
}

236
static void fprint_device_init(FprintDevice *device)
Daniel Drake's avatar
Daniel Drake committed
237
{
238
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(device);
Daniel Drake's avatar
Daniel Drake committed
239
	priv->id = ++last_id;
Bastien Nocera's avatar
Bastien Nocera committed
240 241 242 243 244 245 246 247 248

	/* Setup PolicyKit */
	priv->pol_ctx = polkit_context_new ();
	polkit_context_set_io_watch_functions (priv->pol_ctx, pk_io_add_watch, pk_io_remove_watch);
	if (!polkit_context_init (priv->pol_ctx, NULL)) {
		g_critical ("cannot initialize libpolkit");
		polkit_context_unref (priv->pol_ctx);
		priv->pol_ctx = NULL;
	}
249 250 251 252
	priv->clients = g_hash_table_new_full (g_str_hash,
					       g_str_equal,
					       g_free,
					       g_object_unref);
Daniel Drake's avatar
Daniel Drake committed
253 254
}

255
G_DEFINE_TYPE(FprintDevice, fprint_device, G_TYPE_OBJECT);
Daniel Drake's avatar
Daniel Drake committed
256 257 258 259 260 261 262 263 264 265 266

FprintDevice *fprint_device_new(struct fp_dscv_dev *ddev)
{
	return g_object_new(FPRINT_TYPE_DEVICE, "discovered-dev", ddev, NULL);	
}

guint32 _fprint_device_get_id(FprintDevice *rdev)
{
	return DEVICE_GET_PRIVATE(rdev)->id;
}

267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
static gboolean
_fprint_device_check_claimed (FprintDevice *rdev,
			      DBusGMethodInvocation *context,
			      GError **error)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	DBusConnection *conn;
	char *sender;
	gboolean retval;

	/* The device wasn't claimed, exit */
	if (priv->sender == NULL) {
		g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			     _("Device was not claimed before use"));
		return FALSE;
	}

	conn = dbus_g_connection_get_connection (fprintd_dbus_conn);
	sender = dbus_g_method_get_sender (context);
	retval = g_str_equal (sender, priv->sender);
	g_free (sender);

	if (retval == FALSE) {
		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
297
static gboolean
Bastien Nocera's avatar
Bastien Nocera committed
298
_fprint_device_check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, const char *action, GError **error)
Bastien Nocera's avatar
Bastien Nocera committed
299 300 301 302 303 304 305
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	const char *sender;
	DBusError dbus_error;
	PolKitCaller *pk_caller;
	PolKitAction *pk_action;
	PolKitResult pk_result;
306
	uid_t uid;
Bastien Nocera's avatar
Bastien Nocera committed
307 308 309 310 311 312 313 314 315

	/* Check that caller is privileged */
	sender = dbus_g_method_get_sender (context);
	dbus_error_init (&dbus_error);
	pk_caller = polkit_caller_new_from_dbus_name (
	    dbus_g_connection_get_connection (fprintd_dbus_conn),
	    sender, 
	    &dbus_error);
	if (pk_caller == NULL) {
Bastien Nocera's avatar
Bastien Nocera committed
316 317 318 319
		g_set_error (error, FPRINT_ERROR,
			     FPRINT_ERROR_INTERNAL,
			     "Error getting information about caller: %s: %s",
			     dbus_error.name, dbus_error.message);
Bastien Nocera's avatar
Bastien Nocera committed
320 321 322 323
		dbus_error_free (&dbus_error);
		return FALSE;
	}

324 325 326 327 328 329 330 331 332 333 334
	/* XXX Hack?
	 * We'd like to allow root to set the username by default, so
	 * it can authenticate users through PAM
	 * https://bugzilla.redhat.com/show_bug.cgi?id=447266 */
	if ((polkit_caller_get_uid (pk_caller, &uid) && uid == 0) &&
	    (g_str_equal (action, "net.reactivated.fprint.device.setusername") ||
	     g_str_equal (action, "net.reactivated.fprint.device.verify"))) {
		polkit_caller_unref (pk_caller);
		return TRUE;
	}

Bastien Nocera's avatar
Bastien Nocera committed
335 336 337
	pk_action = polkit_action_new ();
	polkit_action_set_action_id (pk_action, action);
	pk_result = polkit_context_is_caller_authorized (priv->pol_ctx, pk_action, pk_caller,
Bastien Nocera's avatar
Bastien Nocera committed
338
							 TRUE, NULL);
Bastien Nocera's avatar
Bastien Nocera committed
339 340 341 342
	polkit_caller_unref (pk_caller);
	polkit_action_unref (pk_action);

	if (pk_result != POLKIT_RESULT_YES) {
Bastien Nocera's avatar
Bastien Nocera committed
343 344 345 346 347
		g_set_error (error, FPRINT_ERROR,
			     FPRINT_ERROR_INTERNAL,
			     "%s %s <-- (action, result)",
			     action,
			     polkit_result_to_string_representation (pk_result));
Bastien Nocera's avatar
Bastien Nocera committed
348 349 350 351 352 353 354
		dbus_error_free (&dbus_error);
		return FALSE;
	}

	return TRUE;
}

Bastien Nocera's avatar
Bastien Nocera committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
static gboolean
_fprint_device_check_polkit_for_actions (FprintDevice *rdev,
					 DBusGMethodInvocation *context,
					 const char *action1,
					 const char *action2,
					 GError **error)
{
	if (_fprint_device_check_polkit_for_action (rdev, context, action1, error) != FALSE)
		return TRUE;

	g_error_free (*error);
	*error = NULL;

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

371 372 373 374 375 376
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
377
{
378 379 380 381 382 383
	DBusConnection *conn;
	DBusError dbus_error;
	char *sender;
	unsigned long uid;
	struct passwd *user;
	char *client_username;
Bastien Nocera's avatar
Bastien Nocera committed
384

385 386 387 388 389
	/* 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
390

391 392 393 394
	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
395 396
	}

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
	user = getpwuid (uid);
	if (user == NULL) {
		g_free (sender);
		g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			    "Failed to get information about user UID %lu", uid);
		return NULL;
	}
	client_username = g_strdup (user->pw_name);

	/* The current user is usually allowed to access their
	 * own data, this should be followed by PolicyKit checks
	 * anyway */
	if (username == NULL || *username == '\0' || g_str_equal (username, client_username)) {
		if (ret_sender != NULL)
			*ret_sender = sender;
		else
			g_free (sender);
		return client_username;
	}

	/* 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
422 423
	}

424 425 426 427
	if (ret_sender != NULL)
		*ret_sender = sender;
	else
		g_free (sender);
Bastien Nocera's avatar
Bastien Nocera committed
428

429
	return g_strdup (username);
Bastien Nocera's avatar
Bastien Nocera committed
430 431
}

432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
static void action_stop_cb(struct fp_dev *dev, void *user_data)
{
	gboolean *done = (gboolean *) user_data;
	*done = TRUE;
}

static void
_fprint_device_client_disconnected (EggDbusMonitor *monitor, gboolean connected, FprintDevice *rdev)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);

	if (connected == FALSE) {
		const char *sender;
		sender = egg_dbus_monitor_get_service (monitor);

		/* Was that the client that claimed the device? */
		if (priv->sender != NULL) {
			gboolean done = FALSE;
			switch (priv->current_action) {
			case ACTION_NONE:
				break;
			case ACTION_IDENTIFY:
				fp_async_identify_stop(priv->dev, action_stop_cb, &done);
				while (done == FALSE)
					g_main_context_iteration (NULL, TRUE);
				break;
			case ACTION_VERIFY:
				fp_async_verify_stop(priv->dev, action_stop_cb, &done);
				while (done == FALSE)
					g_main_context_iteration (NULL, TRUE);
				break;
			case ACTION_ENROLL:
				fp_async_enroll_stop(priv->dev, action_stop_cb, &done);
				while (done == FALSE)
					g_main_context_iteration (NULL, TRUE);
				break;
			}
			priv->current_action = ACTION_NONE;
			done = FALSE;

			/* Close the claimed device as well */
			fp_async_dev_close (priv->dev, action_stop_cb, &done);
			while (done == FALSE)
				g_main_context_iteration (NULL, TRUE);

			g_free (priv->sender);
			priv->sender = NULL;
			g_free (priv->username);
			priv->username = NULL;
		}
		g_hash_table_remove (priv->clients, sender);
	}

	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)
{
	EggDbusMonitor *monitor;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);

	monitor = g_hash_table_lookup (priv->clients, sender);
	if (monitor == NULL) {
		monitor = egg_dbus_monitor_new ();
		egg_dbus_monitor_assign (monitor, fprintd_dbus_conn, sender);
		//FIXME handle replaced
		g_signal_connect (G_OBJECT (monitor), "connection-changed",
					 G_CALLBACK (_fprint_device_client_disconnected), rdev);
		g_hash_table_insert (priv->clients, g_strdup (sender), monitor);
		g_object_notify (G_OBJECT (rdev), "in-use");
	}
}

Daniel Drake's avatar
Daniel Drake committed
508 509 510 511 512 513 514 515 516 517
static void dev_open_cb(struct fp_dev *dev, int status, void *user_data)
{
	FprintDevice *rdev = user_data;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;

	g_message("device %d claim status %d", priv->id, status);

	if (status != 0) {
		GError *error;
518 519 520 521

		g_free (priv->sender);
		priv->sender = NULL;

Daniel Drake's avatar
Daniel Drake committed
522 523 524 525 526 527 528 529 530 531
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			"Open failed with error %d", status);
		dbus_g_method_return_error(session->context_claim_device, error);
		return;
	}

	priv->dev = dev;
	dbus_g_method_return(session->context_claim_device);
}

Bastien Nocera's avatar
Bastien Nocera committed
532
static void fprint_device_claim(FprintDevice *rdev,
533 534
				const char *username,
				DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
535 536 537
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	GError *error = NULL;
538
	char *sender, *user;
Daniel Drake's avatar
Daniel Drake committed
539 540
	int r;

541
	/* Is it already claimed? */
542 543 544 545
	if (priv->sender != NULL) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			    "Device was already claimed");
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
546
		return;
547 548
	}

549 550
	g_assert (priv->username == NULL);
	g_assert (priv->sender == NULL);
Bastien Nocera's avatar
Bastien Nocera committed
551

552 553 554 555 556 557 558
	sender = NULL;
	user = _fprint_device_check_for_username (rdev,
						  context,
						  username,
						  &sender,
						  &error);
	if (user == NULL) {
559
		g_free (sender);
560
		dbus_g_method_return_error (context, error);
561
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
562
		return;
563 564
	}

565 566 567 568
	if (_fprint_device_check_polkit_for_actions (rdev, context,
						     "net.reactivated.fprint.device.verify",
						     "net.reactivated.fprint.device.enroll",
						     &error) == FALSE) {
569
		g_free (sender);
570 571
		g_free (user);
		dbus_g_method_return_error (context, error);
572 573 574
		return;
	}

575 576
	_fprint_device_add_client (rdev, sender);

577
	priv->username = user;
578 579
	priv->sender = sender;

Bastien Nocera's avatar
Bastien Nocera committed
580
	g_message ("user '%s' claiming the device: %d", priv->username, priv->id);
581

Daniel Drake's avatar
Daniel Drake committed
582 583 584 585 586 587 588
	priv->session = g_slice_new0(struct session_data);
	priv->session->context_claim_device = context;

	r = fp_async_dev_open(priv->ddev, dev_open_cb, rdev);
	if (r < 0) {
		g_slice_free(struct session_data, priv->session);
		priv->session = NULL;
589 590 591 592 593 594

		g_free (priv->username);
		priv->username = NULL;
		g_free (priv->sender);
		priv->sender = NULL;

Daniel Drake's avatar
Daniel Drake committed
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			"Could not attempt device open, error %d", r);
		dbus_g_method_return_error(context, error);
	}
}

static void dev_close_cb(struct fp_dev *dev, void *user_data)
{
	FprintDevice *rdev = user_data;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	DBusGMethodInvocation *context = session->context_release_device;

	priv->dev = NULL;
	g_slice_free(struct session_data, session);
	priv->session = NULL;

612 613 614
	g_free (priv->sender);
	priv->sender = NULL;

615 616 617
	g_free (priv->username);
	priv->username = NULL;

Daniel Drake's avatar
Daniel Drake committed
618 619 620 621
	g_message("released device %d", priv->id);
	dbus_g_method_return(context);
}

Bastien Nocera's avatar
Bastien Nocera committed
622
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
623 624 625 626
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
627 628 629 630
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
631
		return;
632
	}
Daniel Drake's avatar
Daniel Drake committed
633

Bastien Nocera's avatar
Bastien Nocera committed
634 635 636 637 638 639 640 641 642
	/* People that can claim can also release */
	if (_fprint_device_check_polkit_for_actions (rdev, context,
						     "net.reactivated.fprint.device.verify",
						     "net.reactivated.fprint.device.enroll",
						     &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return;
	}

Daniel Drake's avatar
Daniel Drake committed
643 644 645 646 647
	session->context_release_device = context;
	fp_async_dev_close(priv->dev, dev_close_cb, rdev);
}

static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img,
Bastien Nocera's avatar
Bastien Nocera committed
648 649 650 651 652 653 654 655 656 657 658
		      void *user_data)
{
	struct FprintDevice *rdev = user_data;
	g_message("verify_cb: result %d", r);

	g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, r);
	fp_img_free(img);
}

static void identify_cb(struct fp_dev *dev, int r,
			 size_t match_offset, struct fp_img *img, void *user_data)
Daniel Drake's avatar
Daniel Drake committed
659 660
{
	struct FprintDevice *rdev = user_data;
Bastien Nocera's avatar
Bastien Nocera committed
661
	g_message("identify_cb: result %d", r);
Daniel Drake's avatar
Daniel Drake committed
662

Daniel Drake's avatar
Daniel Drake committed
663
	g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, r);
664
	fp_img_free(img);
Daniel Drake's avatar
Daniel Drake committed
665 666
}

Bastien Nocera's avatar
Bastien Nocera committed
667
static void fprint_device_verify_start(FprintDevice *rdev,
668
	guint32 finger_num, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
669 670
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
Bastien Nocera's avatar
Bastien Nocera committed
671
	struct fp_print_data **gallery = NULL;
Daniel Drake's avatar
Daniel Drake committed
672
	struct fp_print_data *data = NULL;
673
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
674 675
	int r;

676 677
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
678
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
679
		return;
680 681
	}

Bastien Nocera's avatar
Bastien Nocera committed
682 683
	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
684 685 686 687 688
		g_error_free (error);
		return;
	}

	if (priv->current_action != ACTION_NONE) {
Bastien Nocera's avatar
Bastien Nocera committed
689 690 691 692 693 694 695
		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
696 697
		dbus_g_method_return_error(context, error);
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
698 699 700
		return;
	}

Bastien Nocera's avatar
Bastien Nocera committed
701 702 703 704 705
	if (finger_num == -1) {
		GSList *prints;

		prints = store.discover_prints(priv->ddev, priv->username);
		if (prints == NULL) {
Bastien Nocera's avatar
Bastien Nocera committed
706 707 708
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
				    "No fingerprints enrolled");
			dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
709 710 711 712 713 714 715 716 717
			return;
		}
		if (fp_dev_supports_identification(priv->dev)) {
			GSList *l;
			GPtrArray *array;

			array = g_ptr_array_new ();

			for (l = prints; l != NULL; l = l->next) {
Bastien Nocera's avatar
Bastien Nocera committed
718 719
				g_message ("adding finger %d to the gallery", GPOINTER_TO_INT (l->data));
				r = store.print_data_load(priv->dev, GPOINTER_TO_INT (l->data),
Bastien Nocera's avatar
Bastien Nocera committed
720 721 722 723 724
							  &data, priv->username);
				//FIXME r < 0 ?
				g_ptr_array_add (array, data);
			}
			data = NULL;
Bastien Nocera's avatar
Bastien Nocera committed
725 726 727 728 729 730 731

			if (array->len > 0) {
				g_ptr_array_add (array,  NULL);
				gallery = (struct fp_print_data **) g_ptr_array_free (array, FALSE);
			} else {
				gallery = NULL;
			}
Bastien Nocera's avatar
Bastien Nocera committed
732
		} else {
Bastien Nocera's avatar
Bastien Nocera committed
733
			finger_num = GPOINTER_TO_INT (prints->data);
Bastien Nocera's avatar
Bastien Nocera committed
734 735
		}
		g_slist_free(prints);
Daniel Drake's avatar
Daniel Drake committed
736
	}
Bastien Nocera's avatar
Bastien Nocera committed
737

Bastien Nocera's avatar
Bastien Nocera committed
738
	if (fp_dev_supports_identification(priv->dev) && finger_num == -1) {
Bastien Nocera's avatar
Bastien Nocera committed
739
		if (gallery == NULL) {
740 741 742 743
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
				    "No fingerprints on that device");
			dbus_g_method_return_error(context, error);
			g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
744 745
			return;
		}
746
		priv->current_action = ACTION_IDENTIFY;
Bastien Nocera's avatar
Bastien Nocera committed
747 748 749 750 751

		g_message ("start identification device %d", priv->id);
		//FIXME we're supposed to free the gallery here?
		r = fp_async_identify_start (priv->dev, gallery, identify_cb, rdev);
	} else {
752
		priv->current_action = ACTION_VERIFY;
Bastien Nocera's avatar
Bastien Nocera committed
753 754 755 756 757 758 759 760 761 762 763 764

		g_message("start verification device %d finger %d", priv->id, finger_num);

		r = store.print_data_load(priv->dev, (enum fp_finger)finger_num, 
					  &data, priv->username);

		if (r < 0 || !data) {
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
				    "No such print %d", finger_num);
			dbus_g_method_return_error(context, error);
			return;
		}
Bastien Nocera's avatar
Bastien Nocera committed
765

Bastien Nocera's avatar
Bastien Nocera committed
766 767 768 769
		/* FIXME fp_async_verify_start should copy the fp_print_data */
		r = fp_async_verify_start(priv->dev, data, verify_cb, rdev);
	}

770 771 772 773 774
	/* Emit VerifyFingerSelected telling the front-end which finger
	 * we selected for auth */
	g_signal_emit(rdev, signals[SIGNAL_VERIFY_FINGER_SELECTED], 0, finger_num);


Daniel Drake's avatar
Daniel Drake committed
775
	if (r < 0) {
Bastien Nocera's avatar
Bastien Nocera committed
776 777 778 779 780 781 782 783
		if (data != NULL) {
			fp_print_data_free (data);
		} else if (gallery != NULL) {
			guint i;
			for (i = 0; gallery[i] != NULL; i++)
				fp_print_data_free(gallery[i]);
			g_free (gallery);
		}
784
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_START,
Daniel Drake's avatar
Daniel Drake committed
785
			"Verify start failed with error %d", r);
786
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
787
		return;
Daniel Drake's avatar
Daniel Drake committed
788 789
	}

790
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
791 792 793 794 795 796 797
}

static void verify_stop_cb(struct fp_dev *dev, void *user_data)
{
	dbus_g_method_return((DBusGMethodInvocation *) user_data);
}

Bastien Nocera's avatar
Bastien Nocera committed
798 799 800 801 802
static void identify_stop_cb(struct fp_dev *dev, void *user_data)
{
	dbus_g_method_return((DBusGMethodInvocation *) user_data);
}

Bastien Nocera's avatar
Bastien Nocera committed
803
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
804 805 806
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
807
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
808 809
	int r;

810 811
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
812
		return;
813 814
	}

Bastien Nocera's avatar
Bastien Nocera committed
815 816 817 818 819
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return;
	}

Bastien Nocera's avatar
Bastien Nocera committed
820
	if (priv->current_action == ACTION_VERIFY) {
Bastien Nocera's avatar
Bastien Nocera committed
821
		r = fp_async_verify_stop(priv->dev, verify_stop_cb, context);
Bastien Nocera's avatar
Bastien Nocera committed
822
	} else if (priv->current_action == ACTION_IDENTIFY) {
Bastien Nocera's avatar
Bastien Nocera committed
823
		r = fp_async_identify_stop(priv->dev, identify_stop_cb, context);
Bastien Nocera's avatar
Bastien Nocera committed
824 825 826 827 828 829
	} else {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_STOP,
			    "No verification in progress");
		dbus_g_method_return_error(context, error);
		g_error_free (error);
		return;
Bastien Nocera's avatar
Bastien Nocera committed
830
	}
Bastien Nocera's avatar
Bastien Nocera committed
831

Daniel Drake's avatar
Daniel Drake committed
832 833 834 835
	if (r < 0) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_STOP,
			"Verify stop failed with error %d", r);
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
836
		g_error_free (error);
Daniel Drake's avatar
Daniel Drake committed
837
	}
Bastien Nocera's avatar
Bastien Nocera committed
838

839
	priv->current_action = ACTION_NONE;
Daniel Drake's avatar
Daniel Drake committed
840 841
}

Daniel Drake's avatar
Daniel Drake committed
842 843 844 845 846 847
static void enroll_stage_cb(struct fp_dev *dev, int result,
	struct fp_print_data *print, struct fp_img *img, void *user_data)
{
	struct FprintDevice *rdev = user_data;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
Bastien Nocera's avatar
Bastien Nocera committed
848
	int r;
Daniel Drake's avatar
Daniel Drake committed
849 850

	g_message("enroll_stage_cb: result %d", result);
Bastien Nocera's avatar
Bastien Nocera committed
851
	if (result == FP_ENROLL_COMPLETE) {
852
		r = store.print_data_save(print, session->enroll_finger, priv->username);
Bastien Nocera's avatar
Bastien Nocera committed
853 854 855
		if (r < 0)
			result = FP_ENROLL_FAIL;
	}
Daniel Drake's avatar
Daniel Drake committed
856 857 858 859 860 861

	g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, result);
	fp_img_free(img);
	fp_print_data_free(print);
}

Bastien Nocera's avatar
Bastien Nocera committed
862
static void fprint_device_enroll_start(FprintDevice *rdev,
863
	guint32 finger_num, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
864 865 866
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
867
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
868 869
	int r;

870 871
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
872
		return;
873 874
	}

Bastien Nocera's avatar
Bastien Nocera committed
875 876 877 878 879
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return;
	}

Bastien Nocera's avatar
Bastien Nocera committed
880 881 882 883 884 885 886 887 888 889 890 891 892
	if (priv->current_action != ACTION_NONE) {
		if (priv->current_action == ACTION_ENROLL) {
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
				    "Enrollment already in progress");
		} else {
			g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
				    "Verification in progress");
		}
		dbus_g_method_return_error(context, error);
		g_error_free (error);
		return;
	}

Daniel Drake's avatar
Daniel Drake committed
893 894 895 896 897
	g_message("start enrollment device %d finger %d", priv->id, finger_num);
	session->enroll_finger = finger_num;
	
	r = fp_async_enroll_start(priv->dev, enroll_stage_cb, rdev);
	if (r < 0) {
898
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_START,
Daniel Drake's avatar
Daniel Drake committed
899
			"Enroll start failed with error %d", r);
900
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
901
		return;
Daniel Drake's avatar
Daniel Drake committed
902 903
	}

904
	priv->current_action = ACTION_ENROLL;
Bastien Nocera's avatar
Bastien Nocera committed
905

906
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
907 908 909 910 911 912 913
}

static void enroll_stop_cb(struct fp_dev *dev, void *user_data)
{
	dbus_g_method_return((DBusGMethodInvocation *) user_data);
}

Bastien Nocera's avatar
Bastien Nocera committed
914
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
915 916 917
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
918
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
919 920
	int r;

921 922
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
923
		return;
924 925
	}

Bastien Nocera's avatar
Bastien Nocera committed
926 927 928 929 930
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return;
	}

Bastien Nocera's avatar
Bastien Nocera committed
931 932 933 934 935 936 937 938
	if (priv->current_action != ACTION_ENROLL) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_STOP,
			    "No enrollment in progress");
		dbus_g_method_return_error(context, error);
		g_error_free (error);
		return;
	}

Daniel Drake's avatar
Daniel Drake committed
939 940 941 942 943
	r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context);
	if (r < 0) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_STOP,
			"Enroll stop failed with error %d", r);
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
944
		g_error_free (error);
Daniel Drake's avatar
Daniel Drake committed
945
	}
Bastien Nocera's avatar
Bastien Nocera committed
946

947
	priv->current_action = ACTION_NONE;
Daniel Drake's avatar
Daniel Drake committed
948 949
}

950
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev,
951 952
						const char *username,
						DBusGMethodInvocation *context)
953 954
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
955
	GError *error = NULL;
956 957 958
	GSList *prints;
	GSList *item;
	GArray *ret;
959
	char *user, *sender;
960 961 962 963 964 965 966

	user = _fprint_device_check_for_username (rdev,
						  context,
						  username,
						  NULL,
						  &error);
	if (user == NULL) {
967
		dbus_g_method_return_error (context, error);
968
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
969
		return;
970 971
	}

Bastien Nocera's avatar
Bastien Nocera committed
972
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.verify", &error) == FALSE) {
973
		g_free (user);
Bastien Nocera's avatar
Bastien Nocera committed
974 975 976 977
		dbus_g_method_return_error (context, error);
		return;
	}

978 979 980 981
	sender = dbus_g_method_get_sender (context);
	_fprint_device_add_client (rdev, sender);
	g_free (sender);

982 983
	prints = store.discover_prints(priv->ddev, user);
	g_free (user);
984
	if (!prints) {
985
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
986
			"Failed to discover prints");
987
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
988
		return;
989 990 991 992
	}

	ret = g_array_new(FALSE, FALSE, sizeof(int));
	for (item = prints; item; item = item->next) {
Bastien Nocera's avatar
Bastien Nocera committed
993
		ret = g_array_append_val(ret, item->data);
994 995 996
	}

	g_slist_free(prints);
997

998
	dbus_g_method_return(context, ret);
999 1000
}

Bastien Nocera's avatar
Bastien Nocera committed
1001
static void fprint_device_delete_enrolled_fingers(FprintDevice *rdev,
1002
						  const char *username,
Bastien Nocera's avatar
Bastien Nocera committed
1003 1004 1005 1006 1007
						  DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	GError *error = NULL;
	guint i;
1008
	char *user, *sender;
Bastien Nocera's avatar
Bastien Nocera committed
1009

1010 1011 1012 1013 1014 1015
	user = _fprint_device_check_for_username (rdev,
						  context,
						  username,
						  NULL,
						  &error);
	if (user == NULL) {
Bastien Nocera's avatar
Bastien Nocera committed
1016
		dbus_g_method_return_error (context, error);
1017
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
1018 1019 1020
		return;
	}

1021
	if (_fprint_device_check_polkit_for_action (rdev, context, "net.reactivated.fprint.device.enroll", &error) == FALSE) {
1022
		g_free (user);
Bastien Nocera's avatar
Bastien Nocera committed
1023 1024 1025 1026
		dbus_g_method_return_error (context, error);
		return;
	}

1027 1028 1029 1030
	sender = dbus_g_method_get_sender (context);
	_fprint_device_add_client (rdev, sender);
	g_free (sender);

Bastien Nocera's avatar
Bastien Nocera committed
1031
	for (i = LEFT_THUMB; i <= RIGHT_LITTLE; i++) {
1032
		store.print_data_delete(priv->ddev, i, user);
Bastien Nocera's avatar
Bastien Nocera committed
1033
	}
1034
	g_free (user);
Bastien Nocera's avatar
Bastien Nocera committed
1035 1036 1037 1038

	dbus_g_method_return(context);
}

Bastien Nocera's avatar
Bastien Nocera committed
1039 1040
static void fprint_device_get_properties (FprintDevice *rdev,
					  DBusGMethodInvocation *context)
Bastien Nocera's avatar
Bastien Nocera committed
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	GHashTable *table;
	struct fp_driver *driver;
	const char *driver_name;

	table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);

	driver = fp_dscv_dev_get_driver (priv->ddev);
	driver_name = fp_driver_get_full_name (driver);
	g_hash_table_insert (table, "Name", g_strdup (driver_name));

Bastien Nocera's avatar
Bastien Nocera committed
1053
	dbus_g_method_return (context, table);
Bastien Nocera's avatar
Bastien Nocera committed
1054 1055
}