Goiz Ruiz | 4 Mar 2009 10:39
Picon

0483:2016 - Sony - SGS Thomson Microelectronics Fingerprint Reader

Hello everyone,

I own a Sony Vaio UX390n with a SGS Thomson Microelectronics Fingerprint Reader, ID 0483:2016.
As far as I know, there is no open source driver for this device. If I'm not mistaken UPEK released a propietary Linux SDK that supports this reader.

Is there any way to incorporate this support into the fprint project?
Considering that I own the device and got Linux installed in the laptop, how can I contribute to the project?
Maybe sniffing the USB traffic and providing the logs?

Goiz.


_______________________________________________
fprint mailing list
fprint <at> reactivated.net
http://lists.reactivated.net/mailman/listinfo/fprint
Michele Caini | 4 Mar 2009 14:59
Picon

Re: 0483:2016 - Sony - SGS Thomson Microelectronics Fingerprint Reader

Goiz Ruiz ha scritto:
> I own a Sony Vaio UX390n with a SGS Thomson Microelectronics Fingerprint
> Reader, ID 0483:2016.
> 
> Is there any way to incorporate this support into the fprint project?

I've the same chipset, and it works.
Nothing needs to be incorporated into the fprint project. ;-)

Michele
G. Ruiz | 4 Mar 2009 23:11
Picon

Re: 0483:2016 - Sony - SGS Thomson Microelectronics Fingerprint Reader

Michele Caini wrote:

> I've the same chipset, and it works.
> Nothing needs to be incorporated into the fprint project. ;-)

Do you have it in a Sony Vaio laptop?
Sony Vaio fingerprint readers have got special propietary firmware that
only allows Sony software to access it.

Has this issue been addressed in fprint?
According to the wiki, it's an unsupported device. I quote:

"UPEK confirms that even though Sony laptops include a 0483:2016 scanner
(which would otherwise be supported by upekts), the Sony version has a
custom firmware designed to prevent any non-Sony software interacting
with the device. Unfortunately they are successful and fprint,
ThinkFinger and UPEK's own Linux drivers do not work with the
fingerprint scanners in Sony laptops. "

If you have the device in a Sony Vaio and it works, I will appreciate if
you could explain your configuration.

Cheers.
Jaroslav Barton | 9 Mar 2009 14:00

[fprintd][PATCH] Support for password prompt while finger scanning

Next try:

Multiple pam stackes will be better, but for some applications
  it is unusable or like sci-fi at this moment (some console
  applications like su, sudo, etc.). Password prompt should be
  enabled by "askpass" pam module parameter in service configuration
  file. Password is stored in PAM_AUTHTOK for next pam module.
  Multiple pam stack aware should use service configuration file
  without askpass option.
---
 pam/Makefile.am           |    5 +-
 pam/README                |    4 +
 pam/fingerprint-strings.h |   21 ++--
 pam/pam_fprintd-uinput.c  |  117 ++++++++++++++++++
 pam/pam_fprintd-uinput.h  |   38 ++++++
 pam/pam_fprintd.c         |  299 ++++++++++++++++++++++++++++++++++++---------
 6 files changed, 413 insertions(+), 71 deletions(-)
 create mode 100644 pam/pam_fprintd-uinput.c
 create mode 100644 pam/pam_fprintd-uinput.h

diff --git a/pam/Makefile.am b/pam/Makefile.am
index 59927d9..7dab1b0 100644
--- a/pam/Makefile.am
+++ b/pam/Makefile.am
 <at>  <at>  -3,12 +3,13  <at>  <at>  if HAVE_PAM
 pammod_PROGRAMS = pam_fprintd.so
 pammoddir=$(libdir)/security

-pam_fprintd_so_SOURCES = pam_fprintd.c $(MARSHALFILES)
+pam_fprintd_so_SOURCES = pam_fprintd.c $(MARSHALFILES) $(UINPUTFILES)
 pam_fprintd_so_CFLAGS = -fPIC $(WARN_CFLAGS) $(GLIB_CFLAGS)
-pam_fprintd_so_LDFLAGS = -shared
+pam_fprintd_so_LDFLAGS = -shared -lpthread
 pam_fprintd_so_LDADD = $(PAM_LIBS) $(GLIB_LIBS)

 MARSHALFILES = marshal.c marshal.h
+UINPUTFILES = pam_fprintd-uinput.c pam_fprintd-uinput.h
 GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
 BUILT_SOURCES = $(MARSHALFILES)

diff --git a/pam/README b/pam/README
index 9174deb..cf0157b 100644
--- a/pam/README
+++ b/pam/README
 <at>  <at>  -14,6 +14,10  <at>  <at>  Options:
 * You can add the "debug" option on the pam configuration file line above,
   this will log more information from PAM to the file specified in your
   syslog configuration (/var/log/secure by default on Fedora)
+* You also can add "askpass" option on the pam configuration file line above,
+  this will allow use "try_first_pas" option of pam_unix module. This option
+  allow entering either the password or a fingerprint (but please see Known
+  issues).

 Known issues:
 * pam_fprintd does not support identifying the user itself as
diff --git a/pam/fingerprint-strings.h b/pam/fingerprint-strings.h
index d1b919e..5499538 100644
--- a/pam/fingerprint-strings.h
+++ b/pam/fingerprint-strings.h
 <at>  <at>  -1,6 +1,7  <at>  <at> 
 /*
  * Helper functions to translate statuses and actions to strings
  * Copyright (C) 2008 Bastien Nocera <hadess <at> hadess.net>
+ * Copyright (C) 2009 Jaroslav Barton <djaara <at> djaara.net>
  * 
  * Experimental code. This will be moved out of fprintd into it's own
  * package once the system has matured.
 <at>  <at>  -25,16 +26,16  <at>  <at>  struct {
 	const char *place_str;
 	const char *swipe_str;
 } fingers[11] = {
-	{ "left-thumb", N_("Place your left thumb on %s"), N_("Swipe your left thumb on %s") },
-	{ "left-index-finger", N_("Place your left index finger on %s"), N_("Swipe your left index finger on
%s") },
-	{ "left-middle-finger", N_("Place your left middle finger on %s"), N_("Swipe your left middle finger
on %s") },
-	{ "left-ring-finger", N_("Place your left ring finger on %s"), N_("Swipe your left ring finger on %s") },
-	{ "left-little-finger", N_("Place your left little finger on %s"), N_("Swipe your left little finger
on %s") },
-	{ "right-thumb", N_("Place your right thumb on %s"), N_("Swipe your right thumb on %s") },
-	{ "right-index-finger", N_("Place your right index finger on %s"), N_("Swipe your right index finger
on %s") },
-	{ "right-middle-finger", N_("Place your right middle finger on %s"), N_("Swipe your right middle
finger on %s") },
-	{ "right-ring-finger", N_("Place your right ring finger on %s"), N_("Swipe your right ring finger on
%s") },
-	{ "right-little-finger", N_("Place your right little finger on %s"), N_("Swipe your right little
finger on %s") },
+	{ "left-thumb", N_("Place your left thumb on %s: "), N_("Swipe your left thumb on %s: ") },
+	{ "left-index-finger", N_("Place your left index finger on %s: "), N_("Swipe your left index finger on
%s: ") },
+	{ "left-middle-finger", N_("Place your left middle finger on %s: "), N_("Swipe your left middle finger
on %s: ") },
+	{ "left-ring-finger", N_("Place your left ring finger on %s: "), N_("Swipe your left ring finger on %s:
") },
+	{ "left-little-finger", N_("Place your left little finger on %s: "), N_("Swipe your left little finger
on %s: ") },
+	{ "right-thumb", N_("Place your right thumb on %s: "), N_("Swipe your right thumb on %s: ") },
+	{ "right-index-finger", N_("Place your right index finger on %s: "), N_("Swipe your right index finger
on %s: ") },
+	{ "right-middle-finger", N_("Place your right middle finger on %s: "), N_("Swipe your right middle
finger on %s: ") },
+	{ "right-ring-finger", N_("Place your right ring finger on %s: "), N_("Swipe your right ring finger on
%s: ") },
+	{ "right-little-finger", N_("Place your right little finger on %s: "), N_("Swipe your right little
finger on %s: ") },
 	{ NULL, NULL, NULL }
 };

diff --git a/pam/pam_fprintd-uinput.c b/pam/pam_fprintd-uinput.c
new file mode 100644
index 0000000..05b2e47
--- /dev/null
+++ b/pam/pam_fprintd-uinput.c
 <at>  <at>  -0,0 +1,117  <at>  <at> 
+/*
+ *   pam_fprintd authentication module
+ *   Copyright (C) 2009 Jaroslav Barton <djaara <at> djaara.net>
+ *
+ *   Based on:
+ *
+ *
+ *   ThinkFinger Pluggable Authentication Module
+ *
+ *   PAM module for libthinkfinger which is a driver for the UPEK/SGS Thomson
+ *   Microelectronics fingerprint reader.
+ *
+ *   Copyright (C) 2007 Timo Hoenig <thoenig <at> suse.de>, <thoenig <at> nouse.net>
+ *
+ *   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.,
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <config.h>
+#include <pam_fprintd-uinput.h>
+
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int uinput_cr (int *fd)
+{
+	int retval = 0, ev_size = 0;
+	struct input_event ev = {
+		.type = EV_KEY,
+		.code = KEY_ENTER,
+		.time = {0, }
+	};
+
+	ev_size = sizeof (ev);
+
+	/* key press */
+	ev.value = 1;
+	if (write (*fd, &ev, ev_size) != ev_size) {
+		retval = errno;
+		goto out;
+	}
+	/* key release */
+	ev.value = 0;
+	if (write (*fd, &ev, ev_size) != ev_size) {
+		retval = errno;
+		goto out;
+	}
+
+out:
+	return retval;
+}
+
+int uinput_close (int *fd)
+{
+	int retval = 0;
+
+	/* destroy virtual input device */
+	if (ioctl (*fd, UI_DEV_DESTROY, 0) < 0)
+		retval = errno;
+
+	if (close (*fd) < 0)
+		retval = errno;
+
+	return retval;
+}
+
+int uinput_open (int *fd)
+{
+	int retval = 0, i, device_size = 0;
+	struct uinput_user_dev device = {
+		.name = "Virtual ThinkFinger Keyboard"
+	};
+
+        *fd = open ("/dev/input/uinput", O_WRONLY | O_NDELAY);
+        if (*fd < 0)
+                *fd = open ("/dev/misc/uinput", O_WRONLY | O_NDELAY);
+        if (*fd < 0)
+                *fd = open ("/dev/uinput", O_WRONLY | O_NDELAY);
+        if (*fd < 0) {
+		retval = errno;
+		goto out;
+	}
+
+	device_size = sizeof (device);
+
+	/* our single key keyboard */
+	i  = ioctl (*fd, UI_SET_EVBIT, EV_KEY) < 0;
+	i |= ioctl (*fd, UI_SET_KEYBIT, KEY_ENTER) < 0;
+
+	if (write (*fd, &device, device_size) != device_size) {
+		retval = errno;
+		goto out;
+	}
+
+	/* create virtual input device */
+	if (ioctl (*fd, UI_DEV_CREATE, 0) < 0)
+		retval = errno;
+
+out:
+	return retval;
+}
+
diff --git a/pam/pam_fprintd-uinput.h b/pam/pam_fprintd-uinput.h
new file mode 100644
index 0000000..2e647b0
--- /dev/null
+++ b/pam/pam_fprintd-uinput.h
 <at>  <at>  -0,0 +1,38  <at>  <at> 
+/*
+ *   pam_fprintd authentication module
+ *   Copyright (C) 2009 Jaroslav Barton <djaara <at> djaara.net>
+ *
+ *   Based on:
+ *
+ *
+ *   ThinkFinger Pluggable Authentication Module
+ *
+ *   PAM module for libthinkfinger which is a driver for the UPEK/SGS Thomson
+ *   Microelectronics fingerprint reader.
+ *
+ *   Copyright (C) 2007 Timo Hoenig <thoenig <at> suse.de>, <thoenig <at> nouse.net>
+ *
+ *   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.,
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef PAM_THINKFINGER_UINPUT_H
+#define PAM_THINKFINGER_UINPUT_H
+
+int uinput_cr    (int *fd);
+int uinput_close (int *fd);
+int uinput_open  (int *fd);
+
+#endif /* PAM_THINKFINGER_UINPUT_H */
diff --git a/pam/pam_fprintd.c b/pam/pam_fprintd.c
index 5e8757c..8d4b7f8 100644
--- a/pam/pam_fprintd.c
+++ b/pam/pam_fprintd.c
 <at>  <at>  -2,6 +2,7  <at>  <at> 
  * pam_fprint: PAM module for fingerprint authentication through fprintd
  * Copyright (C) 2007 Daniel Drake <dsd <at> gentoo.org>
  * Copyright (C) 2008 Bastien Nocera <hadess <at> hadess.net>
+ * Copyright (C) 2009 Jaroslav Barton <djaara <at> djaara.net>
  * 
  * Experimental code. This will be moved out of fprintd into it's own
  * package once the system has matured.
 <at>  <at>  -26,17 +27,20  <at>  <at> 
 #include <sys/types.h>
 #include <string.h>
 #include <syslog.h>
+#include <pthread.h>

 #include <dbus/dbus-glib-bindings.h>
 #include <dbus/dbus-glib-lowlevel.h>

 #define PAM_SM_AUTH
 #include <security/pam_modules.h>
+#include <security/pam_ext.h>

 #include "marshal.h"

 #define N_(x) x
 #include "fingerprint-strings.h"
+#include "pam_fprintd-uinput.h"

 #define MAX_TRIES 3
 #define TIMEOUT 30
 <at>  <at>  -50,13 +54,47  <at>  <at> 
 	}						\
 }

+#define E(pamh, ...) {					\
+	char *s;					\
+	s = g_strdup_printf (__VA_ARGS__);		\
+	send_err_msg (pamh, s);				\
+	g_free (s);					\
+}
+
+typedef struct {
+	guint max_tries;
+	char *result;
+	gboolean timed_out;
+	gboolean is_swipe;
+	pam_handle_t *pamh;
+	GMainLoop *loop;
+
+	char *driver;
+} verify_data;
+
+typedef struct {
+	const char* user;
+	pthread_t t_pam_prompt;
+	pthread_t t_finger;
+	int finger_retval;
+	int prompt_retval;
+	pam_handle_t *pamh;
+	char done;
+	int uinput_fd;
+	verify_data* data;
+} pam_fprintd_s;
+

 static gboolean debug = FALSE;
+static gboolean askpass = FALSE;
+static char *msg = NULL;
+static pthread_mutex_t msg_m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t msg_c = PTHREAD_COND_INITIALIZER;

-static gboolean send_info_msg(pam_handle_t *pamh, const char *msg)
+static gboolean send_msg(pam_handle_t *pamh, const char *msg, int msgtype)
 {
 	const struct pam_message mymsg = {
-		.msg_style = PAM_TEXT_INFO,
+		.msg_style = msgtype,
 		.msg = msg,
 	};
 	const struct pam_message *msgp = &mymsg;
 <at>  <at>  -74,25 +112,15  <at>  <at>  static gboolean send_info_msg(pam_handle_t *pamh, const char *msg)
 	return (pc->conv(1, &msgp, &resp, pc->appdata_ptr) == PAM_SUCCESS);
 }

-static gboolean send_err_msg(pam_handle_t *pamh, const char *msg)
-{
-	const struct pam_message mymsg = {
-		.msg_style = PAM_ERROR_MSG,
-		.msg = msg,
-	};
-	const struct pam_message *msgp = &mymsg;
-	const struct pam_conv *pc;
-	struct pam_response *resp;
-	int r;
-
-	r = pam_get_item(pamh, PAM_CONV, (const void **) &pc);
-	if (r != PAM_SUCCESS)
-		return FALSE;

-	if (!pc || !pc->conv)
-		return FALSE;
+static gboolean send_info_msg(pam_handle_t *pamh, const char *msg)
+{
+	return send_msg(pamh, msg, PAM_TEXT_INFO);
+}

-	return (pc->conv(1, &msgp, &resp, pc->appdata_ptr) == PAM_SUCCESS);
+static gboolean send_err_msg(pam_handle_t *pamh, const char *msg)
+{
+	return send_msg(pamh, msg, PAM_ERROR_MSG);
 }

 static void send_debug_msg(pam_handle_t *pamh, const char *msg)
 <at>  <at>  -200,17 +228,6  <at>  <at>  static DBusGProxy *open_device(pam_handle_t *pamh, DBusGConnection *connection,
 	return dev;
 }

-typedef struct {
-	guint max_tries;
-	char *result;
-	gboolean timed_out;
-	gboolean is_swipe;
-	pam_handle_t *pamh;
-	GMainLoop *loop;
-
-	char *driver;
-} verify_data;
-
 static void verify_result(GObject *object, const char *result, gboolean done, gpointer user_data)
 {
 	verify_data *data = user_data;
 <at>  <at>  -229,20 +246,33  <at>  <at>  static void verify_result(GObject *object, const char *result, gboolean done, gp

 static void verify_finger_selected(GObject *object, const char *finger_name, gpointer user_data)
 {
+	if (askpass) {
+		pthread_mutex_lock(&msg_m);
+	}
+
 	verify_data *data = user_data;
-	char *msg;

 	if (g_str_equal (finger_name, "any")) {
 		if (data->is_swipe == FALSE)
-			msg = g_strdup_printf ("Place your finger on %s", data->driver);
+			msg = g_strdup_printf (N_("Place your finger on %s"), data->driver);
 		else
-			msg = g_strdup_printf ("Swipe your finger on %s", data->driver);
+			msg = g_strdup_printf (N_("Swipe your finger on %s"), data->driver);
 	} else {
 		msg = g_strdup_printf (finger_str_to_msg(finger_name, data->is_swipe), data->driver);
 	}
+
 	D(data->pamh, "verify_finger_selected %s", msg);
-	send_info_msg (data->pamh, msg);
-	g_free (msg);
+
+	if (askpass) {
+		char* msg2 = g_strdup_printf(N_("Password or %s"), msg);
+		g_free(msg);
+		msg = msg2;
+		pthread_cond_broadcast(&msg_c);
+		pthread_mutex_unlock(&msg_m);
+	} else {
+		send_info_msg(data->pamh, msg);
+		g_free(msg);
+	}
 }

 static gboolean verify_timeout_cb (gpointer user_data)
 <at>  <at>  -251,23 +281,43  <at>  <at>  static gboolean verify_timeout_cb (gpointer user_data)

 	data->timed_out = TRUE;
 	send_info_msg (data->pamh, "Verification timed out");
-	g_main_loop_quit (data->loop);
+
+	if (data && g_main_loop_is_running(data->loop)) {
+		g_main_loop_quit (data->loop);
+	}

 	return FALSE;
 }

-static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev)
+static gboolean pass_typed(gpointer user_data) {
+	pam_fprintd_s *fprintd = user_data;
+	pthread_mutex_lock(&msg_m);
+		if (fprintd->done) {
+			if (fprintd->data && g_main_loop_is_running(fprintd->data->loop)) {
+				g_main_loop_quit(fprintd->data->loop);
+			}
+			return FALSE;
+		}
+	pthread_mutex_unlock(&msg_m);
+	return TRUE;
+}
+
+static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev, pam_fprintd_s *fpdata)
 {
 	GError *error = NULL;
 	GHashTable *props;
 	DBusGProxy *p;
 	verify_data *data;
 	int ret;
+	int r;
+
+	pam_fprintd_s* fprintd = fpdata;

 	data = g_new0 (verify_data, 1);
 	data->max_tries = MAX_TRIES;
 	data->pamh = pamh;
 	data->loop = loop;
+	fpdata->data = data;

 	/* Get some properties for the device */
 	p = dbus_g_proxy_new_from_proxy (dev, "org.freedesktop.DBus.Properties", NULL);
 <at>  <at>  -296,7 +346,7  <at>  <at>  static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev)

 	ret = PAM_AUTH_ERR;

-	while (ret == PAM_AUTH_ERR && data->max_tries > 0) {
+	while (ret == PAM_AUTH_ERR && data->max_tries > 0 && !fprintd->done) {
 		GSource *source;
 		guint timeout_id;

 <at>  <at>  -305,6 +355,13  <at>  <at>  static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev)
 		timeout_id = g_source_attach (source, g_main_loop_get_context (loop));
 		g_source_set_callback (source, verify_timeout_cb, data, NULL);

+		/* quit finger thread after pass is typed on keyboard */
+		GSource *passtyped;
+		guint passtyped_id;
+		passtyped = g_timeout_source_new_seconds (1);
+		passtyped_id = g_source_attach (passtyped, g_main_loop_get_context(loop));
+		g_source_set_callback (passtyped, pass_typed, fprintd, NULL);
+
 		data->timed_out = FALSE;

 		if (!dbus_g_proxy_call (dev, "VerifyStart", &error, G_TYPE_STRING, "any", G_TYPE_INVALID,
G_TYPE_INVALID)) {
 <at>  <at>  -313,6 +370,9  <at>  <at>  static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev)

 			g_source_remove (timeout_id);
 			g_source_unref (source);
+
+			g_source_remove (passtyped_id);
+			g_source_unref (passtyped);
 			break;
 		}

 <at>  <at>  -321,19 +381,27  <at>  <at>  static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev)
 		g_source_remove (timeout_id);
 		g_source_unref (source);

+		g_source_remove (passtyped_id);
+		g_source_unref (passtyped);
+
 		/* Ignore errors from VerifyStop */
 		dbus_g_proxy_call (dev, "VerifyStop", NULL, G_TYPE_INVALID, G_TYPE_INVALID);
-
-		if (data->timed_out) {
+		if (data->timed_out || fprintd->done) {
 			ret = PAM_AUTHINFO_UNAVAIL;
 			break;
 		} else {
 			if (g_str_equal (data->result, "verify-no-match")) {
 				send_err_msg (data->pamh, "Failed to match fingerprint");
 				ret = PAM_AUTH_ERR;
-			} else if (g_str_equal (data->result, "verify-match"))
+			} else if (g_str_equal (data->result, "verify-match")) {
+				if (askpass) {
+					r =uinput_cr (&fprintd->uinput_fd);
+					if (r != 0) {
+						E(pamh, "Could not send carriage return via uinput: %s.", strerror (r));
+					}
+				}
 				ret = PAM_SUCCESS;
-			else if (g_str_equal (data->result, "verify-unknown-error"))
+			} else if (g_str_equal (data->result, "verify-unknown-error"))
 				ret = PAM_AUTHINFO_UNAVAIL;
 			else if (g_str_equal (data->result, "verify-disconnected")) {
 				ret = PAM_AUTHINFO_UNAVAIL;
 <at>  <at>  -369,33 +437,101  <at>  <at>  static void release_device(pam_handle_t *pamh, DBusGProxy *dev)
 	}
 }

-static int do_auth(pam_handle_t *pamh, const char *username)
+static void do_auth(void* data)
 {
+	pam_fprintd_s *fprintd = data;
+
 	DBusGProxy *manager;
 	DBusGConnection *connection;
 	DBusGProxy *dev;
 	GMainLoop *loop;
 	int ret;

-	manager = create_manager (pamh, &connection, &loop);
-	if (manager == NULL)
-		return PAM_AUTHINFO_UNAVAIL;
+	manager = create_manager (fprintd->pamh, &connection, &loop);
+	fprintd->done = 0;
+	if (manager == NULL) {
+		fprintd->finger_retval = PAM_AUTHINFO_UNAVAIL;
+		return;
+	}

-	dev = open_device(pamh, connection, manager, username);
+	dev = open_device (fprintd->pamh, connection, manager, fprintd->user);
 	g_object_unref (manager);
 	if (!dev) {
 		g_main_loop_unref (loop);
 		close_and_unref (connection);
-		return PAM_AUTHINFO_UNAVAIL;
+		fprintd->finger_retval = PAM_AUTHINFO_UNAVAIL;
+		return;
 	}
-	ret = do_verify(loop, pamh, dev);
+	ret = do_verify(loop, fprintd->pamh, dev, fprintd);

 	g_main_loop_unref (loop);
-	release_device(pamh, dev);
+	release_device(fprintd->pamh, dev);
 	g_object_unref (dev);
 	close_and_unref (connection);

-	return ret;
+	fprintd->finger_retval = ret;
+	if (askpass) {
+		pthread_exit (NULL);
+	}
+}
+
+/**
+ * Parse module parameters
+ */
+static void pam_fprintd_options(int argc, const char** argv)
+{
+	guint i;
+
+	for (i = 0; i < argc; i++) {
+		if (argv[i] != NULL) {
+			if (g_str_equal (argv[i], "debug")) {
+				g_message ("debug on");
+				debug = TRUE;
+			} else if (g_str_equal (argv[i], "askpass")) {
+				/* g_message ("asking for password"); */
+				askpass = TRUE;
+			}
+		}
+	}
+}
+
+/**
+ * Modified from pam_thinkginger
+ */
+static int pam_user_sanity_check (const char* user)
+{
+	size_t len = strlen(user);
+	return strstr(user, "../") || user[0] == '-' || user[len - 1] == '/';
+}
+
+/**
+ * Modified from pam_thinkfinger
+ */
+static void pam_prompt_thread(void* data)
+{
+	pthread_mutex_lock (&msg_m);
+		while (msg == NULL) {
+			pthread_cond_wait (&msg_c, &msg_m);
+		}
+	pthread_mutex_unlock(&msg_m);
+
+	pam_fprintd_s* fprintd = data;
+	char* resp;
+
+	/* always returning from pam_prompt due to the CR sent by the keyboard or by uinput */
+	pam_prompt (fprintd->pamh, PAM_PROMPT_ECHO_OFF, &resp, msg);
+	g_free(msg);
+
+	/* set authentication token (password) for pam_unix or others */
+	pam_set_item (fprintd->pamh, PAM_AUTHTOK, resp);
+	D(fprintd->pamh, "PAM_AUTHTOK is set");
+
+	/* pam prompt is done, finger thread shoud quit too */
+	pthread_mutex_lock(&msg_m);
+		fprintd->done = 1;
+	pthread_mutex_unlock(&msg_m);
+
+	pthread_exit (NULL);
 }

 PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
 <at>  <at>  -403,36 +539,81  <at>  <at>  PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
 {
 	const char *rhost = NULL;
 	const char *username;
-	guint i;
 	int r;
+	int retval = PAM_AUTH_ERR;
+	pam_fprintd_s fprintd;

 	g_type_init ();

+	pam_fprintd_options (argc, argv);
+
 	dbus_g_object_register_marshaller (fprintd_marshal_VOID__STRING_BOOLEAN,
 					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID);

 	pam_get_item(pamh, PAM_RHOST, (const void **)(const void*) &rhost);
 	if (rhost != NULL && strlen(rhost) > 0) {
 		/* remote login (e.g. over SSH) */
+		D(pamh, "Remote loggin (%s), bypassing...", rhost);
 		return PAM_AUTHINFO_UNAVAIL;
 	}

 	r = pam_get_user(pamh, &username, NULL);
-	if (r != PAM_SUCCESS)
+	if (r != PAM_SUCCESS || pam_user_sanity_check(username))
 		return PAM_AUTHINFO_UNAVAIL;

-	for (i = 0; i < argc; i++) {
-		if (argv[i] != NULL && g_str_equal (argv[i], "debug")) {
-			g_message ("debug on");
-			debug = TRUE;
+	fprintd.pamh = pamh;
+	fprintd.user = username;
+
+	if (askpass) {
+		r = uinput_open (&fprintd.uinput_fd);
+		if (r != 0) {
+			E(pamh, "Initializing uinput failed: %s.", strerror (r));
+			retval = PAM_AUTHINFO_UNAVAIL;
+			goto out;
 		}
+
+		r = pthread_create(&fprintd.t_pam_prompt, NULL, (void*)pam_prompt_thread, &fprintd);
+		if (r != 0) {
+			E(pamh, "Error calling pthread_create (%s).", strerror (r));
+			goto out;
+		}
+
+		r = pthread_create(&fprintd.t_finger, NULL, (void*)do_auth, &fprintd);
+		if (r != 0) {
+			E(pamh, "Error calling pthread_create (%s).", strerror (r));
+			goto out;
+		}
+
+		r = pthread_join (fprintd.t_finger, NULL);
+		if (r != 0) {
+			E(pamh, "Error calling pthread_join (%s).", strerror (r));
+			goto out;
+		}
+
+		r = pthread_join (fprintd.t_pam_prompt, NULL);
+		if (r != 0) {
+			E(pamh, "Error calling pthread_join (%s).", strerror (r));
+			goto out;
+		}
+	} else {
+		do_auth((void*)&fprintd);
 	}

-	r = do_auth(pamh, username);
+	if (fprintd.finger_retval == PAM_SUCCESS)
+		retval = PAM_SUCCESS;
+	else
+		retval = PAM_AUTHINFO_UNAVAIL;

-	return r;
+	if (askpass && fprintd.uinput_fd > 0) {
+		uinput_close(&fprintd.uinput_fd);
+	}
+
+out:
+	return retval;
 }

+
+
 PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
 			      const char **argv)
 {
--

-- 
1.6.0.6
Bastien Nocera | 9 Mar 2009 16:58
Favicon

Re: [fprintd][PATCH] Support for password prompt while finger scanning

On Mon, 2009-03-09 at 14:00 +0100, Jaroslav Barton wrote:
> Next try:
> 
> Multiple pam stackes will be better, but for some applications
>   it is unusable or like sci-fi at this moment (some console
>   applications like su, sudo, etc.). Password prompt should be
>   enabled by "askpass" pam module parameter in service configuration
>   file. Password is stored in PAM_AUTHTOK for next pam module.
>   Multiple pam stack aware should use service configuration file
>   without askpass option.

Using uinput for this is still out of the question, so it won't get
merged, as previously discussed.

Cheers
Jose Miguel Goncalves | 9 Mar 2009 18:54
Picon

Integrating a closed-source driver

Hi,

I have a fingerprint device which has a closed-source driver.
With that binary driver I can successfully scan fingerprints and save 
them has a bitmap image.
I would like to know if it's possible (and how) to use this driver with 
fprint to be able to enroll and verify fingerprints.

Regards,
José Gonçalves
Pavel Herrmann | 9 Mar 2009 20:57
Picon

Re: Integrating a closed-source driver

Hi,
AFAIK libfprint was designed so that the drivers would need to be open-source, 
and without any image-reader driver (which could be used in combination with 
binary drivers). this was probably made this way to prevent fingerprint-
scanner producers from getting the advantage of linux community without giving 
anything (namely open drivers) back.
but you should probably wait for answer from Daniel, he wrote this and should 
give you the most precise information
Pavel

On Monday 09 March 2009 18:54:56 Jose Miguel Goncalves wrote:
> Hi,
>
> I have a fingerprint device which has a closed-source driver.
> With that binary driver I can successfully scan fingerprints and save
> them has a bitmap image.
> I would like to know if it's possible (and how) to use this driver with
> fprint to be able to enroll and verify fingerprints.
>
> Regards,
> José Gonçalves
>
> _______________________________________________
> fprint mailing list
> fprint <at> reactivated.net
> http://lists.reactivated.net/mailman/listinfo/fprint
adelita@CarvajalOnline.com | 9 Mar 2009 20:57
Favicon

Non-swipe Fingerprint Reader recommendation

Hi,

Can anybody recommend a fingerprint reader that works with fprint and is 
similar to the "Microsoft Fingerprint Reader" in terms of how the 
fingerprint is scanned, I don't want a scanner that requires swiping the 
finger.

Thanks in advance for your time,

Adelita
Daniel Drake | 10 Mar 2009 15:22
Favicon

Re: Integrating a closed-source driver

Jose Miguel Goncalves wrote:
> Yes, the driver runs in Linux and I could sniff the USB bus, the problem 
> is that I'm on a tight schedule and I was thinking in a quicker 
> approach, i.e., to wrap the libfprint driver methods to use my binary 
> (closed source) driver.

I don't think it's feasible technically, especially under the new 
asynchronous model of libfprint. I am pretty sure there would be 
licensing conflicts too. It would not be shipped in an official release, 
sorry.

Daniel
Alain M. | 10 Mar 2009 16:58
Picon
Favicon

Re: Integrating a closed-source driver


Daniel Drake escreveu:
> Jose Miguel Goncalves wrote:
>> Yes, the driver runs in Linux and I could sniff the USB bus, the problem 
>> is that I'm on a tight schedule and I was thinking in a quicker 
>> approach, i.e., to wrap the libfprint driver methods to use my binary 
>> (closed source) driver.
> 
> I don't think it's feasible technically, especially under the new 
> asynchronous model of libfprint. I am pretty sure there would be 
> licensing conflicts too. It would not be shipped in an official release, 
> sorry.

Do you nean that if I hava an image (generic, 500dpi, 8bits, gray scale) 
I cannot feed it to fprint????

That is a very much desired approach and opens the door to many 
possibilities. I would even say that this is a *must* :(

I am new here, but I am expecting to start a project with fprint soon, 
using an embedded Linux on ARM9. (This is also a way of being ok with 
copyrights and export laws)

Alain

Gmane