[fprint] [fprintd][PATCH] Support for password prompt while finger scanning
Jaroslav Barton
djaara at djaara.net
Mon Mar 9 13:00:59 GMT 2009
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
@@ -3,12 +3,13 @@ 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
@@ -14,6 +14,10 @@ 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
@@ -1,6 +1,7 @@
/*
* 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.
@@ -25,16 +26,16 @@ 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
@@ -0,0 +1,117 @@
+/*
+ * 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
@@ -0,0 +1,38 @@
+/*
+ * 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
@@ -2,6 +2,7 @@
* 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.
@@ -26,17 +27,20 @@
#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
@@ -50,13 +54,47 @@
} \
}
+#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;
@@ -74,25 +112,15 @@ 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)
@@ -200,17 +228,6 @@ 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;
@@ -229,20 +246,33 @@ 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)
@@ -251,23 +281,43 @@ 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);
@@ -296,7 +346,7 @@ 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;
@@ -305,6 +355,13 @@ 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)) {
@@ -313,6 +370,9 @@ 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;
}
@@ -321,19 +381,27 @@ 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;
@@ -369,33 +437,101 @@ 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,
@@ -403,36 +539,81 @@ 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
More information about the fprint
mailing list